DI: Can a stable dependency have a volatile dependency?

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?

1

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.

2

Context

The distinction between stable and volatile dependencies was an attempt on my part to provide guidance about ‘what to inject and what not to inject.’ It was based on my understanding of the problem space as of late 2000s.

It turns out that it’s closely related to the Stable Dependencies Principle, which I believe I only later read about. When you arrive at a conclusion independently of other people who arrive at a similar conclusion, it strengthens the point. (This is, on the other hand, no guarantee: for centuries, people thought that the sun revolves around the Earth.)

Dependency Inversion

I’m not sure I explicitly stated it in the book, but dependencies are transitive. Thus, if you have, as you put it, a stable dependency that depends on a volatile dependency, that dependency graph contains volatility.

This is, however, the composition view. This describes how the graph looks at run time. As KeithS points out, according to the Liskov Substitution Principle, your StableDependency class should be able to accept any (correct) implementation of IVolatileDependency2. That implementation may or may not have to be volatile.

One problem that Dependency Injection attempts to address is the Stable Dependencies Principle. What if some fairly stable code depends on some other code that’ll change at a higher frequency?

The way we address this dilemma is by applying the Dependency Inversion Principle, by saying that abstractions shouldn’t depend on details, but rather that details should depend on abstractions.

So a consumer of a volatile dependency doesn’t depend on the implementation detail; it depends on the abstraction (e.g. IVolatileDependency2). The abstraction should remain stable, while the implementation can remain volatile.

The implementation, likewise, depends on the abstraction, because it depends on the interface definition (e.g. IVolatileDependency2) in order to implement it. Again, the implementation detail depends on a stable contract.

I understand that you named the interfaces and classes in the OP as you did to illustrate a point, but in a real code base, the whole point is that you shouldn’t care about what’s behind an abstraction.

Specifics

Apart from all the theorising, the remaining question is: should you inject StableDependency into MyClass, or rather its constituent elements. I don’t think that there’s one single right answer to that question, but I recently answered a similar question on my blog. The discussion there doesn’t involve make-believe types like StableDependency, MyClass, etc. so perhaps it’ll be more illuminating.

Referential Transparency

I no longer think about ‘what to inject, and what not to inject’ in terms of stable and volatile dependencies. Instead, I distinguish between pure functions and impure actions.

An impure action is anything that has non-deterministic behaviour or involves side effects, so essentially all file I/O, database reads and writes, random number generation, sending of emails, web service calls, system clock usage, etc.

As that partial list suggests, there’s quite a bit of overlap between impure actions and volatile dependencies.

The interpretation, though, differs. Referential transparency has stronger implications for transitivity, because any function that invokes an impure action must itself be impure. This has implications for architecture, but also for Dependency Injection. Essentially, if you inject an impure action, the dependent component is also impure.

I don’t think that viewpoint is what you’re ultimately asking about, but I wonder if you somehow got them mixed up, since the transitivity effect is much more pronounced in this alternative perspective.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật