Why does dependency injection encourage collaboration to be exposed via constructors?

The general approach to DI that I see in answers like
So Singletons are bad, then what? encourages
business objects that collaborate with other objects to (a) not
directly create those instances and (b) have them passed in at
construction. I can understand (a), but not (b). This seems to occur
most often in response to overuse of Singletons. But why not just have
a modified approach to singleton:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class SingleInstance {
virtual foo();
virtual bar();
static SingleInstance getInstance() {
if(instance_ == null) {
instance_ = new SingleInstance();
}
return instance_;
}
void setMockInstance(SingleInstance s) {
assert(instance_ == null);
instance_ = s;
}
static SingleInstance instance_;
}
</code>
<code>class SingleInstance { virtual foo(); virtual bar(); static SingleInstance getInstance() { if(instance_ == null) { instance_ = new SingleInstance(); } return instance_; } void setMockInstance(SingleInstance s) { assert(instance_ == null); instance_ = s; } static SingleInstance instance_; } </code>
class SingleInstance {
  virtual foo();
  virtual bar();

  static SingleInstance getInstance() {
    if(instance_ == null) {
      instance_ = new SingleInstance();
    }
    return instance_;
  }

  void setMockInstance(SingleInstance s) {
    assert(instance_ == null);
    instance_ = s;
  }

  static SingleInstance instance_;
}

So now this is no longer a Singleton with a capital S (per Misko
Hevery) but in this case still enforces one instance. All code that
wants to access the single instance can still call S::getInstance()
without cluttering up their constructors by explicitly requiring the
instance to be passed in. The default can still be still lazily
initialized in the production code, but for test can still be mocked.

In the referenced answer the first benefit of DI is listed as:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>It makes the code easier to read; you can clearly understand from
the interfaces exactly what data the dependent classes depend on.
</code>
<code>It makes the code easier to read; you can clearly understand from the interfaces exactly what data the dependent classes depend on. </code>
It makes the code easier to read; you can clearly understand from
the interfaces exactly what data the dependent classes depend on.

But why is that not a violation of encapsulation? Do I really need to
know from the public interface everything that accesses the
SingleInstance/Database/etc?

Assume you have a Database and 30 TableGateway classes responsible
for CRUD operations on those tables. In the DI approach TableGateway
constructors would accept the Database on in its constructor. Then a
business logic class would accept the tables it collaborates with/uses:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class BusinessLogic {
BusinessLogic(Table1 t1, Table2 t2, Table3 t3);
void doBusiness() {
t1_.query(...);
t2_.insert(...);
t3_.update(...);
}
}
</code>
<code>class BusinessLogic { BusinessLogic(Table1 t1, Table2 t2, Table3 t3); void doBusiness() { t1_.query(...); t2_.insert(...); t3_.update(...); } } </code>
class BusinessLogic {
  BusinessLogic(Table1 t1, Table2 t2, Table3 t3);
  void doBusiness() {
    t1_.query(...);
    t2_.insert(...);
    t3_.update(...);
  }
}

How is that churn of explicit dependencies in the constructor
advisable?

2

Your modified approach to singleton is still a singleton, and has most of the drawbacks of a singleton:

  • It still introduces high coupling across the application – that is, if one day you want to refactor away from singleton, you will have a hard time doing it;
  • It still gives a way for any component to collaborate with the singleton – meaning that potentially, the singleton can communicate with any piece of the system – but if you go for any kind of layered architectural pattern (MVC, MVVM, 3-tier), then the singleton is a point that has to be controlled.

Encapsulation is related to the fact that an object exposes the operations it supports without requiring that clients know about its implementation – but when you invoke a constructor, the object does not exist yet. The constructor is an implementation detail of the object, equivalent to a static method. In other words, once the object is created, the constructor arguments are irrelevant to the operation of the object.

As for the “churn” of explicit dependencies, making the dependencies explicit is one of the goals of constructor injection. If you have too many, it is taken as a sign that a refactoring, or a reorganization, is in order. (E.g. group related tables into a logical group).

4

Static data (including singleton instances) is problematic for a number of reasons. It’s not thread-friendly. You have added a method to set the single instance to a mock instance. Presumably that is done to support unit testing. This will fail if tests are run in parallel and require different mocks for your Singleton. Worse, the tests will fail when run together but will pass when run separately.

Even without running tests in parallel, static data introduces a global state that is retained between tests. A test that depends on static data could pass reliably when run alone against the initial global state, but consistently fail if run after another test that modifies the global state.

For these reasons, mutable static data should be avoided. I have seen many more incorrect uses of mutable static data than correct uses.

3

The reason I give dependencies to constructors is:

  1. Most of the time the dependencies are required, so why not give them to the constructor
  2. Giving them to the object in an other way makes using them a bit more complex, since you have to make sure you have the dependency

Of course this doesn’t really count when you are using a framework that controls the dependency injection, because the framework will make sure all the dependencies are set before returning the requested object.

3

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