Pages

Google+

Wednesday, July 29, 2009

Dependancy Injection - Minus the Hype

Within the Flash community there has been a fair amount of talk about Dependency Injection. A few ( generally Flex ) frameworks have become popular - notably Robotlegs, Mate and Swiz. It's easy to find high level discussion about them, but these generally involve developers who are already familiar with DI ( Dependency Injection )  and IoC ( Inversion of Control ).

Fowler's article is often cited when references are made to DI.  Admittedly, it's a lot to take in and consider, especially when the article gets into containers.  All this can be confusing to anyone who's not a seasoned coder or just wants a simple example and not all that prose.


A Simple Example


To make this more real world, imagine I have a website in a MVC ( Model-View-Controller ) fashion. The models hold the data for the site, the views are responsible for display objects ( e.g. MovieClips or Sprites )  and there are some kind of controller classes in between. For a good example of MVC go here. Below is a bare bones example of DI when creating views.

The Code


public class WebsiteViews
{
var aboutPage = new AboutPage();
aboutPage.artworkForView = new AboutClassArtworkSetToExportFromFlashIDE();
// Other views created same as above
}

public class AboutPage
{
private var artwork:MovieClip;

public function set artWorkForView(artFromFlashIDE:MovieClip):void
{
this.artwork = artFromFlashIDE;
}
}

A Simple Definition


Dependency injection is a technique where a higher level object gives a lower level object whatever it needs to perform a task. This is in contrast to a higher level object only creating a lower level object - then expecting the lower level object to create what it needs to function.


The dependency injection part of the above example is when I create the 'About' class then pass it the display object it is going to be acting on.  The object 'AboutClassArtworkSetToExportFromFlashIDE" is the dependency and it is being injected into 'AboutPage'. This might seem trivial but it's not. In fact it is invaluable.

To understand why this is significant, it's important to understand how to properly use encapsulation - here is a previous post of mine about effectively using encapsulation. This allows the application designer to effectively use object composition and aggregation. Otherwise the designer might code something like this:
public class WebsiteViews
{
var aboutPage = new AboutPage();
// Other views created same as above
}

public class AboutPage
{
private var artwork:MovieClip;

public function AboutPage():void
{
this.artwork = new AboutClassArtworkSetToExportFromFlashIDE();
}
}

Do this, and you are about to enter a world of hurt.  This is because the designer is now losing control of the application.  The classes are beginning to take on a Matryoshka Doll structure as creating an object begins an uncontrollable sequence of instantiation.  To get around this, programmers use Singletons and conditional business logic to try and wrestle back control of the application. I don't use Singletons and I very rarely use conditionals of any kind.

Unlocking the Power of Dependency Injection


I suspect DI's recent spike in interest has to do with the Agile process and it's Test Driven Development.  In order to build effective unit tests, Java developers almost have to use DI.  This is due to the fact that in order to run a test on piece of code, often the dev will need to pass the code a dummy or null object. In the 'bad' example above, to test my AboutPage class I'd need to have an 'AboutClassArtworkSetToExportFromFlashIDE' ready. This is because whether I like it or not as I create AboutPage, I am also creating 'AboutClassArtworkSetToExportFromFlashIDE'. If I set up my class to not automatically create objects ( the first code example ), I can control what objects it acts upon - or even give it a Null Object.


Flash developers don't do much Unit Testing, and it's not very helpful for production code. So where is this 'Power' alluded to in the previous header? The power lies in using builder classes to consolidate code.



public class WebsiteViews
{
var aboutPage = new AboutPage();
aboutPage.artworkForView = ViewBuilder.buildAndReturnAboutPage();
// Other views created same as above
}

public class AboutPage
{
private var artwork:MovieClip;

public function set artWorkForView(artFromFlashIDE:MovieClip):void
{
this.artwork = artFromFlashIDE;
}
}

// my builder class
public class ViewBuilder
{
public static function buildAndReturnAboutPage():Movieclip
{
var aboutPage = new AboutClassArtworkSetToExportFromFlashIDE();
return aboutPage;
}
}

In this example the builder class is just creating one class, but as my application grows I can start to fill this method with other objects and compose them together to build my view artwork. Using DI, it becomes very easy and practical to use Creator Classes. These constructs are an incredibly useful and simple technique that can give your application tremendous flexibility.

That's it. Dependency Injection can be abstracted out into sophisticated implementations, but in it's simplest form it's something that almost any coder can include into their work-flow.