To constructor or to property dependency?

Us, devel­op­ers, are a bit like that comic strip (from always great xkcd):

Crazy Straws

We can end­lessly debate over tabs ver­sus spaces (don't even get me started), whether to use optional semi­colon or not, and other seem­ingly irrel­e­vant top­ics. We can have heated, informed debates with a lot of merit, or (much more often) not very con­struc­tive exchanges of opinions.

I men­tion that to explic­itly point out, while this post might be per­ceived as one of such dis­cus­sions, the goal of it is not to be a flame­war bait, but to share some experience.

So hav­ing said that, let's cut to the chase.

Depen­den­cies, mechan­ics and semantics

Writ­ing soft­ware in an object ori­ented lan­guage, like C#, fol­low­ing estab­lished prac­tices (SOLID etc) we tend to end up with many types, con­cen­trated on doing one thing, and del­e­gat­ing the rest to others.

Let's take an arti­fi­cial exam­ple of a class that is sup­posed to han­dle sce­nario where a user moved and we need to update their address.

public class UserService: IUserService
{
   // some other members

   public void UserMoved(UserMovedCommand command)
   {
      var user = session.Get<User>(command.UserId);

      logger.Info("Updating address for user {0} from {1} to {2}", user.Id, user.Address, command.Address);

      user.UpdateAddress(command.Address);

      bus.Publish(new UserAddressUpdated(user.Id, user.Address));
   }
}

There are four lines of code in this method, and three dif­fer­ent depen­den­cies are in use: ses­sion, log­ger and bus. As an author of this code, you have a few options of sup­ply­ing those depen­den­cies, two of which that we're going to con­cen­trate on (and by far the most pop­u­lar) are con­struc­tor depen­den­cies and prop­erty dependencies.

Tra­di­tional school of thought

Tra­di­tional approach to that prob­lem among C# devel­op­ers goes some­thing like this:

Use con­struc­tor for required depen­den­cies and prop­er­ties for optional dependencies.

This option is by far the most pop­u­lar and I used to fol­low it myself for a long time. Recently how­ever, at first uncon­sciously, I moved away from it.

While in the­ory it's a neat, arbi­trary rule that's easy to fol­low, in prac­tice I found it is based on a flawed premise. The premise is this:

By look­ing at the class' con­struc­tor and prop­er­ties you will be able to eas­ily see the min­i­mal set of required depen­den­cies (those that go into the con­struc­tor) and optional set that can be sup­plied, but the class doesn't require them (those are exposed as properties).

Fol­low­ing the rule we might build our class like that:

public class UserService: IUserService
{
   // some other members

   public UserService(ISession session, IBus bus)
   {
      //the obvious
   }

   public ILogger Logger {get; set;}
}

This assumes that ses­sion and bus are required and log­ger is not (usu­ally it would be ini­tialised to some sort of NullLogger).

In prac­tice I noticed a few things that make use­ful­ness of this rule questionable:

  • It ignores con­struc­tor over­loads. If I have another con­struc­tor that takes just ses­sion does it mean bus is an optional or manda­tory depen­dency? Even with­out over­load­ing, in C# 4 or later, I can default my con­struc­tor para­me­ters to null. Does it make them required or mandatory?
  • It ignores the fact that in real­ity I very rarely, if ever, have really optional depen­den­cies. Notice the first code sam­ple assumes all of its depen­den­cies, includ­ing log­ger, are not null. If it was truly optional, I should prob­a­bly pro­tect myself from Null­Ref­er­ence­Ex­cep­tions, and in the process com­pletely destroy read­abil­ity of the method, allow­ing it to grow in size for no real benefit.
  • It ignores the fact that I will almost never con­struct instances of those classes myself, del­e­gat­ing this task to my IoC con­tainer. Most mature IoC con­tain­ers are able to han­dle con­struc­tor over­loads and defaulted con­struc­tor para­me­ters, as well as mak­ing prop­er­ties required, ren­der­ing the argu­ment about required ver­sus optional moot.

Another, more prac­ti­cal rule, is this:

Use con­struc­tor for not-changing depen­den­cies and prop­er­ties for ones that can change dur­ing object's lifetime.

In other words, ses­sion and bus would end up being pri­vate read­only fields — the C# com­piler would enforce that once we set them (option­ally val­i­dat­ing them first) the fields in the con­struc­tor, we are guar­an­teed to be deal­ing with the same (cor­rect, not null) objects ever after. On the other hand, Log­ger is up in the air, since tech­ni­cally at any point in time some­one can swap it for a dif­fer­ent instance, or set it to null. There­fore, what usu­ally log­i­cally fol­lows from there, is that prop­erty depen­den­cies should be avoided and every­thing should go through the constructor.

I used to be the fol­lower of this rule until quite recently, but then it does have its flaws as well.

  • It leads to some nasty code in sub­classes where the base class has depen­den­cies. One exam­ple I saw recently was a WPF view model base class with depen­dency on dis­patcher. Because of that every sin­gle (and there were many) view model inher­it­ing from it, needed to have a con­struc­tor declared that takes dis­patcher and passes it up to the base con­struc­tor. Now imag­ine what hap­pens when you find you need event aggre­ga­tor in every view model. You will need to alter every sin­gle view model class you have to add that, and that's a refac­tor­ing ReSharper will not aid you with.
  • It trusts the com­piler more than devel­op­ers. Just because a set­ter is pub­lic, doesn't mean the devel­op­ers will write code set­ting it to some ran­dom val­ues all over the place. It is all a mat­ter of con­ven­tions used in your par­tic­u­lar team. On the team I'm cur­rently work­ing with the rule that every­body knows and fol­lows is we do not use prop­er­ties, even set­table ones, to reas­sign depen­den­cies, we're using meth­ods for that. There­fore, based on the assump­tion that devel­op­ers can be trusted, when read­ing the code and see­ing a prop­erty I know it won't be used to change state, so read­abil­ity and imme­di­ate under­stand­ing of the code does not suffer.

In real­ity, I don't actu­ally think the cur­rent one, or few of my last projects had even a require­ment to swap ser­vice depen­den­cies. Gen­er­ally you will direct your depen­dency graphs from more to less volatile objects (that is object will depend on objects with equal or longer lifes­pan). In few cases where that's not the case the depen­den­cies would be pulled from a fac­tory, and used only within the scope of a sin­gle method, there­fore not being avail­able to the out­side world. The only sce­nario where a long-lived depen­dency would be swapped that I can think of, is some sort of failover or circuit-breaker, but then again, that would be likely dealt with inter­nally, inside the component.

So, look­ing back at the code I tend to write, all depen­den­cies tend to be manda­tory, and all of them tend to not change after the object has been created.

What then?

This robs the afore­men­tioned approaches from their adver­tised ben­e­fits. As such I tend to draw the divi­sion along dif­fer­ent lines. It does work for me quite well so far, and in my mind, offers a few ben­e­fits. The rule I fol­low these days can be explained as follows:

Use con­struc­tor for application-level depen­den­cies and prop­er­ties for infra­struc­ture or inte­gra­tion dependencies.

In other words, the depen­den­cies that are part of the essence of what the type is doing go into the con­struc­tor, and depen­den­cies that are part of the "back­ground" go via properties.

Using our exam­ple from before, with this approach the ses­sion would come via con­struc­tor. It is part of the essence of what the class is doing, being used to obtain the very user whose address infor­ma­tion we want to update. Log­ging and pub­lish­ing the infor­ma­tion onto the bus are some­what less essen­tial to the task, being more of an infra­struc­ture con­cerns, there­fore bus and log­ger would be exposed as properties.

  • This approach clearly puts dis­tinc­tion between what's essen­tial, busi­ness logic, and what is book­keep­ing. Prop­er­ties and fields have dif­fer­ent nam­ing con­ven­tions, and (espe­cially with ReSharper's 'Color iden­ti­fiers' option) with my code colour­ing scheme have sig­nif­i­cantly dif­fer­ent colours. This makes is much eas­ier to find what really is impor­tant in code.
  • Given the infra­struc­ture level depen­den­cies tend to be pushed up to base classes (like in the View­Model exam­ple with Dis­patcher and Even­tAg­gre­ga­tor) the inher­i­tors end up being leaner and more readable.

