Injecting Some Control Into Legacy Code
I’ve been talking a lot recently on how one might get started using techniques such as TDD and Inversion of Control in their daily code, particularly for those of us who spend most of our time dealing with “Legacy” codebases. Some of these ideas are tough to grasp until you’ve had a chance to try them out. So here’s another take on how to get started.
How would we deal with adding or modifying some functionality in a Legacy application, while moving forward with some better practices?
In the Beginning…
We have a big lump of Legacy Code, a formless void of hard to manage complexity. We need to modify some functionality in the MyConsumerClass, that DealsWithThings and can DoStuff. Let’s modify MyConsumerClass in a way that allows us to decouple what MyConsumerClass does from the rest of the Legacy Code. This will be the starting point for making this application cleaner.
Build in Layers
The class we’re working on relies on functionality from The Cloud for doing something with text. (Maybe we’re showing the latest sales figures from the corporate SharePoint portal - the specifics aren’t very important…)
We want to be able to modify the behavior of the text provider without needing sweeping changes everywhere else. So how do we separate these pieces?
First, let’s change MyConsumerClass to access the text via an interface instead of creating specific instances directly from the cloud. MyConsumerClass is going to ask “something” for the appropriate concrete instance - instead of making decisions about what that concrete instance should be. This “something” is our Inversion of Control Container, and it will know how to pick the right ITextProvider implementation, create one of them, and return the reference to MyConsumerClass for use.
The type that the IoC returns might be a thin wrapper on top of the “real” functionality in the Legacy Cloud. It could also be configured to inject an easily testable provider instead. So, we have broken the direct dependency of MyConsumerClass to the Legacy Code Cloud.
The Result
So, what do we have? Our ConsumerClass, and the TextProvider, can now be worked with (and tested) as individual units. They can be maintained without having to get too deep into that Legacy Cloud. We now have the beginnings of infrastructure, the InversionOfControlContainer, which we can leverage against other maintenance tasks. The Legacy Cloud itself is now just that much more smaller - we have walled off a small section of order from the chaos of the rest of the cloud.
Conclusion
After you have spent some time working on breaking dependencies, you’ll find that code without dependencies is easier to maintain. Your classes get less complex, so they are easier to test and verify as correct. Because of fewer dependencies, changes to one part of the application won’t cause problems for another part.






