views:

1717

answers:

14

Hi, I hope this isn't a duplicate. I did a search but there are a lot of dependency injection posts and I couldn't find any needles in the haystack.

So here's my question. I'm refactoring a class and adding a new dependency to it. The class is currently taking its existing dependencies in the constructor. So for consistency, I add the parameter to the constructor.

Of course, there are a few subclasses plus even more for unit tests, so now I am playing the game of going around altering all the constructors to match, and it's taking ages.

It makes me think that using properties with setters is a better way of getting dependencies. I don't think injected dependencies should be part of the interface to constructing an instance of a class. You add a dependency and now all your users (subclasses and anyone instantiating you directly) suddenly know about it. That feels like a break of encapsulation.

But this doesn't seem to be the pattern with the existing code here so I am looking to find out what the general consensus is, pros + cons of constructors vs properties. Is using property setters better?

EDIT: Wow, lots of useful answers in a really short time. Looks like the consensus is for the constructor.

+1  A: 

It's largely a matter of personal taste. Personally I tend to prefer the setter injection, because I believe it gives you more flexibility in the way that you can substitute implementations at runtime. Furthermore, constructors with a lot of arguments are not clean in my opinion, and the arguments provided in a constructor should be limited to non-optional arguments.

As long as the classes interface (API) is clear in what it needs to perform its task, you're good.

nkr1pt
please specify why you are downvoting?
nkr1pt
Yes, constructors with a lot of arguments are bad. That's why you refactor classes with lots of constructor parameters :-).
sleske
@nkr1pt: Most people (me included) agree that setter injection is bad if it allows you to create a class that fail at runtime if the injection is not done. I believe someone therefore objected to your statement of it being personal taste.
sleske
+3  A: 

I prefer constructor injection because it helps "enforce" a class's dependency requirements. If it's in the c'tor, a consumer has to set the objects to get the app to compile. If you use setter injection they may not know they have a problem until run time - and depending on the object, it might be late in run time.

I still use setter injection from time to time when the injected object maybe needs a bunch of work itself, like initialization.

ctacke
+13  A: 

Martin Fowler discusses options in Constructor versus Setter Injection

Update: I tried to look at dependency injection or location from perspective of contract and dependencies lifetime in my blog post Inject or locate dependencies?

Dzmitry Huba
+3  A: 

If you have large number of optional dependencies (which is already a smell) then probably setter injection is the way to go. Constructor injection better reveals your dependencies though.

epitka
+21  A: 

Well, it depends :-).

If the class cannot do its job w/o the dependency, then add it to the constructor. The class needs the new dependency, so you want your change to break things. Also, creating a class that is not fully initialized ("two-step construction") is an anti-pattern (IMHO).

If you the class can work w/o the dependency, a setter is fine.

sleske
I think it's many cases it is preferable to use the Null Object pattern and stick with requiring the references on the constructor. This avoids all null checking and the increased cyclomatic complexity.
Mark Lindell
@Mark: Good point. However, the question was about adding a dependency to an existing class. Then keeping a no-arg constructor allows for backward compatibility.
sleske
What about when the dependency is needed to function, but a default injection of that dependency will usually suffice. Then should that dependency be "overridable" by property or a constructor overload?
Patrick Szalapski
@Patrick: By "the class cannot do its job w/o the dependency", I meant that there is no reasonable default (e.g. the class requires a DB connection). In your situation, both would work. I'd still usually opt for the constructor approach, because it reduces complexity (what if e.g. the setter is called twice)?
sleske
+5  A: 

Of course, putting on the constructor means that you can validate all at once. If you assign things into read-only fields then you have some guarantees about your object's dependencies right from construction time.

It is a real pain adding new dependencies, but at least this way the compiler keeps complaining until it's correct. Which is a good thing, I think.

Joe
+2  A: 

I perfer constructor injection, because this seems most logical. Its like saying my class requires these dependencies to do its job. If its an optional dependency then properties seem reasonable.

I also use property injection for setting things that the container does not have a references to such as an ASP.NET View on a presenter created using the container.

I dont think it breaks encapsulation. The inner workings should remain internal and the dependencies deal with a different concern.

