From microsoft.com:

Notice that the controller class depends onย ProductRepository, and we are letting the controller create theย ProductRepositoryย instance. However, it's a bad idea to hard code the dependency in this way, for several reasons.

  • If you want to replaceย ProductRepositoryย with a different implementation, you also need to modify the controller class.
  • If theย ProductRepositoryย has dependencies, you must configure these inside the controller. For a large project with multiple controllers, your configuration code becomes scattered across your project.
  • It is hard to unit test, because the controller is hard-coded to query the database. For a unit test, you should use a mock or stub repository, which is not possible with the current design.
[emphasis mine - mfn]

You know, I've often wondered why dependency injection is so popular. It truly is just an inversion of control. The control concerns themselves don't change. It's another variation of "it's all zeroes and ones" where you rearrange some deck chairs to make things look new again.

That's not all bad. Cargo culting is much too popular a development mentality. At least rearranging deck chairs makes people look at their architecture closely with fresh eyes, though I fear the result is often trading one cult for another that has better marketing or community buy-in when the decision to join is made.

And I often get the answer highlighted in green when the discussion comes up: "But we have to have interfaces so that we can test it!" Um... not always true. There are other equivalent options. And because there are good ways to test that existed before DI, that's really not a good explaination for its adoption.

DI isn't free; it has a significant cost. It requires a good head rethread and a ton of boilerplate. Easier testing doesn't (again imo) explain its explosive popularity. (Though I'm very happy it's become the industry's party line to proclaim we value testing so much.)

But this line (highlighted in yellow earlier) from Microsoft actually explains the DI advantage:

If the ProductRepository has dependencies, you must configure these inside the controller. For a large project with multiple controllers, your configuration code becomes scattered across your project.

I really think that's it -- put another way, DI helps enable clean encapsulation that, in turn, fosters anonymous collaboration between coding teams.

If I have to learn how to spin up Foo and pass in all of its dependencies, I'm having to schlep around a lot of objects I may have never used before, much less contributed to. If I'm a single-person indie shop, the advantages of Dependency Injection are slim. But if I want to access Foo.NeatMethod without bothering to open the Foo box, well, I'd rather you put all of its dependencies in a row for me.

That's what DI does. It's a decent amount of extra work up front to save everyone down the line from being nickel and dimed -- or, when they're protected from having to learn a whole new domain, dollar and pounded.

This shows that DI's advantages clearly appeal to enterprises; DI is literally an enterprise architecture strategy, not to improve system load or because it's an inherently superior -- again, for a small team, the DI boilerplate might ultimately slow them down -- but because it can help enable a specific type of work, which is work by multiple teams and workers with very little knowledge transfer overlap.

Enterprise development is really a pretty fascinating study in cultural evolution.

Labels: ,