Why use the Enterprise Library Unity Application Block


Many times, I read tutorials on the internet where people (with great intentions) will share code on how to use new technology to make your life as a developer easier.

The good intention is there, and it reminds me a bit of being back in programming school where they would show you code and basically say: this is how you say “hello world”

The problem with this approach is while it teaches the student how to have a good understand of how to do certain things it does not necessarily show you WHY you should do one thing over another.

I have this problem in my head, a problem with the Unity Application Block in the Enterprise Library.

There are plenty of great tutorials on how to use Unity but I have yet to see one that explains good patterns on WHEN and WHY you should use it. When is it appropriate? What is an example of a real life situation where it could solve a problem. It’s almost like everyone explains how to drive a car but no one actually says that you could go in the taxi or delivery business. Once I know how to drive, I’ll ask myself: ok – great – now what? What do I do with this and when do I use it. Sometimes, it will be obvious and sometimes it won’t be. And it will be obvious to varying degrees based on some individuals as well. Other folks, while they need – won’t get it.

I’m going to mix a few different things here so that we can look at a real-life situation that Unity can help you with.

Before I start, please give this site a visit: http://www.pnpguidance.net/Category/Unity.aspx – I would not be able to explain anything about Unity without David Hayden’s excellent help.

O’Reilly published an excellent book called “Head First Design Patterns” (see link in references), if you don’t know what I mean by my next couple of terms – this is a great book to check out to learn their details.

Let’s not talk about Unity for a few paragraphs and talk about the Strategy Pattern. The basics of the strategy pattern is that you should delegate class behavior to a more specialized class that implements this behavior.

If you can’t pick up on the key advantage of this, it means that you can actually make classes/objects that don’t implement a fixed behavior and actually set this behavior at runtime.

When you design a class that implements that Strategy Pattern, you should actually create properties to store these behavior objects so that your class can invoke the methods/properties of those classes in it’s own methods/properties.

So instead of having the following:

public abstract class RobotTerminator
{
public abstract void FindTarget();
}

public class RobotTerminatorSarah : RobotTerminator
{
public override void FindTarget()
{
// find Sarah
}
}

public class RobotTerminatorJohn : RobotTerminator
{
public override void FindTarget()
{
// find John
}
}


You could instead have the following:



public interface ITargetFinder
{
void FindTarget();
}

public abstract class RobotTerminator
{
private ITargetFinder _targetAcquisition;

public RobotTerminator(ITargetFinder targetAcquisition)
{
this._targetAcquisition = targetAcquisition;
}

public void FindTarget()
{
this._targetAcquisition.FindTarget();
}
}

Do you notice the difference? First off, I’m no longer using inheritance. Why would I want to do that and repeat the code all the time? I am simplifying the RobotTerminator class and this way, I can make new target acquisition objects instead that will find my targets and allow John and Sarah’s nemesis to deal with them.

The principal advantage is that I don’t need to recompile all of my robots before I send them back in time with new targets and missions all the time. While  I will agree that the example below is over-simplified, it illustrates the point well. You don’t want to have to open up the Drone’s heads all the time to give them new mission parameters, especially not upload/recompile their Operating System (imagine having to stitch their heads all the time). In the old way, I would have to inherit the base abstract class into a new one and write code there. This makes for very inefficient machines (no wonder they rarely get their targets in the movies, too much custom programming and not enough testing).



With the new method, I can send custom behavior “on the fly” during runtime and have the O/S simply execute that behavior instead.



Ok, I think that we get the point of the Strategy Pattern and why it’s useful, now let’s raise the bar once again.



Enter the Unity framework, let’s take a look at the following code:



public interface ITargetFinder
{
void FindTarget();
}

public abstract class RobotTerminator
{
private ITargetFinder _targetAcquisition;

public RobotTerminator(ITargetFinder targetAcquisition)
{
this._targetAcquisition = targetAcquisition;
}

public void FindTarget()
{
this._targetAcquisition.FindTarget();
}
}



Our new code is much better, but there is still some level of strictness around it. Wouldn’t be great if we could simply alter the behavior of our machine not only at runtime but also through configuration? Right now, we have to pass an ITargetFinder interface (so we have to build a real object that implements this interface and send it over as a parameter). But we would have to write at least some code so that we could configure behavior at runtime for our machine. We don’t have to turn it off but we still have some degree of code to write in order to tell the system to alter the behavior.



Take a look at the following:



public interface ITargetFinder
{
void FindTarget();
}

public static class TargetFinderFactory
{
public static ITargetFinder GetTarget()
{
// get target through configuration
return null;
}
}

public abstract class RobotTerminator
{
private ITargetFinder _targetAcquisition;

public ITargetFinder targetAcquisition
{
get { return this._targetAcquisition; }
set { this._targetAcquisition = value; }
}

public RobotTerminator()
: this(TargetFinderFactory.GetTarget())
{ }

public RobotTerminator(ITargetFinder targetFinder)
{
this._targetAcquisition = targetFinder;
}

public void FindTarget()
{
this._targetAcquisition.FindTarget();
}



This is a bit more interesting. We now have a factory that will crank out targets like muffins, when our Robot comes online it will automatically get an assignment through the factory. The behavior can also be changed during runtime by simply changing the target finder of the object. We can even go as far as specifying a target immediately or having the default read the configuration file. Much better indeed.



This is much better, but Unity can make it even better, let’s take a look at it:



public interface ITargetFinder
{
void FindTarget();
}

public abstract class RobotTerminator
{
private ITargetFinder _targetAcquisition;

[Dependency]
public ITargetFinder targetAcquisition
{
get { return this._targetAcquisition; }
set { this._targetAcquisition = value; }
}

public void FindTarget()
{
this._targetAcquisition.FindTarget();
}
}


Where are our constructors? Why are they gone? And where is our target factory? Our machines are going to be standing idle if they have no targets to find.



And what is that [Dependency] attribute?



[Dependency] is an attribute that tells Unity that the property is a Dependency and needs Unity to initialize/assign it for us. For reference purposes, check out the following code:



IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers["targetOne"].Configure(container);

RobotTerminator newRobot = container.Resolve<RobotTerminator>();



What does it do? Well, the first section basically tells Unity to load a configuration file that will explain to it which types to load depending on the configuration file. The last line of code essentially instantiates our class into an object and tells Unity to look for any Dependencies (that is what the [Dependency] attribute is for) and will essentially invoke the Setter method of the property and pass it a concrete object.



We have greatly remove some code from our RobotTerminator class and consequently also removed responsibilities. Which is turn is a good practice because it makes the class simpler to understand. We moved the responsibility of finding targets to Unity and depending if we choose configuration files or not (which is our decision, the designer/programmer) Unity will in the end use the settings that we create and Hand out objects when necessary to the objects that will use them. The great thing is that we have done all of this while making our code much easier to maintain and potentially remove quite a bit of issues as well. With the option of moving out the decision of passing which objects (removed our factory) we have also further decoupled our system and now have a degree of coupling that is as far as can be. Loose coupling is good, it basically means that you have less shackles to maintain – shackles, as you may imagine are as bad in real life as in code.



Unity can also help you not only with Properties (our example was specific to the Strategy Pattern and Unity) but can also help you create Object factories that can return objects that are controlled (or orchestrated, if I can use the term) through configuration files.



Do you remember program output? How come computers can send output to files, printers or screens evenly? Well Unity can help you achieve this level of flexibility without going insane trying to figure out the plumbing to implement all of this.



Resources:


0 comments: