Share on Facebook Share on Twitter Email
Answers.com

Dependency injection

 
Wikipedia: Dependency injection
 

Dependency injection (DI) in computer programming refers to the process of supplying an external dependency to a software component. It is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency. The term was first coined by Martin Fowler to more clearly describe the mechanism.[1]

Contents

Basics

Conventionally, if an object, in order to accomplish a certain task, needs a particular service, it will also be responsible for instantiating and disposing of (removing from memory, closing streams, etc.) the service, therefore making it more complex and hard to maintain. Ideally, this object would not need to manage its services life cycle but just have a reference to an implementation of the said services and invoke its relevant behaviors. Dependency injection is a design pattern that can be applied to provide an object with its dependencies and move the code related to the service life cycle to a more appropriate place.

Such pattern involves at least three elements: a dependent, its dependencies and a provider. The dependent is an object that is expected to accomplish a relevant task in a computer program. In order to do so, it needs the help of other objects (the dependencies) that provide specialized services. The provider is the component that is able to compose the dependent and its dependencies so they are ready to be used, while also managing other aspects of these objects life cycle, such as when and how they are instantiated (cached or not, for example). This provider may be implemented, for example, as a service locator, an abstract factory, a factory method or a more complex structure, like a framework.

As a simple example of the above explanation, we can think of a car as the dependent, the engine as the dependency and a car factory as a provider. A car does not know how to install an engine on itself, but it needs an engine to run. The assembling of an engine on a car is a car factory responsibility.

When the dependency injection technique is used to decouple high-level modules from low-level services, the resulting design guideline is called the dependency inversion principle.

Code illustration using Java

Using the car/engine example above mentioned, the following Java code shows a typical arrangement with no dependency injection applied:

public class Car {
 
    private Engine engine = new Engine();
 
    /** @returns the car speed */
    public int onAcceleratorPedalStep(int gasPedalPressure) {
        engine.setFuelValveIntake(gasPedalPressure);
        int torque = engine.getTorque();
        int speed = ... //math to get the car speed from the engine torque
        return speed;
    }
 
}
 
//omitting the Engine class since it isn't relevant to this example 
//or its implementation is unknown

As shown, the Car class needs to create an instance of an Engine class to calculate its speed based on how much pressure is made on the accelerator pedal. A similar implementation would instantiate the Engine inside the onAcceleratorPedalStep method, but such an approach still forces the Car class to know how to instantiate its own Engine.


Now, should this example use dependency injection, a possible implementation would be:

public class Car {
 
    private Engine engine;
 
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
 
    /** @returns the car speed */
    public int onAcceleratorPedalStep(int gasPedalPressure) {
        engine.setFuelValveIntake(gasPedalPressure);
        int torque = engine.getTorque();
        int speed = ... //math to get the car speed from the engine torque
        return speed;
    }
 
}
 
//omitting the Engine class since it isn't relevant to this example 
//or its implementation is unknown
 
public class CarFactory {
 
    public Car buildCar() {
        Car car = new Car();
        Engine engine = new Engine();
        car.setEngine(engine);
        return car;
    }
 
}

In this example, the CarFactory class represents the provider. It is a simple application of the factory method design pattern that makes it possible for the Car class to not need to know how to get an engine for itself. This is now CarFactory's responsibility.

This example does not show the full potential of dependency injection since the CarFactory is very simple. To make it a little more interesting one could consider designing it to provide a single instance of Engine to all cars it builds. More instantiation strategies could also exist and be used as specified in a CarFactory's configuration file (a typical feature in dependency injection frameworks). Also, note that in real programs there will be many classes that, like Car, will need to use many components. In this case, the provider's capability to inject dependencies will remove a lot of coding effort from the dependents.

Benefits and issues

One important benefit of using dependency injection approach is the reduction of boilerplate code in the application objects since all work to initialize or setup dependencies will be made in the provider component[2].

Also, it offers more flexibility because it becomes easier to create alternative implementations of a given service type, and then to specify which implementation is to be used via a configuration file, without any change to the objects that use the service. This is especially useful in unit testing, because it is easy to inject a fake implementation of a service into the object being tested.

On the other hand, excessive use of dependency injection can make applications more complex and harder to maintain: in order to understand the application's behaviour the developer needs to look at the configuration as well as the code, and the configuration is "invisible" to IDE-supported reference analysis and refactoring unless the IDE specifically supports the dependency injection framework. Frameworks such as the Grok web framework introspect the code and use convention over configuration as an alternative form of deducing configuration information. For example, if a Model and View class were in the same module, then an instance of the View will be created with the appropriate Model instance passed into the constructor.

Types

Fowler identifies three ways in which an object can get a reference to an external module, according to the pattern used to provide the dependency:[3]

  • Type 1 or interface injection, in which the exported module provides an interface that its users must implement in order to get the dependencies at runtime.
  • Type 2 or setter injection, in which the dependent module exposes a setter method which the framework uses to inject the dependency.
  • Type 3 or constructor injection, in which the dependencies are provided through the class constructor. This is the main form used by PicoContainer, although it also supports setter injection.

It is possible for other frameworks to have other types of injection, beyond those presented above.[4]

Existing frameworks

Dependency injection frameworks exist for a number of platforms and languages, as can be seen in the following table:

Language/platform DI Framework
ActionScript Prana Framework
ActionScript di-as3
ActionScript Syringe
ActionScript lowRa (AS3)
ActionScript Pixlib (AS2)
ActionScript VEGAS and AndromedA this IOC extension.(AS3/AS2/SSAS) (see Introduction IOC based ECMAScript notation)
ActionScript Parsley (AS3) as part of the Spicefactory
C++ Autumn Framework
C++ PocoCapsule/C++ IOC and DSM Framework
C++ QtIOCContainer
C++ C++ Builder coupling dependency injection and component based assembly
ColdFusion ColdSpring Framework
Delphi Delphi Pascal coupling dependency injection and component based assembly
Flex Flicc
Flex Mate
Flex Swiz
Java Butterfly Container
Java Essence Java Configuration File
Java Apache Felix iPOJO
Java Google Guice
Java HiveMind
Java JBoss Microcontainer
Java PicoContainer
Java Openxava
Java JBuilder coupling dependency injection and component based assembly
Java simject
Java Seasar
Java Spring Framework
Java J2EE 5 / EJB 3
Java Naked Objects
Java miocc - Microscopic Inversion of Control Container
Java Spring ME
Java Yan
Java JSR-330 Dependency Injection for Java
Java 2 Micro Edition Israfil micro container (CLDC 1.1)
Java 2 Micro Edition Spring ME
JavaScript Squirrel IoC
JavaScript ContainerJS
Microsoft .NET Managed Extensibility Framework
Microsoft .NET Autofac
Microsoft .NET Castle MicroKernel/Windsor
Microsoft .NET ObjectBuilder
Microsoft .NET PicoContainer.NET
Microsoft .NET Puzzle.NFactory
Microsoft .NET Spring.NET
Microsoft .NET StructureMap
Microsoft .NET Ninject
Microsoft .NET Unity
Microsoft .NET The LinFu Framework
Microsoft .NET NauckIT.MicroKernel
Microsoft .NET WINTER4NET
PHP 4 drip
PHP 5 Phemto
PHP 5 DiContainer
PHP 5 Garden
PHP 5 Xyster Framework
PHP 5 Lion Framework
PHP 5 Spiral Di Container
PHP 5 Symfony Dependency Injection Container
Perl The IOC Module
Perl Bread::Board
Python Zope Component Architecture
Python Spring Python
Python PyContainer
Ruby Copland
Ruby Needle

See also

Further reading

References


Search unanswered questions...
Enter a word or phrase...
All Community Q&A Reference topics
 
 

 

Copyrights:

Wikipedia. This article is licensed under the GNU Free Documentation License. It uses material from the Wikipedia article "Dependency injection" Read more