Tuesday, February 26, 2008

Dependency Injection

I have released an early version of a Dependency injection framework I am developing. Yes another one!

NDependencyInjection is being used in a real application and is under heavy development. I intend it to be very opinionated. It will make writing apps the way I write them easy.

First decision: Only support constructor injection.


This decision is not without it's complications. Not least of which is 'what do you do about objects that refer to each-other?'. Luckly I have a solution to this problem. The injection framework in-fact automatically solves these loops.

Second decision: Applications should be built in layers.


When assembling the complex network of simple objects that make up a good design. You group them into sub-assemblies and these into bigger assemblies until you have your final application.

Within the Application there are objects that you only have one instance of. These are by definition Singletons.

Within the sub-assemblies you get classes that act as Singletons, but only within that scope. You may have several instances in your application, but the individual sub-system only has one, and all references to that type refer to the same instance. In all respects this is a ScopedSingleton.

The framework supports Scopes and Singletons.
More on this later.

Anyway.. for now.. you can get at an early release version from NDependencyInjection.

5 comments:

Anonymous said...

"Within the Application there are objects that you only have one instance of. These are by definition Singletons."

No they're not. A Singleton is a class that you can't create more instances of, not one that you simply don't make more instances of. Be very wary of changing the class design just for convenience.

Nigel said...

Thanks for the feedback Marty.

I don't understand "Be very wary of changing the class design just for convenience". Please can you expand on this?

Here is what I am thinking...

Given the assumption that you divide your code into 'definition of classes to use' and 'wiring' [which is the intent of my dependency injection framework]...

Then the decision to use a class as a service that there is only one instance of is a wiring decision.

If you then define in your writing so that you _can't_ create second instance of the class it is then a Singleton.

Can you agree with that? Even if the class in question has no explicit code to enforce a Singleton nature.

Assuming you can go with me on that (feel free to disagree)...

That just leaves the concept of Scopes having Singletons.

I agree that here I am stretching the term Singleton. However, if we can agree that the 'definition of the wiring' is what makes a class a singleton, not the class itself, then extending the concept to say that within a limited scope a class is a Singleton, then that is where I am coming from.

Within the Scope every class that wants access to the specific resource or service has to use the same instance. Singularity is enforced by the wiring.

To stretch the definition in this way involves seeing each subsystem as its own module with it's own wiring.

Imagine you wrote a Plugin-API that exposed a 'ResourceRegistry' class. As far as that plugin is concerned there is only once instance of this registry class and it accessed as a singleton. To your plugin it is a Singleton.

However in your application code a plugin is one of many, and you have separate ResourceRegistry instances for each plugin. In this context it is not a Singleton.

Does this make sense?

Anonymous said...

Your comment was kinda long winded, so I'll just try coming at the issue from a different angle to try and explain my point of view.

The Singleton pattern enforces the rule that only one instance of a class can get created. It usually allows access to that class by calling something like MyClass.getInstance(). When you do that, you and up with lots of methods like this:

void foo() {
...
MyClass.getInstance();
...
}

This is awful to test. Much better to inject the dependency like this:

void foo(MyClass variableName) {
}

The decision to only create one instance in your application is different to the design decision about whether another instance *can* exist. I might want to create ten different ResourceRegistry objects in my test suite, but only one in my application.

My point is: Don't make things Singletons just because you only want one in your application. You'll end up with code that is hard to test, because people *will* end up calling the getInstance() method somewhere in the bowels of your code.

Nigel said...

I thought I had explained that I have no Singleton classes at all. The decision to use a class as a singleton is a wiring decision.

Obviously I didn't explain clearly enough.

Ronald Widha said...

Just looking at your code samples,
is this a fair enough assumption on how a typical MVC app would be constructed if I were to use the framework?

public class ShowBananaController
{
private ISystemDefinition definition;

// default constructor
public ShowBananaController()
{
definition = new SystemDefinition();
definition.HasInstance(new Banana(1)).Provides<IBanana>();
definition.HasInstance(new WebFormView("showBanana")).Provides<IViewEngine>();
this(definition);
}

// dependency injection constructor: most likely used for testing
public ShowBananaController(ISystemDefinition _definition)
{
definition = _definition;
}

// the resource consumer function
public void PrintName()
{
IBanana b = definition.Get<IBanana>();
IViewEngine view = definition.Get<IViewEngine>();
view.Print(b.Name)
}
}


p.s more questions later if you say yes (-:

GitHub Projects