David Kiff
Thanks for your answer. It certainly seems the constructor is the popular answer.However I do think it breaks encapsulation in some way. Pre-dependency injection, the class would declare and instantiate any concrete types it needed to do its job. With DI, subclasses (and any manual instantiators) now know what tools a base class is using. You add a new dependency and now you have to chain the instance through from all the subclasses, even if they don't need to use the dependency themselves.
Niall Connaughton
Just wrote a nice long answer and lost it due to an exception on this site!! :( In summary, the baseclass is usually used to re-use logic. This logic could quite easily go into the subclass... so you could think of the baseclass and subclass = one concern, that is dependent on multiple external objects, that do different jobs. The fact you have dependencies, does not mean you need to expose anything you would have previously kept private.
David Kiff
+4  A: 

I personally prefer the Extract and Override "pattern" over injecting dependencies in the constructor, largely for the reason outlined in your question. You can set the properties as virtual and then override the implementation in a derived testable class.

Russ Cam
+2  A: 

I think that constructor injection are better if the injection is mandatory. If this adds too many constructors, consider using factories instead of constructors.

The setter injection is nice if the injection is optional, or if you want to change it halfway trough. I generally don't like setters, but it's a matter of taste.

Philippe
I'd argue that usually changing injection halfway through is bad style (because you are adding hidden state to your object). But no rule w/o exception of course...
sleske
Yep, that why I said I didn't like setter too much... I like the constructor approach as then it cannot be changed.
Philippe
+6  A: 

The users of a class are supposed to know about the dependencies of a given class. If I had a class that, for example, connected to a database, and didn't provide a means to inject a persistence layer dependency, a user would never know that a connection to the database would have to be available. However, if I alter the constructor I let the users know that there is a dependency on the persistence layer.

Also, to prevent yourself from having to alter every use of the old constructor, simply apply constructor chaining as a temporary bridge between the old and new constructor.

public class ClassExample
{
    public ClassExample(IDependencyOne dependencyOne, IDependencyTwo dependencyTwo)
        : this (dependnecyOne, dependencyTwo, new DependnecyThreeConcreteImpl())
    { }

    public ClassExample(IDependencyOne dependencyOne, IDependencyTwo dependencyTwo, IDependencyThree dependencyThree)
    {
        // Set the properties here.
    }
}

One of the points of dependency injection is to reveal what dependencies the class has. If the class has too many dependencies, then it may be time for some refactoring to take place: Does every method of the class use all the dependencies? If not, then that's a good starting point to see where the class could be split up.

Secret Agent Man
Of course constructor chaining only works if there is a reasonable default value for the new parameter. But otherwise you cannot avoid breaking things anyway...
sleske
Usually, you would use whatever you were using in the method prior to dependency injection as the default parameter. Ideally, this would make the new constructor addition a clean refactoring, as the behavior of the class would not change.
Secret Agent Man
I take your point about resource managing dependencies like database connections. I think the problem in my case is that the class I'm adding a dependency to has several subclasses. In an IOC container world where the property would be set by the container, using the setter would at least relieve the pressure on constructor interface duplication between all the subclasses.
Niall Connaughton
A: 

One option that might be worth considering is composing complex multiple-dependencies out of simple single dependencies. That is, define extra classes for compound dependencies. This makes things a little easier WRT constructor injection - fewer parameters per call - while still maintaining the must-supply-all-dependencies-to-instantiate thing.

Of course it makes most sense if there's some kind of logical grouping of dependencies, so the compound is more than an arbitrary aggregate, and it makes most sense if there are multiple dependents for a single compound dependency - but the parameter block "pattern" has been around for a long time, and most of those that I've seen have been pretty arbitrary.

Personally, though, I'm more a fan of using methods/property-setters to specify dependencies, options etc. The call names help describe what is going on. It's a good idea to provide example this-is-how-to-set-it-up snippets, though, and make sure the dependent class does enough error checks. You might want to use a finite state model for the setup.

Steve314
A: 

I vote for property injection. Those in favor of constructor injection usually do so in order to "protect developers from themselves".

zvolkov
A: 

In part it depends on your current code base - a nice discussion here: http://www.vsj.co.uk/articles/display.asp?id=805

Dave
A: 

I recently ran into a situation where I had multiple dependencies in a class, but only one of the dependencies was necessarily going to change in each implementation. Since the data access and error logging dependencies would likely only be changed for testing purposes, I added optional parameters for those dependencies and provided default implementations of those dependencies in my constructor code. In this way, the class maintains its default behavior unless overridden by the consumer of the class.

Using optional parameters can only be accomplished in frameworks that support them, such as .NET 4 (for both C# and VB.NET, though VB.NET has always had them). Of course, you can accomplish similar functionality by simply using a property that can be reassigned by the consumer of your class, but you don't get the advantage of immutability provided by having a private interface object assigned to a parameter of the constructor.

All of this being said, if you are introducing a new dependency that must be provided by every consumer, you're going to have to refactor your constructor and all code that consumers your class. My suggestions above really only apply if you have the luxury of being able to provide a default implementation for all of your current code but still provide the ability to override the default implementation if necessary.

Ben McCormack