introducing dependency injection · dependency injection container • creates objects on demand...
TRANSCRIPT
![Page 1: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/1.jpg)
IntroducingDependency Injection
Rob AllenNovember 2013
![Page 2: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/2.jpg)
I make websites19ft.com
![Page 3: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/3.jpg)
Dependency Injection enables loose coupling andloose coupling makes code more maintainable
Mark Seemann
![Page 4: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/4.jpg)
We’re actually talking about loose coupling today
![Page 5: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/5.jpg)
Coupling
![Page 6: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/6.jpg)
Benefits of loose coupling• Maintainability - Classes are more clearly defined• Extensibility - easy to recompose application• Testability - isolate what you’re testing
![Page 7: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/7.jpg)
A worked exampleClass A needs class B in order to work.
class Letter
{
protected $paper;
public function __construct()
{
$this->paper = new WritingPaper();
}
}
// usage:
$letter = new Letter();
$letter->write("Dear John, ...");
![Page 8: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/8.jpg)
Pros and cons:Pros:
• Very simple to use
Cons:
• Tight coupling
• Cannot test Letter in isolation• Cannot change $paper
![Page 9: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/9.jpg)
The problem with coupling• How do we change the paper size?• How do we change the type of paper?
![Page 10: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/10.jpg)
Method parameters?class Letter
{
protected $paper;
public function __construct($size)
{
$this->paper = new WritingPaper($size);
}
}
// usage:
$letter = new Letter('A4');
$letter->write("Dear John, ...");
![Page 11: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/11.jpg)
Use a Registry?class Letter
{
protected $paper;
public function write($text)
{
$paper = Zend_Registry::get('paper');
return $paper->placeWords($text);
}
}
// usage:
Zend_Registry::set('paper', new AirmailPaper('A4'));
$letter = new Letter();
$letter->write("Dear John, ...");
![Page 12: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/12.jpg)
Inject the dependency!
![Page 13: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/13.jpg)
Injectionclass Letter
{
protected $paper;
public function __construct($paper)
{
$this->paper = $paper;
}
}
// usage:
$letter = new Letter(new WritingPaper('A4'));
$letter->write("Dear John, ...");
![Page 14: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/14.jpg)
This is also known as
Inversion of Control
![Page 15: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/15.jpg)
Pros and cons:Pros:
• Decoupled $paper from Letter:
• Can change the type of paper• Natural configuration of the Paper object
• Can test Letter independently
Cons:
• Burden of construction of $paper is on the user
![Page 16: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/16.jpg)
Dependency Injection
That’s it; we’re done!
![Page 17: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/17.jpg)
Types of injectionConstructor injection:
$letter = new Letter($paper);
Property injection:
$letter = new Letter();
$letter->paper = $paper;
Setter injection:
$letter = new Letter();
$letter->setPaper($paper);
![Page 18: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/18.jpg)
NoteToo many constructor parameters is a code smell
Two-phase construction is Bad(TM)
![Page 19: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/19.jpg)
Rule of thumb• Constructor injection for required dependencies• Setter injection for optional dependencies
![Page 20: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/20.jpg)
How about usage?$paper = new AirmailPaper('A4');
$envelope = new Envelope('DL');
$letter = new Letter($paper, $envelope);
$letter->write("Dear John, ...");
Setup of dependencies gets tedious quickly
![Page 21: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/21.jpg)
Dependency Injection Container
A DIC is an object that handles the creation of objectsand their dependencies for you
Dependency resolution can be automatic or configured
DICs are optional
![Page 22: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/22.jpg)
Write a simple containerclass LetterContainer
{
public function getLetter()
{
$paper = new AirmailPaper('A4');
$envelope = new Envelope('DL');
$letter = new Letter($paper, $envelope);
return $letter;
}
}
![Page 23: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/23.jpg)
Usage$container = new LetterContainer()
$letter = $container->getLetter();
![Page 24: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/24.jpg)
Handle configurationclass LetterContainer
{
protected $params;
public function __construct(array $params)
{
$this->params = $params;
}
![Page 25: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/25.jpg)
cont… public function getLetter()
{
$paper = new AirmailPaper(
$this->params['paper.size']);
$envelope = new Envelope(
$this->params['envelope.size']);
$letter = new Letter($paper, $envelope);
return $letter;
}
}
![Page 26: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/26.jpg)
Usage// usage:
$container = new LetterContainer(array(
'paper.size' => 'A4',
'envelope.size' => 'DL',
))
$letter = $container->getLetter();
Now, it’s easy to change parameters of the dependentobjects
![Page 27: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/27.jpg)
Shared objectsclass LetterContainer
{
protected $shared;
// ...
public function getLetter()
{
if (!isset(self::$shared['letter'])) {
// ... create $letter as before ...
self::$shared['letter'] = $letter;
}
return self::$shared['letter'];
}
}
![Page 28: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/28.jpg)
Dependency Injection Container
• Creates objects on demand• Manages construction of an object’s dependencies• Separates of configuration from construction• Can allow for shared objects
However:
Writing and maintaining a container class by hand istedious!
![Page 29: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/29.jpg)
Available DICsDon’t reinvent the wheel
• Pimple by Fabien Potencier• Dice by Tom Butler• SymfonyContainer - part of Symfony2• ZendDi & ZendServiceManager - part of ZF 2
![Page 30: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/30.jpg)
Pimple• Easy to use• Small: only 70 lines of PHP• Configured manually
![Page 31: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/31.jpg)
Pimple$container = new Pimple();
$container['letter'] = function ($c) {
$paper = new AirmailPaper('A4');
$envelope = new Envelope('DL');
$letter = new Letter($paper, $envelope);
return $letter;
};
![Page 32: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/32.jpg)
Pimple usage$container = new Pimple();
$letter = $container['letter'];
![Page 33: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/33.jpg)
More typically$container = new Pimple();
$container['paper.size'] = 'DL';
$container['envelope.size'] = 'DL';
$container['paper'] = function ($c) {
$size = $c['paper.size'];
return new AirmailPaper($size);
};
$container['envelope'] = function ($c) {
$size = $c['envelope.size'];
return new Envelope($size);
};
![Page 34: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/34.jpg)
cont…$container['letter'] = function ($c) {
$paper = $c['paper'];
$envelope = $c['envelope'];
return new Letter($paper, $envelope);
};
Usage is identical:
$container = new Pimple();
$letter = $container['letter'];
![Page 35: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/35.jpg)
Recommendation• Hold configuration separately• Create each each object separately
![Page 36: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/36.jpg)
Automatic resolutionclass Letter
{
protected $paper;
public function __construct(AirmailPaper $paper)
{
$this->paper = $paper;
}
}
Usage:
$di = new Zend\Di\Di();
$letter = $di->get('Letter');
![Page 37: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/37.jpg)
ZendDi configurationbeforehand:
$di->instanceManager()->setParameters('AirmailPaper',
array(
'size' => 'A4',
)
);
when retrieving:
$letter = $di->get('Letter', array('size' => 'A4'));
![Page 38: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/38.jpg)
Service Locationclass Letter
{
protected $paper;
public function __construct($locator)
{
$this->paper = $locator->get('paper');
}
}
![Page 39: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/39.jpg)
Service Location• Application pulls its dependencies in when it needs
them• Still decouples concrete implementation of Paper
from Letter
![Page 40: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/40.jpg)
RecapDependency injection promotes:
• loose coupling• easier testing• separation of configuration from usage
![Page 41: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/41.jpg)
“Dependency Injection” is a 25-dollar term for a5-cent concept.
James Shore
![Page 42: Introducing Dependency Injection · Dependency Injection Container • Creates objects on demand • Manages construction of an object’s dependencies • Separates of configuration](https://reader030.vdocuments.net/reader030/viewer/2022040215/5ecd82136466ba57552f193c/html5/thumbnails/42.jpg)
Thank you!https://joind.in/9263
Rob Allen - http://akrabat.com - @akrabat