So, I gave the first of my talks about Design Patterns last week. I concentrated my attention on the Command and Singleton patterns. My colleagues weren’t particularly interested in the Command pattern, but my remarks on the Singleton pattern raised a lot of interest. For many, it was the first time they’d really heard someone come out and say that static methods were a bad idea. It was ironic that Max Pool was blogging about the uselessness of evangelism on modern programming techniques while I was having a positive experience doing exactly that.
The thing is, everyone is used to a certain way of doing things. They know that using static methods and shared state take time. They know that they always end up with dependency soup, but it’s usually thought that this is just what programs are like. To a certain extent, it’s always going to be hard to eliminate externalities, but it’s a lot easier than most people expect.
Constructor Injection, equally, is really easy to explain: you just pass things into the constructor. Developers who write a lot of tests can instantly see the advantages of doing things that way.
None of this makes it easy to be the guy in the room saying the exact opposite of what most people expect, but it’s very rewarding when it comes off.
Here’s some talking points:
- Business requirements change, they usually change in a way you’re not expecting.
- If you only need one instance, creating it in the Main method and passing it into the objects that need it is much more flexible than using a Singleton pattern.
- If something is public, it will get used, you can’t create a static method and then say that people shouldn’t use it. They will, and it’ll be your fault.
- Constructor Injection is a very low cost thing to implement when you’re writing new code.
- Refactoring old code to use it is much harder, but that reflects the refactoring challenges inherent in Singleton-style code.
- If you’re passing a lot of objects down a function chain, that’s a code smell. Chances are that the “group of objects” is a good candidate for a class. Once you understand what that class is actually called, you’re on your way to a better design.
- Passing lots of objects in constructor chains isn’t as easy to deal with. Dependency injection containers make this problem manageable. (Amongst other things…)
- Evaluating all of your dependencies up front can lead to problems with circular dependencies. Usually the best way to deal with this is to redesign objects so that they don’t have circular dependencies, but property injection can help in ugly cases.
- Ironically, developers often spend a lot of time trying to think of the best way to make object interact, how to load configuration settings and so on. Constructor Injection makes this simple: it’s always in the constructor.
- Constructor Injection isn’t quite the end of the story. If you actually need more than one object, we need to start talking about abstract factories.
The sooner you start using constructor injection, the sooner refactoring your code will stop feeling like playing Jenga.