Udostępnij za pośrednictwem


Making Dependency Injection your friend

 

Imagine…You are happily in the final steps of your project, and suddenly the client “decides” that the logging mechanism that you development in your Solution does not met the requirements of their processes, instead of the good old Enterprise Library Logging that you had used, they want that the Solution use a different mechanism that they use in other Solutions…Wouldn’t be nice if we can just say to our Solution to use a new Logging Mechanism without changing our code.

Imagine….You need the replicate your Production Environment in a VPC Image to promote some kind of Test or demonstration, after you start installing your Platform in the Virtual Environment you realize you going to need a DC Server, an Active directory, etc…Wouldn’t be nice if you can just say to your solution to use a new Authentication Mechanism instead of the Integrated one used in our Production Environment, and doing that without have to change our code.

Been there? Sure you had. I know I had. And the solution for this, is Dependency Injection, I’m telling you.

So let’s talk a little bit about this DI thing.

In nowadays everyone recognize the benefits of using an approach that promotes two things:

· Loose coupling between Components

· High level of cohesion of the Solution.

One of the mechanisms that are a potential champion in this area is the Dependency Injection paradigm. With this kind of Model the teams are able to promote aggressive decoupling and independence of the components of their Solutions

Of course we all are aware of things like: Spring .NET, CASTLE Windsor or even the classic Struture Map.

But we all also know that this are lightweight dependency Injection Containers that can give us great help in assembling our components from different projects in a application with great levels of cohesion in run time, also they are very useful in promoting the reusability of the code that the Teams producing, but still give us little power and flexibility to satisfy our real needs.

The Dependency Injection, in the other side, is one of those mechanisms that give us the power to create all the stuff we need in a very comprehensive and easy way. You can find a very old but still very actual introduction to the Dependency Injection technique by Martin Fowler in this article, go read (a classic).

In an essence the DI gives to the developers the ability to decouple related but distinct operations in client applications. This implies that it is easier for the developer to focus on create smaller building blocks that potentiate the degrees of reusability of their code.

However this kind of technique, or even the related Inversion of Control (IOC) approach, are not very widely adopted because the developers tend to think that this approaches are only useful on an context of Unit Testing.

Typically, if the developers have not adopt a TDD approach, they will not take time to considering this Design Alternatives, so they are far from getting the big advantages that are inherent to the DI and IOC.

So, what advantages I am talking about? We can discuss a lot around this issue, but I think I can enumerate at least the following, without getting wrong:

· Dynamic and pluggable Architectures

· Dependency Injection

· Dynamic and pluggable architectures

· Consistent (and by design) Extensibility

· Interception allowance

· Lifecycle Management

· Independent component evolution

· Decoupled Architectures

· Separation of concerns

· Business Logic versus Infrastructure Logic

Regarding the possible approaches to use the DI, depending what you need, you can use the following:

· Constructor Injection

 

· Setter Injection

 

· Interface Injection

 

 

 

In one of the Projects that I had been involved I can say that the use of the DI clearly save our day. Let’s say we had a solution ready to be delivered and suddenly in last minute the client decides that they don’t want anymore that we use the logging mechanisms from the Enterprise Library that we had been using in our solution, instead they want the use an internal mechanism they use in all their applications, sounds familiar?

Well don’t worry, here comes the DI to save the day, because we had use DI exhaustively in our Project, inclusive in the Logging Classes, we are able to change the Logger without need to change any line of our code.

Let’s see that, in just a brief overview:

We had use for the Logging mechanisms of our solution the DI Constructor approach, so, we had configured the dependency in our Logger something like the follow:

public class LoggerSvc()

{

                public void MyMethod1(Logger logDef)

                {

                               IDependencyContainer container = DependencyContainerProvider.GetContainer();

                              container.Register<ILoggerWriter, MyLoggerWriter>();

                               LoggerManager manager = container.Resolve<LoggerManager>();

                               manager.AddLogger(logDef);

                }

               

                //other code goes here

}

DefaultMappingAttribute

[DefaultMapping(typeof(MyLoggerWriter))]

public interface ILoggerWriter()

{ //interface code goes here}

public class LoggerSvc()

{

                public void MyMethod1(Logger logDef)

                {

                               IDependencyContainer container = DependencyContainerProvider.GetContainer();

                               TransactionManager manager = container.Resolve<LoggerManager>();

                               manager.AddLogger(logDef);

                }

                //other code goes here

}

After this, we had to implement the Constructor Injection:

public class LoggerManager()

{

                public LoggerManager

                (ILoggerWriter writer)

                {

                               this.LoggerWriter = writer;

                }

                public ILoggerWriter LoggerWriter {get; private set;}

               

                //other code goes here

}

Et voila, when we receive the new “requirement” from the client we had the capability to just promote the use of the new Logger by a simple change in our configuration file by using the Policy Injection Application Block (PIA).

For those who are not aware of this “wonder”, I strongly recommend that you go find out more about, but I can say that it is a powerful mechanism that gives us a common behavior injection mechanism and a clear extensibility point for every one of our solutions:

In a visual way it is something like this.

Finally some tips to implement a good DI approach

· Make all classes inherent from a single base, so that they can be easily managed by container;

· Make the framework as simple as possible, put main functionalities into plug-ins, so that sub-components can be easily replaced;

· Use the injection methods and service locator together; (e.g., Use constructor injection to inject service locator)

So, farewell and remember, SGIP!

JPauloP