Last week Jimmy Bogard posted why he believed the dependency injection pattern appearing in the NerdDinner application was flawed. I want to take the opportunity to say the pattern in NerdDinner really isn't that bad and I want to explain why. Before I go on I will say that I entirely agree with Jimmy's thoughts on the pattern for my own code and you won't find the anti-pattern Jimmy describes in my code.
So why isn't the pattern that bad? I see Dependency Injection as generally having at least two major benefits:
The pattern under scrutiny in NerdDinner accounts for testability, of which I am a firm believer in, but lacks in flexibility. If I had to rank the two items above, I would rank testability above flexibility. Testability is a core tenet on which I stand for with the code I write.
To recap here is the code from Jimmy's post:
1: public class SearchController : Controller {
2:
3: IDinnerRepository dinnerRepository;
4:
5: //
6: // Dependency Injection enabled constructors
7:
8: public SearchController()
9: : this(new DinnerRepository()) {
10: }
11:
12: public SearchController(IDinnerRepository repository) {
13: dinnerRepository = repository;
14: }
The first constructor, when called, "news up" a new DinnerRepository() and passes it into another constructor on the same object which is generally considered "poor man's dependency injection". This pattern is considered bad (this an anti-pattern) because some, of which Jimmy is one, believe you shouldn't "new up" new objects this way, choosing instead to allow a container to inject the primal dependency. The problem I have with this view is that for many applications a container is overkill. Many applications will only have one concrete implementation of a class, so in many ways this constructor and the object creation could be seen as providing a sensible default to the application, allowing the consumer to create an instance without worry about what else the object needs.
Absolutely correct, I don't write my code this way. Why? I already have a container set up in my application and so to not use it would be foolish. We also have a complex application/domain, sometimes with multiple concrete implementations of an interface.
I used to write code this way using this pattern. Really. I don't feel ashamed to say so. The reason we adopted the dependency injection (DI) pattern in the application where this overloaded constructor "anti-pattern" was used was because DI allows for testability, and as I have previously mentioned, this "anti-pattern" doesn't stand in the way of testing.
I further believe that most developers must make a certain progression on their own. We can write and share our experiences but in the end every developer out there must some day be convinced in their own time. \They must come to the conclusion on their own, like I did, that using "poor man's injection" will work for many many scenarios but will get ugly fast in others.
For simple applications/domain, typically not much (again, my opinion). For complex domain the issue you will run into is maintainability/flexibility. If you get to a complex domain and you use the pattern from NerdDinner you will someday have:
1: public SearchController(new SearchService(new SearchLogService(new Logger()), new SearchRepository(new SessionBuilder()), new SearchResultFormatter(new FormatProvider())))
Ugly for sure. This is why it's generally considered an "Anti-Pattern". However for applications where the controller is the service-layer and controllers therefore use repositories, I would not be too concerned with the use of this pattern.
While Jimmy did a great job fixing the application, you first have to believe the application needed fixing. Which of course, depends on context. How big/complex is your application/domain? Jimmy's application/domain is sufficiently complex as is mine, yours may not be. For NerdDinner I believe the pattern was a suitable choice.
This blog contains the thoughts and discoveries of Tim Barcz, a technologist with a interests in computer programming technologies.