inversion of control
TRANSCRIPT
Inversion of ControlGuy Nir
January 2012
2
» The problem …» Inversion of Control» Benefits» Acceptance misbelieves
Agenda
The problem …
4
The problem …
public class MediaPlayer {
private InputSource inputSource;private OutputDevice outputDevice;
/** * Class constructor. */public MediaPlayer() {
inputSource = new FileInputSource(“c:/media/movie.avi”);outputDevice = new Screen();
}
/** * Play media. */public void play() {
while (running) {// Read from 'inputSource' and write to 'outputDevice'.
}}
}
5
The problem …
/** * Represents an input source. */public interface InputSource {
// Business methods.
}
/** * Represents an output device. */public interface OutputDevice {
// Business methods.
}
6
The problem …
<< InputSource
>>File (C:/….)
<<TargetDevice>>
Screen
Media Player
7
The problem …
<< InputSource
>>File (<?>)
<<TargetDevice>>
Screen
Configuration file
source = C:/media/file.avi
Media Player
8
The problem …
<< InputSource
>>File (<?>)
<<TargetDevice>><?>
Configuration file
source = C:/media/file.avi
targetClass =example.ScreenTarget
Media Player
9
The problem …
<< InputSource
>>File (<?>)
<<TargetDevice>><?>
Configuration file
source = C:/media/file.avi
targetClass =example.ScreenTarget
Media Player XXDatabase
10
The problem …
<< InputSource
>>File (<?>)
<<TargetDevice>><?>
Configuration file
source = C:/media/file.avi
targetClass =example.ScreenTarget
Media Player XXDatabase
Web service
11
The problem …
<< InputSource
>>File (<?>)
<< Target >><?>
Configuration file
source = C:/media/file.avi
targetClass =example.ScreenTarget
Media Player XXDatabase
Web service
12
» Too strict, cannot be changed easily.» Hard to extend» Can barely be reused (if at all).» Contradicts the ‘Open-Close principle’.[1]
The problem with the design …Driven by behavior and not by functionality
The problem …
[1] Open/closed principle by Bertrand Meyer
13
The problem …
<< InputSource
>>File (C:/….)
<< TargetDevice
>>Screen
Media Player
14
The problem …
<< InputSource
>>
<< TargetDevice
>>
Media Player
15
The problem …
/** * Represents an input source. */public interface InputSource {
// Business methods.
}
/** * Represents an output device. */public interface OutputDevice {
// Business methods.
}
16
The problem …
public class MediaPlayer {
private InputSource inputSource;private OutputDevice outputDevice;
/** * Class constructor. */public MediaPlayer() {
inputSource = new FileInputSource(“c:/media/movie.avi”);outputDevice = new Screen();
}
/** * Play media. */public void play() {
while (running) {// Read from 'inputSource' and write to 'outputDevice'.
}}
}
17
The problem …
public class MediaPlayer {
private InputSource inputSource;private OutputDevice outputDevice;
public void setInputSource(InputSource inputSource) {this.inputSource = inputSource;
}
public void setOutputDevice(OutputDevice outputDevice) {this.outputDevice = outputDevice;
}
/** * Play media. */public void play() {
while (running) {// Read from 'inputSource' and write to 'outputDevice'.
}}}
That’s our business logic.
18
» Concentrates on functionality only No lookup or creation of resources, Separation of concerns.
» We’re not limited to certain behavior Source and Target can be anything, Source and Target can be fetched from any where
• Configuration file, Database, Web service, …
What we’ve accomplished…Design by functionality
The problem …
19
» We can inject any source / target ! E.g.: deployable on other platforms Quickly inject mockups
• Required for Agile development• Required for unit testing.
What we’ve accomplished… (continued)
The problem …
Inversion of Control
21
» Is a conceptual abstraction in software development.» Introduced by Martin Fowler’s in 1988.[1]
» Has 3 flavors, Constructor injection (Dependency injection) Setter injection (Dependency injection) Dependency lookup.
Inversion of Control
[1] Martin Fowler – Dependency injection
22
» Inject required resources via constructor.
Constructor injection
Inversion of Control
public class ConstructorInjection {
private final DataSource dataSource;private final int timeout;
/** * Class constructor. * * @param dataSource Database connection. * @param timeout Query timeout. */public ConstructorInjection(DataSource dataSource, int timeout) { ... }
}
23
» Pros: Require user to specify all required resources. Object is guaranteed to be injected with resources.
• May cancel object if a resource is not fulfilled ( == null).
Constructor injection
Inversion of Control
public ConstructorInjection(DataSource dataSource, int timeout) {if (dataSource == null || timeout < 1)
throw new IllegalArgumentException();
this.dataSource = dataSource;this.timeout = timeout;
}
24
» Cons: Sometimes tedious,
• Must inject all resources or replace them with null. Does not work well for a large number of dependencies.
Constructor injection
Inversion of Control
public BadConstructorInjection(DataSource dataSource,int timeout, Dialect dialect, String characterSet, double
threashold,boolean eagerly, Formatter messageFormatter, ...) {
}
25
» Inject required resources via setXXX() method. Using JavaBean™ mutators.
Setter injection
Inversion of Control
public class SetterInjection {
private DataSource dataSource;private int timeout;
public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;
}
public void setTimeout(int timeout) {this.timeout = timeout;
}}
26
» Pros: Inject as many dependencies as you want. Each resource/value treated independently.
» Cons: Debatable issues …
Setter injection
Inversion of Control
public void setTimeout(int timeout) {if (timeout < 0) {
throw new IllegalArgumentException("Timeout cannot be negative.");}
this.timeout = timeout;}
27
» Split resource locating between user and implementation.
» Used much less than Constructor/Setter injections.
Dependency lookup
Inversion of Control
public void lookupDS(JNDIContext context) throws NamingException {dataSource = (DataSource) context.lookup("env:/ds/oracleDataSource");
}
public void locateConfigFile(File rootDir) throws NamingException {// Search file system for configuration file, starting with ‘rootDir’.
}
Benefits
29
» Full separation of concerns Reusable components Extendable components.
» Design and development by functionality. Each object/module is focused on its business logic. Produce a better, small, more efficient code.
» Agility. Excellent for Agile practices (e.g.: XP, TDD, …).
Benefits
Acceptance misbelievesOpen discussion about Inversion of Control
31
» Psychologically, hard to accept a new working methodology.
» Tendency to think that IoC creates too much code.
» It looks complex.
Acceptance misbelieves
Q & A