dependency injection
The pattern
by Marc Morera
@BeFactory
class Carpenter	

{	

	

 public function work()	

	

 {	

	

 	

 $hammer = new Hammer();	

	

 	

 $hammer->chop();	

	
...
Problems?
Let’s talk about	

responsibility
•

Any carpenter should ignore how to build a
hammer, but how to use it.	


•

The carpenter goes to a hardware store to g...
•

Not testable	


•

High coupling
class Carpenter	

{	

	

 public function work(Hammer $hammer)	

	

 {	

	

 	

 $hammer->chop();	

	

 }	

}	

!

$hammer...
•

So can we just have a carpenter without a
hammer?	


•

No way!	


•

A carpenter ALWAYS have a hammer.	


•

No hammer...
class Carpenter	

{	

	

 private $hammer;	

!

	

	

	

	


public function __construct(Hammer $hammer)	

{	

 	

	

 $th...
2 years later…
•

All carpenters are upgraded.	


•

No hammers anymore.	


•

All carpenters will use a simple small red ...
•

We want to make sure all objects that every
carpenter will use to chop, will be suitable for
that.	


•

How can ensure...
Interfaces
interface ToolInterface	

{	

	

 public function chop();	

}	

!

class Hammer implements ToolInterface	

{	

	

 public ...
class Carpenter	

{	

	

 private $tool;	

!

	

	

	

	


public function __construct(ToolInterface $tool)	

{	

 	

	

 ...
•

Very testable and easily mockable	


•

Low coupling	


•

Seems to be the best solution ever
But…
is this implementation a good one?
NO.
•

This is purely what means dependency
injection.	


•

Every dependency of an object is injected	


•

… into the constr...
Think about a full project with this code
$iron = new Iron;	

$wood = new Wood;	

$plastic = new Plastic(new Blue);	

$ham...
•

Not maintainable	


•

Not scalable	


•

Responsibility of building a carpenter is now
distributed by all controllers.
Container
What container should provide?
•

Definition	


•

Customization	


•

Instantiation
•

Our container is the provider of all instances.	


•

It is therefore responsable of building them
Services
•

A service is just an instance of an object	


•

Each service must define the path of the object
( given by the...
services:	

	

 iron:	

	

 	

 class: Iron	

	

 wood:	

	

 	

 class: Wood	

	

 plastic:	

	

 	

 class: Plastic	

	
...
$carpenter = $container->get(‘carpenter’);
Customization
•

In this example, every time a Carpenter is
requested, a new Hammer will be used.	


•

If we want to swit...
services:	

	

 iron:	

	

 	

 class: Iron	

	

 wood:	

	

 	

 class: Wood	

	

 plastic:	

	

 	

 class: Plastic	

	
...
Parameters

•

Any parameter should be able to be defined in
the project	


•

A parameter is used using “%” keyword.
parameters:	

	

 tool_class: Hammer	

services:	

	

 iron:	

	

 	

 class: Iron	

	

 wood:	

	

 	

 class: Wood	

	

...
Scopes
•

Prototype. 	


•

Container. Some objects can be just reused in
every request ( an infinite paint can ) - In the
...
Prototype
•

One instance per container request	


•

Container just build an instance and return it	


•

It’s defined by ...
Container
•

First time, object is built and stored.	


•

From next requests, same instance is reused and
returned	


•

...
services:	

	

 paint_can:	

	

 	

 class: PaintCan	

	

 	

 scope: container	

	

 carpenter:	

	

 	

 class: Painter	...
•

Each time a painter is requested, we’ll reuse
same paint can object since they all can share
it.
Implementations
•

Symfony2 - DependencyInjection Component	


•

Android - Dagger	


•

Objective C - Typhoon
DI Saves your life
Use it, dude!
QA?
Upcoming SlideShare
Loading in …5
×

Dependency injection

910 views

Published on

Dependency injection pattern, explained with a simple and common real life example.

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
910
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
15
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Dependency injection

  1. 1. dependency injection The pattern
  2. 2. by Marc Morera @BeFactory
  3. 3. class Carpenter { public function work() { $hammer = new Hammer(); $hammer->chop(); } } ! $carpenter = new Carpenter(); $carpenter->work();
  4. 4. Problems?
  5. 5. Let’s talk about responsibility
  6. 6. • Any carpenter should ignore how to build a hammer, but how to use it. • The carpenter goes to a hardware store to get some nice brown and big hammer.
  7. 7. • Not testable • High coupling
  8. 8. class Carpenter { public function work(Hammer $hammer) { $hammer->chop(); } } ! $hammer = new Hammer(); $carpenter = new Carpenter(); $carpenter->work($hammer);
  9. 9. • So can we just have a carpenter without a hammer? • No way! • A carpenter ALWAYS have a hammer. • No hammer, no carpenter.
  10. 10. class Carpenter { private $hammer; ! public function __construct(Hammer $hammer) { $this->hammer = $hammer; } ! } public function work() { $this->hammer->chop(); } ! $hammer = new Hammer(); $carpenter = new Carpenter($hammer); $carpenter->work();
  11. 11. 2 years later… • All carpenters are upgraded. • No hammers anymore. • All carpenters will use a simple small red mallet
  12. 12. • We want to make sure all objects that every carpenter will use to chop, will be suitable for that. • How can ensure this?
  13. 13. Interfaces
  14. 14. interface ToolInterface { public function chop(); } ! class Hammer implements ToolInterface { public function chop() { } } ! class Mallet implements ToolInterface { public function chop() { } }
  15. 15. class Carpenter { private $tool; ! public function __construct(ToolInterface $tool) { $this->tool = $tool; } ! } public function work() { $this->tool->chop(); } ! $carpenter = new Carpenter(new Hammer); $carpenter = new Carpenter(new Mallet); $carpenter->work();
  16. 16. • Very testable and easily mockable • Low coupling • Seems to be the best solution ever
  17. 17. But… is this implementation a good one?
  18. 18. NO.
  19. 19. • This is purely what means dependency injection. • Every dependency of an object is injected • … into the constructor if is needed for the class to be built • … in a method if is just needed for this method
  20. 20. Think about a full project with this code $iron = new Iron; $wood = new Wood; $plastic = new Plastic(new Blue); $hammer = new Hammer($iron, $wood, $plastic); $paintCan = new Paint(new Red); $carpenter = new Carpenter($hammer, $glasses, $paintCan); ! $nail = new Nail($iron); $carpenter->work($iron);
  21. 21. • Not maintainable • Not scalable • Responsibility of building a carpenter is now distributed by all controllers.
  22. 22. Container
  23. 23. What container should provide? • Definition • Customization • Instantiation
  24. 24. • Our container is the provider of all instances. • It is therefore responsable of building them
  25. 25. Services • A service is just an instance of an object • Each service must define the path of the object ( given by the namespace ) • Also can define how to be built ( arguments ) • An argument can be another service ( using @ )
  26. 26. services: iron: class: Iron wood: class: Wood plastic: class: Plastic hammer: class: Hammer arguments: iron: @iron wood: @wood plastic: @plastic carpenter: class: Carpenter arguments: hammer: @hammer
  27. 27. $carpenter = $container->get(‘carpenter’);
  28. 28. Customization • In this example, every time a Carpenter is requested, a new Hammer will be used. • If we want to switch to a Mallet, we must change definition. • We should be able to configure it outside the definition of the container.
  29. 29. services: iron: class: Iron wood: class: Wood plastic: class: Plastic hammer: class: Hammer arguments: iron: @iron wood: @wood plastic: @plastic carpenter: class: Carpenter arguments: hammer: @hammer
  30. 30. Parameters • Any parameter should be able to be defined in the project • A parameter is used using “%” keyword.
  31. 31. parameters: tool_class: Hammer services: iron: class: Iron wood: class: Wood plastic: class: Plastic tool: class: %tool_class% arguments: iron: @iron wood: @wood plastic: @plastic carpenter: class: Carpenter arguments: tool: @tool
  32. 32. Scopes • Prototype. • Container. Some objects can be just reused in every request ( an infinite paint can ) - In the real world, a Logger or a simple Text library.
  33. 33. Prototype • One instance per container request • Container just build an instance and return it • It’s defined by setting scope: prototype • For example, a nail
  34. 34. Container • First time, object is built and stored. • From next requests, same instance is reused and returned • Saving memory ( storing objects ) and cpu ( building them ) • It’s defined by setting scope: container. Default behavior
  35. 35. services: paint_can: class: PaintCan scope: container carpenter: class: Painter scope: prototype arguments: paint_can: @paint_can
  36. 36. • Each time a painter is requested, we’ll reuse same paint can object since they all can share it.
  37. 37. Implementations • Symfony2 - DependencyInjection Component • Android - Dagger • Objective C - Typhoon
  38. 38. DI Saves your life Use it, dude!
  39. 39. QA?

×