tags:

views:

119

answers:

4

Hi y'all,

I was wondering, I recently read an article that spoke of the ills of using the singleton pattern siting the disadvantage of global variable occurrence and rightly that the singleton violates alot of the rules we learn from OOP school, single responsibility principle, programming to interfaces and abstract classes and not to concrete classes... all that good stuff. I was wondering how then do you work with like database connection class where you want just one connection to your DB and one object of your DB floating around. The author spoke of Dependency Injection principle which to my mind stands well with the Dependency Inversion rule. How do I know and control what object gets passed around as a dependency other than the fact that I created the class and expect everyone using it play nice and make sure they are using the right resource?!

+1  A: 

Dependency injection containers (even one you develop yourself, which isn't an entirely uncommon practice) are generally very configurable. What you'd do in that scenario is configure it such that any request for the interface that implementation, well, implements would be satisfied with that implementation. Even if it's a singleton.

For example, take a look at the Logger singleton being used here: http://www.pnpguidance.net/News/StructureMapTutorialDependencyInjectionIoCNET.aspx

David
+2  A: 

For those who criticize the singleton pattern, based on SRP, here is an opposing view. Also, I've found that dependency injection containers can create as many problems as they solve. That said, I'm using a promising compromise, as covered in another post.

Brent Arias
+1  A: 

Don't take what you read anywhere as absolute truth. Read it, understand it and then you can see when it's best to apply certain things. In your case, why wouldn't you want to create a static singleton?

Serg
Because there might be better abstractions. Often times a more flexible approach will make the code much easier to refactor or reuse. For example, there are reasons you would *want* to be able to run multiple versions of your code in parallel, with separate connections to the DB, even if you usually want to keep only one connection. A simple singleton won't give you the flexibility to change the design to support that scenario.
Merlyn Morgan-Graham
Merlyn I agree with you. I am looking at doing some stuff and what you just said has sparked ideas in my head. Nice going!
Eagletrophy
+2  A: 

Edit: This answer assumes you are using a dependency injection container, either one you wrote yourself, or one you got from a library. If not, then use a DI container :)

How do I know and control what object gets passed around as a dependency other than the fact that I created the class and expect everyone using it play nice and make sure they are using the right resource?!

By contract

The oral contract - You write a design spec that says "thou shalt not instantiate this class directly" and "thou shalt not pass around any object you got from the dependency injection container. Pass the container if you have to".

The compiler contract - You give them a dependency injection container, and they grab the instance out of it, by abstract interface. If you want only a single instance to be used, you can supply them a named instance, which they extract with both the name, and the interface.

ISomething instance = serviceLocator.ResolveInstance<ISomething>(
  "TheInstanceImSupposedToUse");

You can also make all your concrete classes private/internal/what-have-you, and only provide them an abstract interface to operate against. This will prevent them from instantiating the classes themselves.

// This can only be instantiated by you, but can be used by them via ISomething
private class ConcreteSomething : ISomething
{
    // ...
}

By code review

You make group-wide coding and design standards that are fair, and make sure they are understood by everyone within the group.

You use a source control mechanism, and require code reviews before they check in. You read over their code for what they link to, what headers they include, what objects they instantiate, and what instances they are passing around.

If they violate your rules during code reviews, you don't let them check in until they fix their code. Optionally, for repeat offenders, you make them pay you a dollar, you make them buy you lunch, or you hire a different contractor to replace them. Whatever works well within your group :)

Merlyn Morgan-Graham