In clos­ing

So there you have it. It may be less pure, but trades purity for read­abil­ity and reduces amount of boil­er­plate code, and that's a trade­off I am happy to make.


Posted 09-05-2012 2:32 PM by Krzysztof Koźmic
Filed under: ,

[Advertisement]

Comments

Bryan wrote re: To constructor or to property dependency?
on 09-05-2012 5:47 PM

Doesn't putting the session in the constructor still leave you having to touch every subclass in the case of overloaded constructors?

Harry M wrote re: To constructor or to property dependency?
on 09-05-2012 7:51 PM

Debating this kind of thing make me think of not seeing the wood for the trees.

Both approaches work, are fairly maintainable, and with some non-brittle tests (perhaps using an AutoMocker) you can rewrite a class from one style to the other at a whim.

There are probably more important battles to fight in your organisation than this one, although if not, that's great!

And just to confound things, I will throw my keys into the pot - NEVER inject onto properties! :)

Shane C wrote re: To constructor or to property dependency?
on 09-06-2012 9:08 AM

I agree with Harry M on not using properties.. why confuse the issue? A dependency is a dependency.. end of story.

Chris Marisic wrote re: To constructor or to property dependency?
on 09-07-2012 12:27 PM

I'm with the commenters, everything is a constructor parameter.

