Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've recently been reading through Mark Seemann's Dependency Injection in .NET and have been attempting to apply some of what I've learned in a new project I'm working on, and I'm stumped on a particular scenario trying to determine what dependencies I should and should not inject. I've read several other questions on SO and elsewhere that discuss similar scenarios but in a roundabout manner, and I think I've narrowed the underlying conceptual question to that which is in the title:

Can a stable dependency have a volatile dependency? Put another way: If a stable dependency has a volatile dependency, is the stable dependency really stable?

A quick example:

public class MyClass
{
    private IVolatileDependency1 _one;
    private StableDependency _stable;

    public MyClass(IVolatileDependency1 one, IVolatileDependency2 two)
    {
        _one = one;
        _stable = new StableDependency(two)
    }
}

public class StableDependency
{
    private IVolatileDependency2 _two;

    public StableDependency(IVolatileDependency2 two)
    {
        _two = two;
    }
}

In this situation, MyClass has a stable dependency which I've chosen not to inject but instead instantiate internally and hold via composition. However, that stable dependency has a volatile dependency, which I'm injecting into MyClass and passing through to StableDependency's constructor.

For whatever reason, this smells a little bit to me. It's fairly straightforward in such a simple contrived example, but I can see things getting out of hand quickly in a more complicated real-world situation.

Is StableDependency really stable, or should I be composing/resolving it prior to constructing MyClass and injecting it from there? I really don't foresee StableDependency changing or being replaced by another implementation, but on the other hand the practice of passing dependencies down through parent classes to their children (parent/child in the composition sense) seems to expose the details of the children up through the parent, which would be a violation of the Law of Demeter.

EDIT: Changed VolatileDependency1 and VolatileDependency2 to interfaces to clarify that they are intended to be satisfied by multiple possible implementations (LSP-compatible).

EDIT 2: Thinking on this some more, and reading KeithS's answer and default.kramer's comment below, make me realize that maybe I shouldn't have named StableDependency as I did, because I don't think it's a dependency in the first place. It's not something I ever expect to have multiple implementations for; it's merely an implementation detail that MyClass uses composition to contain a StableDependency, so MyClass's knowledge of how to construct a StableDependency isn't a problem I don't think. The big question is, StableDependency does have a dependency on IVolatileDependency2, so how do I inject that dependency? Do I reason that for all intents and purposes MyClass has a dependency on IVolatileDependency2, and the fact that it just passes that dependency down to StableDependency is an implementation detail unrelated to DI?

share|improve this question
2  
I would definitely inject the StableDependency. I don't want to know how to construct one, I just want one. Plus, I wouldn't want to repeat the construction logic in other classes. –  default.kramer Aug 14 '12 at 17:16
add comment

1 Answer

up vote 5 down vote accepted

If the StableDependency can accept any VolatileDependency2 implementation without knowing the difference between any two of them (Liskov Substitution Principle), and you don't need to be able to change StableDependency, then your snippet is perfectly fine.

Now, the DI purists might say that there should be no "stable" dependencies. If one class A depends on another class B, there is always a chance that B will have to be replaced with a C:B and thus you are going to want the flexibility to inject B so that you do not have to recompile A to make this change. In your case, by declaring StableDependency, you are asserting that you will never need a BetterStableDependency. Right or wrong, who knows; if you're right then the implementation never changes, but if you're wrong then the tightly-coupled implementation requires changes in more places.

When you use an IoC framework to automate your DI, you usually end up registering every dependency with the IoC no matter how likely it is to change; you have it, why not use it? So, I'd go ahead and register StableDependency with the IoC container as an IMaybeStableDependency.

share|improve this answer
    
+1 for a very clear and level headed answer. –  maple_shaft Aug 14 '12 at 1:23
    
I would say that such purists are failing hard at YAGNI. If the dependency does not need two different implementations now, than it's interface is most likely to change before it does and you'll need to refactor anyway. –  Jan Hudec Aug 14 '12 at 12:49
    
A very good point; you can't close the system to all types of change, and a change to the interface IB of B before the introduction of a C:B or C:IB will require changing IB as well as A and B. But, it remains that tightly-coupled object instantiation violates the Open/Closed Principle. –  KeithS Aug 14 '12 at 21:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.