Dependency Injection 2014
-
Upload
piotr-kundu -
Category
Software
-
view
175 -
download
0
Transcript of Dependency Injection 2014
12/12/2014
1
Steven van Deursen
cuttingedge.it/blogs/steven
@dot_net_junkie
Dependency Injection
“Dependency injection is a software
design pattern that implements
inversion of control and allows a
program design to follow the
dependency inversion principle.”
Source:
en.wikipedia.org/wiki/Dependency_injection
12/12/2014
2
Inversion of Control
• Describes the interaction between code and a framework
• IoC does not describe how the interaction takes place.
• It’s so common; we don’t think about it anymore.
The SOLID principles
•Single responsibility principle
•Open/closed principle
•Liskov substitution principle
•Interface segregation principle
•Dependency inversion principle
12/12/2014
3
Dependency Inversion Principle
“A. High-level modules should not
depend on low-level modules. Both
should depend on abstractions.
B. Abstractions should not depend on
details. Details should depend on
abstractions.”
Source:
en.wikipedia.org/wiki/Dependency_inversion_principle
Dependency Inversion Principle
Example: the “Copy” program
12/12/2014
4
Dependency Inversion Principle
Example: the “Copy” program
“A. High-level modules should not
depend on low-level modules. Both
should depend on abstractions.
B. Abstractions should not depend on
details. Details should depend on
abstractions.”
Dependency Inversion Principle (DIP)
The problem of class coupling
•Maintainability
•Extendibility
•Reusability
•Testability
•Parallel development
“A. High-level modules should not
depend on low-level modules. Both
should depend on abstractions.
B. Abstractions should not depend on
details. Details should depend on
abstractions.”
12/12/2014
5
static class CameraOperator{public:
static Snapshot Operate(){
CameraPosition position = DetermineNextCameraPosition();
return RaytracingCamera::TakeSnapshot(position);}
static CameraPosition DetermineNextCameraPosition(){
time_t currentTime = time(NULL);
// Assume some complex time dependent calculation.return CameraPosition();
}};
DIP Violations
static class CameraOperator{public:
static Snapshot Operate(){
CameraPosition position = DetermineNextCameraPosition();ICamera* camera = ...;return camera->TakeSnapshot(position);
}
static CameraPosition DetermineNextCameraPosition(){
ITimeProvider* timeProvider = ...;time_t currentTime = timeProvider->GetCurrentTime();// Assume some complex time dependent calculation.return CameraPosition();
}};
Applying DIP
12/12/2014
6
Service Locator
static class CameraOperator{public:
static Snapshot Operate(){
CameraPosition position = DetermineNextCameraPosition();
ICamera* camera = Locator::Get<ICamera>();return camera->TakeSnapshot(position);delete camera;
}
static CameraPosition DetermineNextCameraPosition(){
ITimeProvider* timeProvider = Locator::Get<ITimeProvider>();time_t currentTime = timeProvider->GetCurrentTime();delete timeProvider;
// Assume some complex time dependent calculation.return CameraPosition();
}};
Service Locator
12/12/2014
7
Service Locator
Advantages
•Easy to grasp
• Easy to get started with in a legacy application
Service Locator
Disadvantages
• DIP violation in itself
•Can’t work without the Locator
•Context unclear from perspective of the locator
•Hard to test
•No compile-time support
•Dependencies unclear
12/12/2014
9
class CameraOperator{private:
ITimeProvider* timeProvider;ICamera* camera;
public:CameraOperator(ITimeProvider* timeProvider, ICamera* camera){
this->timeProvider = timeProvider;this->camera = camera;
}
Snapshot Operate(){
CameraPosition position = DetermineNextCameraPosition();return this->camera->TakeSnapshot(position);
}
CameraPosition DetermineNextCameraPosition(){
time_t currentTime = this->timeProvider->GetCurrentTime();return CameraPosition();
}};
Dependency Injection
Dependency Injection
Advantages
• Dependencies clear
•Compile-time support
•Easy to spot SRP violations
•No more dependency with Locator.
12/12/2014
10
Dependency Injection
Disadvantages
•We’ll get to that…
class MovieScene{public:
void RecordScene(){
SystemTimeProvider* timeProvider = new SystemTimeProvider();RaytracingCamera* camera = new RaytracingCamera();CameraOperator* cameraOperator =
new CameraOperator(timeProvider, camera);MpegFileRecorder* recorder =
new MpegFileRecorder("c:\\movies\\di_bloopers.mpg");
while (!wholeSceneRecorded) {Snapshot snapshot = cameraOperator->Operate();recorder->Append(snapshot);
}
delete recorder;delete cameraOperator;delete camera;delete timeProvider;
}};
Dependency Injection
12/12/2014
11
class MovieScene{private:
ITimeProvider* timeProvider;ICamera* camera;IRecorder* recorder;
public:MovieScene(ITimeProvider* provider, ICamera* camera, IRecorder* recorder){
this->timeProvider = provider;this->camera = camera;this->recorder = recorder;
}
void RecordScene(){
CameraOperator* cameraOperator =new CameraOperator(this->timeProvider, this->camera);
while (!wholeSceneRecorded) {Snapshot snapshot = cameraOperator->Operate();this->recorder->Append(snapshot);
}
delete cameraOperator;}
};
Dependency Injection
class MovieScene{private:
ICameraOperator* cameraOperator;IRecorder* recorder;
public:MovieScene(ICameraOperator* cameraOperator, IRecorder* recorder){
this->cameraOperator = cameraOperator;this->recorder = recorder;
}
void RecordScene(){
while (!wholeSceneRecorded) {Snapshot snapshot = this->cameraOperator->Operate();this->recorder->Append(snapshot);
}}
};
Dependency Injection
12/12/2014
12
int _tmain(int argc, _TCHAR* argv[]){
// Composition RootITimeProvider* timeProvider = new SystemTimeProvider();ICamera* camera = new RaytracingCamera(1280, 1024);ICameraOperator* operator =
new CameraOperator(timeProvider, camera);
IRecorder* recorder =new MpegFileRecorder("c:\\movies\\di_successStories.mpg");
MovieScene* movieScene = new MovieScene(cameraOperator, recorder);
movieScene->RecordScene();
delete movieScene;delete recorder;delete cameraOperator;delete camera;delete timeProvider;
return 0;};
Composition Root
ITimeProvider* g_timeProvider = new SystemTimeProvider();
int _tmain(int argc, _TCHAR* argv[]){
while (true) // Simulate requests{
Request<MovieScene>* request = CreateScene(new WireframeCamera(375, 300), new ScreenViewer());
MovieScene* scene = request->Root;scene->RecordScene();delete request;
}
return 0;};
Request<MovieScene>* CreateScene(ICamera* camera, IRecorder* recorder){
Request<MovieScene>* request = new Request<MovieScene>();
request->Root = new MovieScene(request->Add(new CameraOperator(
g_timeProvider, request->Add(camera))),
request->Add(recorder));
return request;};
Composition Root
12/12/2014
13
Composition Root
Advantages of centralizing creation of object graphs
•Not doing so fails DIP
•Easier to reason about concurrency and thread-safety
•Easier to reason about resource management.
Dependency Injection
Disadvantages?
•Takes time to master
•Not easy to apply in legacy systems
12/12/2014
14
Books!
•Mark Seemann
•Roy Osherove
•Jeff Langr
•Robert C. Martin
Steven van Deursen
cuttingedge.it/blogs/steven
@dot_net_junkie