LP on .NET

April 3, 2013

Dependency Injection – A Compromise

Filed under: .NET,C#,Software Development — Larry Parker @ 9:38 pm

I’ve blogged a lot over the past few years about writing testable code, as well as using stubs and mocking frameworks in unit tests to test all that testable code.

The common denominator to all this has been dependency injection.  To quote myself from a previous post:

Dependency injection is a pattern whereby dependencies are supplied (or injected) into a system. … in a nutshell you simply hand the dependencies (typically as interfaces) to your class or method which then works with them in an abstract way.

I also said this in another post:

It seems that I can’t say enough about dependency injection these days. It gives me an incredible amount of control over my code in the form of testability and modularity.

I’ve been using this pattern for a couple of years now.  It really has given me an incredible amount of control over my code, especially in the form of testability.  I love writing unit tests that can mock out some or all of the injected interfaces.  It really makes testing simple.

But incredible control in the form of modularity?  When’s the last time I swapped out my persistence layer with a new module that provided a new and improved persistence layer?  Or swapped out a configuration manager with a better one by simply editing an app.config setting that pointed to another assembly?

Let me think.

Still thinking…

Hmmm.  Haven’t done it.  Except perhaps as a proof-of-concept and maybe a demo or two.

As for “simply handing the dependencies” to my classes, it’s simple in theory.  Until you end up with a constructor that takes a whole bunch of parameters and you end up writing code like this just to create an instance of your class:

   1: WidgetProvisioningManager widgetProvisioningManager = new WidgetProvisioningManager(

   2:     new WidgetProvisioningDataManager(systemContext),

   3:     new WidgetDbProvisioningDataManager(databaseServer),

   4:     o => new OrganizationDataManager(o),

   5:     (u, c) => new EmployeeDataManager(u, c),

   6:     emailServerConfiguration,

   7:     (m, t) => QueueManager.Enqueue(m, t, null),

   8:     executionContext.LogWriter,

   9:     new WidgetMembershipManager());

So much for the simple part.  Try showing this to another developer who needs to actually work with your WidgetProvisioningManager class.  “Yes Joe, to create a new instance of my WidgetProvisioningManager class, you do need to pass in seven parameters to the constructor.”  (pause)  “You got a problem with that?”

There are other options, like inversion of control containers such as StructureMap.  I’ve looked at these a bit but have not been able to warm up to them.  Too much up-front configuration, and your application becomes too dependent on them at runtime (whereas something like Moq never leaves the lab).

So now what?

Without getting into all of the heated discussions about which pattern is best (and I have encountered many both on the web and in the office), may I suggest a compromise.

Make your class’s public constructor as simple as possible, but no simpler (Einstein would love your constructor).  And developers who use your classes will not complain that they don’t have to pass in seven parameters.

As for testability, dependency injection still plays a part, as do mocking frameworks.  But make the constructor with the seven parameters internal so nobody else has to see it (and make your assembly’s internals available only to your unit test assemblies).

Using this approach, we can have our cake and eat it too.  Our WidgetProvisioningManager class now has two constructors.  The easy one marked as public for everyone to use:

   1: public WidgetProvisioningManager()

   2: {

   3:     _widgetProvisioningDataManager = new WidgetProvisioningDataManager(AppRuntime.SystemContext);

   4:     _widgetDbProvisioningDataManager = new WidgetDbProvisioningDataManager(AppRuntime.DatabaseServer);

   5:     _organizationDataManagerFactory = o => new OrganizationDataManager(o);

   6:     _employeeDataManagerFactory = (u, c) => new EmployeeDataManager(u, c);

   7:     _emailServerConfiguration = AppRuntime.EmailServerConfiguration;

   8:     _enqueueFunc = (m, t) => QueueManager.Enqueue(m, t, null);

   9:     _logWriter = AppRuntime.LogWriter;

  10:     _widgetMembershipManager =  new WidgetMembershipManager();

  11: }

And the DI constructor marked as internal for your unit tests:

   1: internal WidgetProvisioningManager(IWidgetProvisioningDataManager widgetProvisioningDataManager = null,

   2:     WidgetDbProvisioningDataManager widgetDbProvisioningDataManager = null,

   3:     Func<IContext, IOrganizationDataManager> organizationDataManagerFactory = null,

   4:     Func<IContext, EmailServerConfiguration, IEmployeeDataManager> employeeDataManagerFactory = null,

   5:     EmailServerConfiguration emailServerConfiguration = null,

   6:     Func<Int32, String, Int64> enqueueFunc = null,

   7:     ILogWriter logWriter = null,

   8:     IWidgetMembershipManager widgetMembershipManager = null)

   9: {

  10:     _widgetProvisioningDataManager = widgetProvisioningDataManager;

  11:     _widgetDbProvisioningDataManager = widgetDbProvisioningDataManager;

  12:     _organizationDataManagerFactory = organizationDataManagerFactory;

  13:     _employeeDataManagerFactory = employeeDataManagerFactory;

  14:     _emailServerConfiguration = emailServerConfiguration;

  15:     _enqueueFunc = enqueueFunc;

  16:     _logWriter = logWriter;

  17:     _widgetMembershipManager = widgetMembershipManager;

  18: }

Note that both constructors save things to private fields (the ones with the underscore prefix), and the rest of the class just uses interfaces and doesn’t care where they came from.

The public constructor creates concrete classes so consumers of the class can just use your class without any headaches.

The internal constructor is the one with all the (optional) parameters, so you can still go to town using mocking frameworks for your unit tests.

So that’s my dependency injection compromise.

Hope this helps.

Advertisements

2 Comments »

  1. Amen, and amen! Some other variations of that same idea that I’ve seen:
    * Have the public constructor pass in the parameters to the internal one with constructor chaining.
    * If the public constructor needs to do some manipulation of the input parameters, turn it into a factory method instead.
    * If a singleton is needed (on those rare occassions!), the static “accessor” property can function like the factory method the first time the object is called on.

    Comment by Wayne — April 4, 2013 @ 9:42 am | Reply

  2. Unfortunately you are approaching the problem from an incorrect point of view. The problem is not that your constructors are complicated but that your class is doing too much. Once you have a class that has more than a certain number of dependencies, for me the threshold is five, it means that your class is doing too much, surely it is breaking the Single Responsibility Principle, and it should be broken down in smaller, more manageable pieces.

    On the other hand, this kind of constructor chaining is now recognized as a dependency injection anti-pattern. If you google “bastard injection” you will find some references about it.

    Try to keep your classes small with as few dependencies as possible and you will realize your maintenance efforts will be even smaller.

    Regards.

    Comment by sergeromero — April 16, 2013 @ 3:59 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: