Dependency injection

From Wikipedia, the free encyclopedia

Jump to: navigation, search

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

[edit] Basics

Conventionally, if an object needs to gain access to a particular service, the object takes responsibility to access that service: either it holds a direct reference to the location of that service, or it goes to a known service locator and requests that it be passed back a reference to an implementation of a specified type of service. By contrast, using dependency injection, the object simply provides a property that can hold a reference to that type of service; then, when the object is created, a reference to an implementation of that type of service will automatically be injected into that property by an external mechanism.

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.

The dependency injection approach 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 mock 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.

[edit] Code illustration using Java

Suppose that Foo is an interface:

public interface Foo
{
      void bar(); // Perform bar
      void baz(); // Perform baz
}

There exist also a number of implementation classes, each of them implementing Foo in some way:

public class DatabaseFoo implements Foo
{
      void bar() {
          Database.selectBar().execute(); // Use the database to do bar
      }
 
      void baz() {
          Database.selectBaz().run(); // Use the database to do baz
      }
}
public class PixieDustFoo implements Foo
{
      void bar() {
          Spell.cast("bar"); // Magic!
      }
 
      void baz() {
          Spell.cast("baz"); // More magic!
      }
}

Foo only specifies the operations available in its interface, but doesn't itself provide any implementation, instead leaving that to other implementer classes. This way a user wishing to use the Foo functionality can use any implementation, not knowing anything more about them than that they conform to the Foo interface.

An object needing the services defined by Foo needs to get an instance of a class that implements Foo:

public class ImportantClass 
{
      Foo foo;
 
      public ImportantClass() {
            this.foo = new DatabaseFoo();
      }
 
      void doReallyImportantStuff() {
            this.foo.bar();
      }
}

However, this defeats the entire point of using an interface instead of a concrete implementation. To fix that, it's enough to let the outside caller provide the desired implementation:

public class ImportantClass 
{
      Foo foo;
 
      public ImportantClass(Foo foo) {
            this.foo = foo;
      }
 
      void doReallyImportantStuff() {
            this.foo.bar();
      }
}

When using dependency injection there is usually a configuration mechanism or architecture for deciding which implementation gets injected into an object.

[edit] 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:[2]

  • 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.[3]

[edit] 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 2 Micro Edition Israfil micro container (CLDC 1.1)
Java 2 Micro Edition Spring ME
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 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
Perl The IOC Module
Perl Bread::Board
Python Zope Component Architecture
Python Spring Python
Python PyContainer
Ruby Copland
Ruby Needle

[edit] See also

[edit] Further reading

[edit] References

Personal tools