Tame your software dependencies with the Microsoft Unity Application Block and Common Service Library Locator in your application code. Source codes provided including the unit tests.
Hi, in this post I will explain and demonstrate how we can strive for a loosely coupled design for our dependencies in the software application with Dependency Injection (DI) container and the Common Service Locator Library from Microsoft Pattern & Practices group. In other word, we try to achieve loosely coupled design in such as way that the application interacts with the different components it relies on through the component interfaces instead of the component's concrete dependencies with the help of DI container. So, the architecture will be much more flexible and open to change without having most of the codes need to be modified.
Most of us familiar with the layered approach and may have been practicing it all these while in the software development. The idea of layered approach is to logically separate the application components into groups that represent distinct roles and functionality with the aims to make the application more maintainable and easier to scale out when necessary to improve performance. Generally, an application consists of number of basic layers. The most common is the three layer approach which comprises the data layer, business layer and the UI layer. In this simple three layering scheme, the UI layer talks to the business layer and the business layer talks to the data layer in a one way direction from top to bottom. The same goes to the dependencies that flow the same way with each of the layer being aware of the layer beneath it but the current layer is unaware of the layer above it.
This is a good design technique as it allows the factoring of responsibilities and separation of concerns into multiple layers of a software application. However, if we see it from the testability perspective, how testable of each of this layer when in isolation? We know that there is a direct coupling of upper layer to the lower layer. Take for e.g. the business layer is intimately dependent on the data layer. If the business layer is taking a direct concrete references to the data layer, then it would be impossible to test the business layer in isolation because all the real dependencies of the data layer such as the database and other states have to be ready at the time when the business layer needed to be unit tested. This incurs high cost for practicing Test Driven Development as all the concrete dependencies need to be in a known state such as the database initial data and time spent in running the tests would be significant as accessing external resources such as file and database takes times. Since we are using the real dependencies during the tests, then those failing tests are hard to be diagnosed as the failure in the business layer may be related to the problem in the lower data layer. Diagnosing the root cause is time-consuming and tedious as testing the business layer alone has to take care of the errors and problems in the lower data layer. Other problem would be the ease of maintenance of the codes. Changes in the lower layer will force the immediate layer above it to be modified in some way due to the implicit and explicit dependencies that the upper layer has on the lower layer.
Dependency Injection Container Comes to Rescue
Based on what I have described, building loosely coupled application/components requires more than just separating the application into its distinctive layer of responsibilities. It requires the effort of programming against the abstraction. Another term for this is programming to contract. The high level component doesn’t depend on the low level component but its abstraction or interface instead. However, programming to contract does not solve the problem completely as the concrete implementations of the dependencies need to be instantiated somewhere in the application. One of the ideal solutions is to make use of the Dependency Injection container to return the concrete implementations. The container centralizes the objects creation for the dependencies and also provides the flexibility to switch among different implementations of the same interface/abstraction without having the client code knowing about it.
Generally, if you read up the definition of Dependency Injection from Wikipedia, it is process of supplying an external dependency to a software component. It is a specific form of Inversion of Control, IoC where the process of getting the dependency is the process being inverted. Hypothetically, a business component makes calls to a service component by instantiating an object of the callee component and it is the responsibility of the business component to take care of the whole life cycle of the instance. With dependency injection, this process is handled by a dependency provider which is also referred to as container in the current trend. The business component will no longer create the instance of the callee but requests it from the container. The container returns a reference to the implementation to the business component so that it can accomplish its task. The container itself knows how to orchestrate the dependent and manage its life cycle. All the boilerplate codes of handling all these are being built into the container itself and the consumer simply request the references. As in most of the containers available nowadays, the types mapping registration is done in the container initialization during run time or through some form of XML file configuration during the design time. Other mean will be through some form of attribute decoration for the type member that need dependency injection. So, the container knows what and how to return the reference to the implementation instance of the requested/target type.
Factory vs DI Container
At this juncture, I would like make clear that the factory pattern/class has been very popular and it is a common way to provide dependency injection in the component or class to achieve loose coupling. Through this way, the instance of the dependent type or class is constructed and initialized in the factory class and injected into the calling component or class. The factory class is rarely reused outside of the creating component. Its purpose merely serve the dependencies needs of a few related creating components within a particular business domain or a family of calling classes in the class hierarchy. In other words, the factory is a specialized class to serve particular dependency needs. On the other hand, container provides a layer of abstraction to house components. Within the container, it has generic factory classes to instantiate instances of classes.
In fact, container works at a broader level and does more than what factory pattern can offer besides instantiating objects, resolving and injecting dependencies. It allows us to define what type of dependencies to inject into each target type and configure the instantiation mode for each type. For e.g. should a new instance of a type be created every time it is requested or the same instance is reused (singleton). Container itself also provides lifetime management. It keeps references to the objects it instantiates to manage their life cycles, or keep the objects alive for reuse later such as the singleton object. Type or class that is configured to return a new instance whenever a request is made, container will forget their references so that the garbage collector can reclaim their storage. So, Dependency Injection Container/Framework just make it easier.
From other point of view, factory pattern requires the developers themselves to write code for constructing, initializing and wiring up the dependencies. All the factory classes has to come into the picture of the class API design. Whereas, with the Dependency Injection Container/Framework, we outsource all these responsibilities to a third party component which is separated from our application code. With the high level of configurability of DI container, any types of instances can be easily created and configured. The configuration information is placed in a central place for easy modification later. Through the file based configuration, dependencies change can be made without having to recompile the factories.
Anywhere, in a small application with a few types of instance to be created, factory pattern works very well and it is simple to understand. Besides, it provides a great learning experience in designing factory classes in a software application.
Microsoft Unity DI Container (Unity Application Block 1.2) & Common Service Locator Library 1.0
This post is not about what is Dependency Injection in depth. It is about putting it into action with the Unity DI Container. I will demonstrate how to apply the Dependency Injection and Common Service Locator Library to the sample code that I have prepared for my previous post on Repository, Specification, Unit of Work, Persistence Ignorance POCO with Microsoft ADO.NET Entity Framework Beta 2 and Using the Mocking Framework - Moq. The sample application comes with this post won’t be must different from those found in the posts mentioned just now. In fact it is the same sample application with some modifications to demonstrate the purpose of this post. Anyway, prior to completing this post, I have refactored the sample project code and the changes are briefly explained at this post; Repository, Specification, Unit of Work, Persistence Ignorance POCO with Microsoft. ADO.NET Entity Framework 4.0 Beta 2 – Code Update.
You will see the use of DI container, in more specific, the Microsoft Unity DI Container 1.2 to inject life (dependencies) in to the sample application. There are lots of DI containers out there available for .NET platform. To name a few, Castle Windsor, Spring.NET framework, StructureMap, Linfu, Seasar2 Container and etc. Some of these containers have been in existence for over a period of time and well ahead of the Microsoft Unity DI container. I choose Unity container because I have used it before and I am more familiar with Enterprise Library from Microsoft’s pattern and practices group, compared to other open source enterprise frameworks. Other than that, Unity Application Block has a comprehensive documentation and quick starts for beginner.
Besides, you will also see the container abstraction library, Common Service Locator Library being put into use to provide container abstraction. So, you can have your application code to switch among different type of DI container without having it to tie to the specific container. It provides you a way to evaluate each of the available container in term of its performance and how it best fits your application needs before you finally decide the specific container you really want to use. It also fulfills the need of your customer who wants to use different DI container on request. So, it will spare you the need of having to modify your application code to take a different dependency on a particular DI implementation. By relying on the Common Service Locator Library, we can make our application container agnostic. Of course, it will create one more level of indirection which is sometimes not desirable. There are Service Locator and Dependency Injection pattern out there to help us to build loosely coupled components. There are lot of article out there provide full coverage of both. If you are interested to know further and want to contrast Service Locator to Dependency Injection, you can follow Martin Fowler's article here. Without much ado, let have a look at the Solution View of the Dependency Injection & Common Service Locator Sample Application in Figure 1.0.
Figure 1.0 Solution View of the Dependency Injection & Common Service Locator Sample Application
You will also notice the UnityServiceLocator C# source file in the solution view. UnityServiceLocator class is the adapter for UnityContainer to the IServiceLocator interface in the Common Service Locator Library. This adapter class is necessary as in our sample application, we no longer code against the specific container interface for Unity, IUnityContainer. Instead, we will code against IServiceLocator interface to access the Unity container's services indirectly. This avoid hard references to the IUnityContainer and it will allow us to switch different DI containers without changing the code in our sample application as long as we have the adapter for each of the different DI container.
As usual, the CustomerRepositoryMoqTest contain the unit tests to test the business layer types, CustomerRepository but with its dependency being mocked by the Moq mocking object framework. The CustomerRepositoryTest uses the real dependency for the unit tests. Moq is used to replace the real dependency with the mock object that mimics the behavior of the real dependency and enable us to carry unit tests even without the presence of the real dependency. This is only possible if the higher level API interact with the lower level dependencies via interfaces instead of the concrete or hard references.
Figure 1.2 Solution View for the Factory Classes that are Removed
Figure 1.3 - ObjectContextFactory Create ObjectContext Instance in the AspNetObjectContextLifetimeManager
Figure 1.4 - ServiceLocator Create ObjectContext Instance in the AspNetObjectSourceLifetimeManager