A while back a colleague of mine sent me a link to a Wikipedia article about a design pattern called Inversion of Control (IoC). He also told me about a framework called Spring.NET that is apparently very popular (as well as other similar frameworks that extend the .NET Framework in an attempt to make building enterprise level applications easier). In reading up on Spring.NET, I also came across a methodology called Aspect Oriented Programming (AOP) and a technique called Dependency Injection (DI). After getting to fully know these design patterns, techniques and methodologies (oh my!), I feel like I've been living under a rock not knowing about them.
Let's talk about Dependency Injection first. This is a specific form of IoC. This technique allows the user application to swap out functional pieces of the application thus changing how the application runs. Instead of a software component creating or retrieving it's own dependencies, it asks the user layer for it's dependencies.
Quick example: I have an AccountManager class in a banking program. The AccountManager class interacts with the persistent data via the BankDb class. Pretty typical. The AccountManager class depends on the BankDb class and knows how to instantiate this class on it's own. However, if we employ DI, we would modify the AccountManager class to take in a IBankDb class on instantiation. Then when we instantiate the AccountManager class in the interface layer, we can supply the BankDb (which implements IBankDb) and the AccountManager no longer needs to know how to create that instance on it's own because it will be spoon-fed this object.
But wait! We're not done. Now we employ the help of the Spring.NET framework to do the DI for us. We can now define in XML configuration files (such as the application configuration file) what class should be passed in to the AccountManager class when we instantiate the AccountManager. Instead of hard-coding a BankDb object into the constructor, we retrieve the IBankDb object to use from the Spring.NET IoC container. The Spring.NET IoC container is configured using the XML configuration files.
Ok, so what exactly do we have?
We have an AccountManager who doesn't care what object it uses to interact with the persistent data as long as it's an object that implements IBankDb. And we also have an application that is able to dynamically load which object to pass into the AccountManager via the application configuration file.
How does this benefit us?
Well first, you can now fully unit test the AccountManager class (as long as IBankDb is it's only dependency). You can use a framework such as Rhino Mocks or NMock to mock the IBankDb in order to help you fully unit test the AccountManager class.
Second, what if the person that needs to write the actual BankDb hasn't written it yet and you're not able to write it yourself because you don't have the appropriate access to write that code? Well, you can write your own mock BankDb class that does enough for you to test your interface and when the actual BankDb class is created, you simply change a configuration file instead of your code.
Another example of the second benefit is in a web service. Say you now have a web service that uses the AccountManager class. You now want to create a development set of web services that allow consumers of the web services to develop their applications without hitting the live data but acts the same in all other aspects. You can use the same exact AccountManager class, but now supply it a different BankDb class using just a configuration file change. (By the way, Spring.NET has a way of dynamically generating .NET web services, so you don't even need to actually create another .asmx file - it's all done through the web.config).
Can't we accomplish the same thing by swapping the BankDb object via code?
Yes. Using Spring.NET to do your DI vs. code is really your call. This call is roughly equivalent to choosing C# over VB.NET, or Pepsi over Coca Cola. There are arguments for either choice but at the end of the day, they both accomplish the same thing. The only advice I can offer there is to go with what your comfortable with. Spring.NET configuration files do have their headaches involved, but being able to change the functionality of the application without recompiling your application is pretty cool and sometimes handy.
Another example before I let you go. I recently developed some web services. I made three projects: The web service project, a .NET library and a Windows application to test the web service. I relied on Spring.NET to do all of my DI. The web services consume local services (code run directly from the library - not Windows services) to accomplish their tasks. The tester application is written such that by commenting out one line and un-commenting another in the application configuration file, I can switch the tester application between using the production web services, using the development web services and using the local services without recompiling the application. When the Windows app is using the local services, it is using the same exact Spring.NET configuration files that the web services do (thus injecting the dependencies the exact same way the web services would). So I can test the local services and work out the bugs, then switch over to the web services (confident that the local services will work the same for them as it did for the Windows app) and do a great deal less testing on the web services.
If you've never looked at IoC, DI or Spring.NET (or equivalent frameworks), I encourage you to do so. There can be a learning curve involved in figuring out when to and when not to use these, but I'm sure that you'll be able to figure out when those times are.
0 comments:
Post a Comment