It's been my opinion for a while that anyone who can look at their own code from six months ago and not see any areas for improvement has begun to fossilise. Part of being a professional software developer is constant improvement (also known as a constant race to stay relevant). As a case study, my usage of Dependency Injection.
My first significant use of DI was a couple of years ago using Spring.NET. This usage was characterised by a few properties:
- Exclusive use of setter injection
- No mocks and overly complex hand-coded stubs
- Use of the DI container in the unit tests
- Many instances of querying the DI container directly rather than having dependencies injected
- Configuration that required every dependency to be explicitly defined
This was better that what had come before but it had a lot of downsides. In particular the configuration was large and overly complex and hence tedious to maintain, and the lack of proper mocks and stubs meant the unit tests tended to not really be testing single units.
Subsequently I began to use mocks a lot more (Rhino Mocks, highly recommended). This solved a lot of the issues with the unit tests, making them less fragile and eliminating database interaction in the tests (this is evil. Just don't do it).
From there I moved to a project using Castle Windsor. This introduced a different philosophy of constructor injection and auto-wiring. These were concepts of which I was initially skeptical (always a good default position). However from observing and working with the system I've seen the advantages. Constructor injection allows a clear definition of the dependencies of a class to be obtained unambiguously from the code (or via reflection). Auto-wiring is often criticised by people who feel that it is too much like magic and doesn't make the construction of the software obvious. I've found that in practice provided you understand the principals of auto-wiring behaviour this is rarely an issue and the resulting configuration is significantly simpler and requires less maintenance.
Most recently I've been using StructureMap. Here I've been taking advantage of its fluent interface and convention over configuration capabilities. This has removed the requirement to inform the DI container of each class to be managed while still allowing individual configuration as required. I've estimated that on my current project over 95% of the DI configuration could be replaced by a some relatively simple logic telling the DI container which assemblies to obtain classes from (unfortunately such a change is not feasible for other reasons).
From here I plan (once I've further explored StructureMap) to look at other alternatives such as the Managed Extensibility Framework. At the very least looking at alternatives can make you better understand the technologies you already use. I'm hoping that, as in the past, I find new ways of looking at things that enable me to continue to improve the solutions that I provide to clients.