If a dependency is optional the constructor overloads will express an overload that does not require it.

I'm also a big fan of using lots of optional arguments and setting defaults to null, and then inside the constructor checking if the argument is null and if so initialize a suitable default.

Richard Dingwall wrote re: To constructor or to property dependency?
on 09-11-2012 5:50 PM

Property dependencies aka half-initialized objects, and having to null check my logger every time I call it. Sounds GREAT.

Seriously. Constructor parameters for lifetime scope and method parameters for short-lived. That is the only way to inject dependencies to an object.

Ramon Smits wrote re: To constructor or to property dependency?
on 09-18-2012 3:54 PM

I like constructor dependency injection as it helps to change code fast without missing any clients. Using property injection can result in having clients that 'forget' to inject a value resulting in broken unit tests. I rather have compile time issues then at runtime.

However, I think that the data session is infrastructural as wel. It is generic, it has transactions that are managed somewhere else. Having something to send messages to is IMHO the same thing.

Chris Brandsma wrote re: To constructor or to property dependency?
on 09-26-2012 8:35 PM

It is also important to remember the anti-pattern of DI: Too many constructor parameters!  

Now, I like IoCs and DP. But there is an issue that can happen with large projects over time where DI is too freely used, you end up with classes where there are a TON of constructor parameters, and each parameter can have a ton of its own parameters.  Suddenly you find you are injecting 100s of classes to create a web page.

DI makes it very easy to loose track of what is going on and inject subtle problems when overused.

Then throw on auto scanning, and now your project takes extra seconds (lots of them) to load.

Dathan wrote re: To constructor or to property dependency?
on 09-27-2012 1:58 PM

We have a simple rule: whenever possible, objects should be fully initialized and ready to use as soon as the constructor returns -- implying, of course, that all required dependencies are injected via the constructor.  It does sometimes cause problems (e.g., complicating constructors in derived classes), but if you're in the happy position of being able to depend on interfaces instead of classes, most of those problems are easily mitigated through composition instead of inheritance.

Eber Irigoyen wrote re: To constructor or to property dependency?
on 10-02-2012 11:46 AM

I don't necessarily agree with your approach, I'm just curious how this is working for you, especially if you have quite a few other developers on your team

Neil Kidd wrote re: To constructor or to property dependency?
on 10-23-2012 6:49 PM

I'm with Dathan on this. After construction any object should be "good to go" and immutable. Optional parameters can be taken care of in a constructor overload that chains, with safe defaults (think null object pattern), to one single constructor. Properties are evil! except in DTO's. If you require different parameters, maybe you are missing an object?

Regards,

Neil

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)