Inversion of control
In software engineering, inversion of control (IoC) is a programming technique, expressed here in terms of object-oriented programming, in which object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis.
In traditional programming, the flow of the business logic is determined by objects that are statically assigned to one another. With inversion of control, the flow depends on the object graph that is instantiated by the assembler. Such a dynamic flow is made possible by object interactions being defined through abstractions. The binding process is achieved through dependency injection, although some argue that the use of a service locator also provides inversion of control.
In order for the assembler to bind objects to one another, the objects must possess compatible abstractions. For example, class A may delegate behavior to interface I which is implemented by class B; the assembler instantiates A and B then injects B to A.
In practice, inversion of control is a style of software construction where reusable code controls the execution of problem-specific code. It carries the strong connotation that the reusable code and the problem-specific code are developed independently, which often results in a single integrated application. Inversion of control as a design guideline serves the following purposes:
- There is a decoupling of the execution of a certain task from implementation.
- Every module can focus on what it is designed for.
- Modules make no assumptions about what other systems do but rely on their contracts.
- Replacing modules has no side effect on other modules.
Inversion of control is sometimes facetiously referred to as the "Hollywood Principle: Don't call us, we'll call you", because program logic runs against abstractions such as callbacks.
Background
Inversion of control is not a new term in computer science. Martin Fowler traces the etymology of the phrase back to 1988.[1] Dependency injection is a specific type of IoC using contextualized lookup.[2] The use of a service locator is considered to be the same design pattern. In an article by Loek Bergman,[3] it is presented as an architectural principle.
In an article by Robert C. Martin,[4] the dependency inversion principle and abstraction by layering come together. His reason to use the term "inversion" is in comparison with traditional software development methods. He describes the uncoupling of services by the abstraction of layers when he is talking about dependency inversion. The principle is used to find out where system borders are in the design of the abstraction layers.
Inversion of control is highly associated with dependency injection and the dependency inversion principle. Dependency injection is the main method to implement inversion of control.
Implementation techniques
In object-oriented programming, there are several basic techniques to implement inversion of control. These are:
- Using a factory pattern
- Using a service locator pattern
- Using a dependency injection, for example:
- A constructor injection
- Parameter injection
- A setter injection
- An interface injection
- Using a contextualized lookup
- Using Template method design pattern
- Using strategy design pattern
In an original article by Martin Fowler,[5] the first three different techniques are discussed. In a description about inversion of control types,[6] the last one is mentioned. Often the contextualized lookup will be accomplished using a service locator.
More important than the applied technique, however, is the optimization of the purposes.
Examples
public class ServerFacade { public <K, V> V respondToRequest(K request) { if (businessLayer.validateRequest(request)) { DAO.getData(request); return Aspect.convertData(request); } return null; } }
This basic outline in Java gives an example of code following the IoC methodology. It is important, however, that in the ServerFacade a lot of assumptions are made about the data returned by the data access object (DAO).
Although all these assumptions might be valid at some time, they couple the implementation of the ServerFacade to the DAO implementation. Designing the application in the manner of inversion of control would hand over the control completely to the DAO object. The code would then become
public class ServerFacade { public <K, V> V respondToRequest(K request, DAO dao) { return dao.getData(request); } }
The example shows that the way the method respondToRequest is constructed determines if IoC is used. It is the way that parameters are used that define IoC. This resembles the message-passing style that some object-oriented programming languages use.
See also
- Abstraction layer
- Asynchronous I/O
- Callback (computer science)
- Closure (computer science)
- Continuation
- Delegate (CLI)
- Dependency inversion principle
- Flow-based programming
- Implicit invocation
- Interrupt handler
- Message Passing
- Monad (functional programming)
- Observer pattern
- Publish/subscribe
- Service locator pattern
- Signal (computing)
- Software framework
- Strategy pattern
- User exit
- Visitor pattern
- XSLT is a data-driven scripting language, meaning that the input data controls which templates (methods) are executed and in what order. Templates automatically return control to the input data upon completion or by using the
<xsl:apply-templates />
command.
References
- ↑ Inversion of Control on Martin Fowler's Bliki
- ↑ Dependency Injection.
- ↑ Inside Architecture: write once, run anywhere by Loek Bergman
- ↑ The Dependency Inversion principle by Robert C. Martin
- ↑ Inversion of Control Containers and the Dependency Injection Pattern by Martin Fowler
- ↑ IoC Types