Inversion of Control and Dependency Injection in Flex using the Parsley Application Framework – Part 1

The Inversion of Control (IoC) design principle and the related Dependency Injection (DI) design pattern have been around for several years. In the Java world, popular frameworks such as Spring make heavy use of these concepts. With the introduction of Actionscript 3 in 2006, the opportunities for framework development increased greatly. As the community matures, we are starting to see robust tools appear on the development landscape. It is a good time to be a Flash geek!

Through this series of articles, we will delve into the Parsley application framework and look at how it implements IoC and DI in the context of a photo slideshow. Through this example we will look at bootstrapping the container, connecting to services, and populating our components with the results. In this first part, we will get an overview of IoC and DI and talk about some of the benefits and drawbacks of using these concepts in our applications.

What is Inversion of Control?

One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user’s application code. The framework often plays the role of the main program in coordinating and sequencing application activity. This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application. –Ralph Johnson and Brian Foote [1]

If you are using an Actionscript framework in your development, odds are you’re making use of IoC. This includes Flex itself, PureMVC, Mate, SWiZ, Parsley, and other similar frameworks. The framework is providing an abstracted skeleton to which the developer can code against. Communication between the actors in the system are coordinated by the framework within a predefined architecture. In other words, some level of control is inverted from the individual components of an application to the underlying framework.

This inversion can be approached from many different directions. In frameworks such as PureMVC and Cairngorm, this inversion of control is handled by extension of framework classes. By extending these objects, the framework is provided with the appropriate interface to access and manipulate the application specific objects. Frameworks such as Parsley and SWiZ provide metadata annotation as the mechanism for wiring into the framework.

What is Dependency Injection?

DI is a design pattern canonized by Martin Fowler [2]. Essentially, your application’s objects do not configure themselves. They rely on an external mechanism for configuration that ‘injects’ the object’s dependencies by populating its instance variables. Fowler felt that Inversion of Control was too generic of a description (as all frameworks tend to invert control), and decided on the name Dependency Injection for the pattern.

Dependency Injection means giving an object its instance variables [3]

Say what? Given this simple definition of DI, this is something we are all making use of on a constant basis. Unless you are writing strictly procedural AS3 (which is certainly possible), DI is likely being used in your applications. Yes, the concept can quickly become more complex – abstracting simple concepts tends to have that effect.

The pattern describes three primary methods for injecting our dependencies:

Constructor Injection:

1
2
3
4
5
6
7
8
9
10
11
12
package
{
	public class MyObject
	{
		private var dependsOn:IDependency;
 
		public function MyObject(dependsOn:IDependency)
		{
			this.dependsOn = dependsOn;
		}
	}
}

usage:

1
var myObject:MyObject = new MyObject(aDependencyImplementation);

Setter Injection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package
{
	public class MyObject
	{
		private var dependsOn:IDependency;
 
		public function MyObject()
		{
		}
 
		public function setDependsOn(value:IDependency):void{
			this.dependsOn = value;
		}
	}
}

usage:

1
2
var myObject:MyObject = new MyObject()
myObject.setDependsOn(aDependencyImplementation);

Property Injection:

1
2
3
4
5
6
7
8
9
10
11
package
{
	public class MyObject
	{
		public var dependsOn:IDependency;
 
		public function MyObject()
		{
		}
	}
}

usage:

1
2
var myObject:MyObject = new MyObject()
myObject.dependsOn =  aDependencyImplementation;

Setter and property injection are both very similar, and are useful for optional dependencies. Constructor injection is useful for required dependencies that an object must have to function.

Benefits of Dependency Injection

One of the primary benefits of DI is related to unit testing your application. DI allows you to create loosely couple objects that can be easily replaced with mock or stub objects for testing. Unit testing needs to test your objects in isolation, without regard for how the object interacts with its various dependencies.

A unit test is a user of the object it tests. An object must exist for a reason, so there must be other objects that also use it. Even when only one application object uses it, the fact that the unit test is also a user means it has at least two users, and therefore the object must be reusable by design. Test-driven development (TDD), in which unit tests are written before the objects they test, is gaining as a development best practice. One beneficial consequence of TDD is that objects are designed with testability in mind, and therefore, an object and its dependencies must be loosely coupled and reusable. Dependency injection is a popular pattern to design loosely coupled—and therefore robust, reusable, and testable—objects. [4]

DI can also encourage component reuse in much the same way. Since the object’s dependencies are not hard-coded, it is open for reuse. The injectable objects are more adaptable allowing developers to see clearly where to start adding features. The loose coupling can create a more maintainable code-base allowing developers to more easily track down bugs.

Drawbacks of Dependency Injection

No Silver Bullets. [5]

DI can potentially obfuscate an application. To understand the application a developer has to understand both the code and the configuration defining the dependency injections. In many situations, an IDE will not be able to read and give feedback on the configuration.

Inversion of Control Containers

You don’t need an IoC Container (framework) to benefit from DI. As we have seen, you are probably already using DI in your code, irrespective of your preferred framework. IoC Containers provide out of the box methods for instantiating and configuring your application’s objects. The use of an IoC container is dependent on your (and your application’s) needs. For smaller projects, it might not be appropriate.

In the second part of this series, we will look into the Parsley application framework and its implementation of an IoC container and DI.

[1] https://www.laputan.org/drc/drc.html
[2] https://martinfowler.com/articles/injection.html
[3] https://jamesshore.com/Blog/Dependency-Injection-Demystified.html
[4] https://www.ddj.com/development-tools/185300375
[5] https://www.virtualschool.edu/mon/SoftwareEngineering/BrooksNoSilverBullet.html

  • https://blog.vivisectingmedia.com James

    Thanks for taking the time to write up the IoC/DI intro, this is a nice clear and simple explanation. Looking forward to the future parts!

  • https://blog.vivisectingmedia.com James

    Thanks for taking the time to write up the IoC/DI intro, this is a nice clear and simple explanation. Looking forward to the future parts!