Dependency Injection in PHP - dwx13
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,376
On Slideshare
1,341
From Embeds
35
Number of Embeds
2

Actions

Shares
Downloads
7
Comments
0
Likes
3

Embeds 35

http://lanyrd.com 31
https://twitter.com 4

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Dependency InjectionWas, wie, warum?Stephan Hochdörfer, bitExpert AG
  • 2. Dependency Injection – Was, wie warum?Über mich Stephan Hochdörfer Head of IT der bitExpert AG, Mannheim PHP`ler seit 1999 S.Hochdoerfer@bitExpert.de @shochdoerfer
  • 3. Dependency Injection – Was, wie warum?DI ist nicht alles. Es geht um mehr.
  • 4. Dependency Injection – Was, wie warum?Separation of Concerns
  • 5. Design by ContractDependency Injection – Was, wie warum?
  • 6. Dependency Injection – Was, wie warum?Dependency Injection
  • 7. Dependency Injection – Was, wie warum?Dependency Injection"[...] zur Laufzeit die Abhängigkeiteneines Objekts diesem von einemanderen Objekt als Referenzen zurVerfügung gestellt werden."(Wikipedia)
  • 8. Dependency Injection – Was, wie warum?Was sind Dependencies?
  • 9. Dependency Injection – Was, wie warum?Sind Dependencies schlecht?
  • 10. Dependency Injection – Was, wie warum?Dependencies: Starke Kopplung
  • 11. Keine Wiederverwendung!Dependency Injection – Was, wie warum?
  • 12. Keine Isolation, nicht testbar!Dependency Injection – Was, wie warum?
  • 13. Dependency Injection – Was, wie warum?Dependency Wahnsinn!
  • 14. Was ist Dependency Injection?Dependency Injection – Was, wie warum?
  • 15. Was ist Dependency Injection?Dependency Injection – Was, wie warum?new DeletePage(new PageManager());
  • 16. Was ist Dependency Injection?ConsumerDependency Injection – Was, wie warum?
  • 17. Was ist Dependency Injection?Consumer DependenciesDependency Injection – Was, wie warum?
  • 18. Was ist Dependency Injection?Consumer Dependencies ContainerDependency Injection – Was, wie warum?
  • 19. Was ist Dependency Injection?Consumer Dependencies ContainerDependency Injection – Was, wie warum?
  • 20. sDependency Injection – Was, wie warum?„new“ is evil!
  • 21. <?phpclass DeletePage extends Mvc_Action_AAction {private $pageManager;public function __construct() {$this->pageManager = new PageManager();}protected function execute(Mvc_Request $request) {$this->pageManager->delete((int) $request->get(pageId));}}Dependency Injection – Was, wie warum?„new“ is evil!
  • 22. Dependency Injection – Was, wie warum?„new“ is evil!<?phpclass DeletePage extends Mvc_Action_AAction {private $pageManager;public function __construct(PageManager $pm) {$this->pageManager = $pm;}protected function execute(Mvc_Request $request) {$this->pageManager->delete((int) $request->get(pageId));}}
  • 23. "High-level modules should notdepend on low-level modules.Both should depend on abstractions."Robert C. MartinDependency Injection – Was, wie warum?
  • 24. Dependency Injection – Was, wie warum?„new“ is evil!<?phpclass DeletePage extends Mvc_Action_AAction {private $pageManager;public function __construct(IPageManager $pm) {$this->pageManager = $pm;}protected function execute(Mvc_Request $request) {$this->pageManager->delete((int) $request->get(pageId));}}
  • 25. Wie verwaltet man Dependencies?Dependency Injection – Was, wie warum?
  • 26. Wie verwaltet man Dependencies?Simple Container vs. Full stackedDI FrameworkDependency Injection – Was, wie warum?
  • 27. Der Container nimmt uns die Arbeit ab!Dependency Injection – Was, wie warum?
  • 28. Wie Dependencies injizieren?Dependency Injection – Was, wie warum?
  • 29. Constructor Injection<?phpclass MySampleService implements IMySampleService {/*** @var ISampleDao*/private $sampleDao;public function __construct(ISampleDao $sampleDao) {$this->sampleDao = $sampleDao;}}Dependency Injection – Was, wie warum?
  • 30. Setter Injection<?phpclass MySampleService implements IMySampleService {/*** @var ISampleDao*/private $sampleDao;public function setSampleDao(ISampleDao $sampleDao){$this->sampleDao = $sampleDao;}}Dependency Injection – Was, wie warum?
  • 31. Interface Injection<?phpinterface IApplicationContextAware {public function setCtx(IApplicationContext $ctx);}Dependency Injection – Was, wie warum?
  • 32. Interface Injection<?phpclass MySampleService implements IMySampleService,IApplicationContextAware {/*** @var IApplicationContext*/private $ctx;public function setCtx(IApplicationContext $ctx) {$this->ctx = $ctx;}}Dependency Injection – Was, wie warum?
  • 33. Property InjectionDependency Injection – Was, wie warum?
  • 34. Property InjectionDependency Injection – Was, wie warum?"NEIN NEIN NEIN!"David Zülke
  • 35. Wie funktioniert das „Wiring“?Dependency Injection – Was, wie warum?
  • 36. Dependency Injection – Was, wie warum?Annotations<?phpclass MySampleService implements IMySampleService {private $sampleDao;/*** @Inject*/public function __construct(ISampleDao $sampleDao){$this->sampleDao = $sampleDao;}}
  • 37. Dependency Injection – Was, wie warum?Annotations<?phpclass MySampleService implements IMySampleService {private $sampleDao;/*** @Inject* @Named(TheSampleDao)*/public function __construct(ISampleDao $sampleDao){$this->sampleDao = $sampleDao;}}
  • 38. Externe Konfiguration - XML<?xml version="1.0" encoding="UTF-8" ?><beans><bean id="SampleDao" class="SampleDao"><constructor-arg value="app_sample" /><constructor-arg value="iSampleId" /><constructor-arg value="BoSample" /></bean><bean id="SampleService" class="MySampleService"><constructor-arg ref="SampleDao" /></bean></beans>Dependency Injection – Was, wie warum?
  • 39. Externe Konfiguration - YAMLservices:SampleDao:class: SampleDaoarguments: [app_sample, iSampleId, BoSample]SampleService:class: SampleServicearguments: [@SampleDao]Dependency Injection – Was, wie warum?
  • 40. Externe Konfiguration - PHP<?phpclass BeanCache extends Beanfactory_Container_PHP {protected function createSampleDao() {$oBean = new SampleDao(app_sample,iSampleId, BoSample);return $oBean;}protected function createMySampleService() {$oBean = new MySampleService($this->getBean(SampleDao));return $oBean;}}Dependency Injection – Was, wie warum?
  • 41. Interne vs. Externe KonfigurationDependency Injection – Was, wie warum?
  • 42. Interne vs. Externe KonfigurationDependency Injection – Was, wie warum?Klassenkonfigurationvs.Instanzkonfiguration
  • 43. Dependency Injection – Was, wie warum?Was bringt mir das? Beispiel bitte.
  • 44. Unittesting einfach gemachtDependency Injection – Was, wie warum?
  • 45. Unittesting einfach gemacht<?phprequire_once PHPUnit/Framework.php;class ServiceTest extends PHPUnit_Framework_TestCase {public function testSampleService() {// set up dependencies$sampleDao = $this->getMock(ISampleDao);$service = new MySampleService($sampleDao);// run test case$return = $service->doWork();// check assertions$this->assertTrue($return);}}Dependency Injection – Was, wie warum?
  • 46. Eine Klasse, mehrfache AusprägungDependency Injection – Was, wie warum?
  • 47. Eine Klasse, mehrfache AusprägungPage ExporterPage ExporterReleased / PublishedPagesReleased / PublishedPagesWorkingcopyPagesWorkingcopyPagesDependency Injection – Was, wie warum?
  • 48. Eine Klasse, mehrfache Ausprägung<?phpabstract class PageExporter {protected function setPageDao(IPageDao $pageDao) {$this->pageDao = $pageDao;}}Dependency Injection – Was, wie warum?
  • 49. Eine Klasse, mehrfache Ausprägung<?phpabstract class PageExporter {protected function setPageDao(IPageDao $pageDao) {$this->pageDao = $pageDao;}}Zur Erinnerung:Der Vertrag!Dependency Injection – Was, wie warum?
  • 50. Eine Klasse, mehrfache Ausprägung<?phpclass PublishedPageExporter extends PageExporter {public function __construct() {$this->setPageDao(new PublishedPageDao());}}class WorkingCopyPageExporter extends PageExporter {public function __construct() {$this->setPageDao(new WorkingCopyPageDao());}}Dependency Injection – Was, wie warum?
  • 51. "Only deleted code is good code!"Oliver GierkeEine Klasse, mehrfache AusprägungDependency Injection – Was, wie warum?
  • 52. Eine Klasse, mehrfache Ausprägung<?phpclass PageExporter {public function __construct(IPageDao $pageDao) {$this->pageDao = $pageDao;}}Dependency Injection – Was, wie warum?
  • 53. Eine Klasse, mehrfache Ausprägung<?xml version="1.0" encoding="UTF-8" ?><beans><bean id="ExportLive" class="PageExporter"><constructor-arg ref="PublishedPageDao" /></bean><bean id="ExportWorking" class="PageExporter"><constructor-arg ref="WorkingCopyPageDao" /></bean></beans>Dependency Injection – Was, wie warum?
  • 54. Eine Klasse, mehrfache Ausprägung<?php// create ApplicationContext instance$ctx = new ApplicationContext();// retrieve live exporter$exporter = $ctx->getBean(ExportLive);// retrieve working copy exporter$exporter = $ctx->getBean(ExportWorking);Dependency Injection – Was, wie warum?
  • 55. Externe Services mockenDependency Injection – Was, wie warum?
  • 56. Externe Services mockenBookingmanagerBookingmanager WS-KonnektorWS-Konnektor WebserviceWebserviceDependency Injection – Was, wie warum?
  • 57. Externe Services mockenBookingmanagerBookingmanager WS-KonnektorWS-Konnektor WebserviceWebserviceDependency Injection – Was, wie warum?Zur Erinnerung:Der Vertrag!
  • 58. Externe Services mockenBookingmanagerBookingmanager FS-KonnektorFS-Konnektor FilesystemFilesystemDependency Injection – Was, wie warum?
  • 59. Externe Services mockenBookingmanagerBookingmanager FS-KonnektorFS-Konnektor FilesystemFilesystemerfüllt denVertrag!Dependency Injection – Was, wie warum?
  • 60. Sauberer, lesbarer CodeDependency Injection – Was, wie warum?
  • 61. Sauberer, lesbarer Code<?phpclass DeletePage extends Mvc_Action_AAction {private $pageManager;public function __construct(IPageManager $pm) {$this->pageManager = $pm;}protected function execute(Mvc_Request $request) {$this->pageManager->delete((int) $request->get(pageId));return new ModelAndView($this->getSuccessView());}}Dependency Injection – Was, wie warum?
  • 62. Keine Framework AbhängigkeitDependency Injection – Was, wie warum?
  • 63. Keine Framework Abhängigkeit<?phpclass MySampleService implements IMySampleService {private $sampleDao;public function __construct(ISampleDao $sampleDao) {$this->sampleDao = $sampleDao;}public function getSample($sampleId) {try {return $this->sampleDao->readById($sampleId);}catch(DaoException $exception) {}}}Dependency Injection – Was, wie warum?
  • 64. Dependency Injection – Was, wie warum?Wie siehst das nun in der Praxis aus?
  • 65. Dependency Injection – Was, wie warum?Pimple
  • 66. Pimple – Erste SchritteDependency Injection – Was, wie warum?<?phpclass TalkService {public function __construct() {}public function getTalks() {}}
  • 67. Pimple – Erste SchritteDependency Injection – Was, wie warum?<?phprequire_once /path/to/Pimple.php;require_once /path/to/TalkService.php;// create the Container$container = new Pimple();// define talkService object in container$container[talkService] = function ($c) {return new TalkService();};// instantiate talkService from container$talkService = $container[talkService];
  • 68. Pimple – Constructor InjectionDependency Injection – Was, wie warum?<?phpinterface GenericRepository {public function readTalks();}class TalkRepository implements GenericRepository {public function readTalks() {}}class TalkService {public function __construct(TalkRepository $repo) {}public function getTalks() {}}
  • 69. Pimple – Constructor InjectionDependency Injection – Was, wie warum?<?phprequire_once /path/to/Pimple.php;require_once /path/to/TalkService.php;// create the Container$container = new Pimple();// define services in container$container[talkRepository] = function ($c) {return new TalkRepository();};$container[talkService] = function ($c) {return new TalkService($c[talkRepository]);};// instantiate talkService from container$talkService = $container[talkService];
  • 70. Pimple – Setter InjectionDependency Injection – Was, wie warum?<?phpclass Logger {public function doLog($logMsg) {}}class TalkService {public function __construct(TalkRepository $repo) {}public function setLogger(Logger $logger) {}public function getTalks() {}}
  • 71. Pimple – Setter InjectionDependency Injection – Was, wie warum?<?phprequire_once /path/to/Pimple.php;require_once /path/to/TalkService.php;// create the Container$container = new Pimple();// define services in container$container[logger] = function ($c) {return new Logger();};$container[talkRepository] = function ($c) {return new TalkRepository();};$container[talkService] = function ($c) {$service = new TalkService($c[talkRepository]);$service->setLogger($c[logger]);return $service;};// instantiate talkService from container$talkService = $container[talkService];
  • 72. Dependency Injection – Was, wie warum?
  • 73. ZendDi – Erste SchritteDependency Injection – Was, wie warum?<?phpnamespace Acme;class TalkService {public function __construct() {}public function getTalks() {}}
  • 74. ZendDi – Erste SchritteDependency Injection – Was, wie warum?<?php$di = new ZendDiDi();$service = $di->get(AcmeTalkService);$service->getTalks();
  • 75. ZendDi – Constructor InjectionDependency Injection – Was, wie warum?<?phpnamespace Acme;interface GenericRepository {public function readTalks();}class TalkRepository implements GenericRepository {public function readTalks() {}}class TalkService {public function __construct(TalkRepository $repo) {}public function getTalks() {}}
  • 76. ZendDi – Constructor InjectionDependency Injection – Was, wie warum?<?php$di = new ZendDiDi();$service = $di->get(AcmeTalkService);$service->getTalks();
  • 77. ZendDi – Setter InjectionDependency Injection – Was, wie warum?<?phpnamespace Acme;class Logger {public function doLog($logMsg) {}}class TalkService {public function __construct(TalkRepository $repo) {}public function setLogger(Logger $logger) {}public function getTalks() {}}
  • 78. ZendDi – Setter InjectionDependency Injection – Was, wie warum?<?php$di = new ZendDiDi();$di->configure(new ZendDiConfiguration(array(definition => array(class => array(AcmeTalkService => array(setLogger => array(required => true)))))));$service = $di->get(AcmeTalkService);var_dump($service);
  • 79. ZendDi – Interface InjectionDependency Injection – Was, wie warum?<?phpnamespace Acme;class Logger {public function doLog($logMsg) {}}interface LoggerAware {public function setLogger(Logger $logger);}class TalkService implements LoggerAware {public function __construct(TalkRepository $repo) {}public function setLogger(Logger $logger) {}public function getTalks() {}}
  • 80. ZendDi – Interface InjectionDependency Injection – Was, wie warum?<?php$di = new ZendDiDi();$service = $di->get(AcmeTalkService);$service->getTalks();
  • 81. ZendDi – GrundsätzlichesDependency Injection – Was, wie warum?<?php$di = new ZendDiDi();$service = $di->get(AcmeTalkService);var_dump($service);$service2 = $di->get(AcmeTalkService);var_dump($service2); // same instance as $service$service3 = $di->get(AcmeTalkService,array(repo => new AcmeTalkRepository()));
  • 82. ZendDi – Builder DefinitionDependency Injection – Was, wie warum?<?php// describe dependency$dep = new ZendDiDefinitionBuilderPhpClass();$dep->setName(AcmeTalkRepository);// describe class$class = new ZendDiDefinitionBuilderPhpClass();$class->setName(AcmeTalkService);// add injection method$im = new ZendDiDefinitionBuilderInjectionMethod();$im->setName(__construct);$im->addParameter(repo, AcmeTalkRepository);$class->addInjectionMethod($im);// configure builder$builder = new ZendDiDefinitionBuilderDefinition();$builder->addClass($dep);$builder->addClass($class);
  • 83. ZendDi – Builder DefinitionDependency Injection – Was, wie warum?<?php// add to Di$defList = new ZendDiDefinitionList($builder);$di = new ZendDiDi($defList);$service = $di->get(AcmeTalkService);var_dump($service);
  • 84. Dependency Injection – Was, wie warum?
  • 85. Symfony2Dependency Injection – Was, wie warum?<?phpnamespace AcmeTalkBundleController;use SymfonyBundleFrameworkBundleControllerController;use SensioBundleFrameworkExtraBundleConfigurationRoute;use SensioBundleFrameworkExtraBundleConfigurationTemplate;class TalkController extends Controller {/*** @Route("/", name="_talk")* @Template()*/public function indexAction() {$service = $this->get(acme.talk.service);return array();}}
  • 86. Symfony2 – KonfigurationsdateiDependency Injection – Was, wie warum?<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://symfony.com/schema/dic/services/services-1.0.xsd"></container>File services.xml in src/Acme/DemoBundle/Resources/config
  • 87. Symfony2 – Constructor InjectionDependency Injection – Was, wie warum?<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://symfony.com/schema/dic/services/services-1.0.xsd"><services><service id="acme.talk.repo"class="AcmeTalkBundleServiceTalkRepository" /><service id="acme.talk.service"class="AcmeTalkBundleServiceTalkService"><argument type="service" id="acme.talk.repo" /></service></services></container>
  • 88. Symfony2 – Setter InjectionDependency Injection – Was, wie warum?<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://symfony.com/schema/dic/services/services-1.0.xsd"><services><service id="acme.talk.logger"class="AcmeTalkBundleServiceLogger" /><service id="acme.talk.repo"class="AcmeTalkBundleServiceTalkRepository" /><service id="acme.talk.service"class="AcmeTalkBundleServiceTalkService"><argument type="service" id="acme.talk.repo" /><call method="setLogger"><argument type="service" id="acme.talk.logger" /></call></service></services></container>
  • 89. Symfony2 – Setter Injection (optional)Dependency Injection – Was, wie warum?<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://symfony.com/schema/dic/services/services-1.0.xsd"><services><service id="acme.talk.logger"class="AcmeTalkBundleServiceLogger" /><service id="acme.talk.repo"class="AcmeTalkBundleServiceTalkRepository" /><service id="acme.talk.service"class="AcmeTalkBundleServiceTalkService"><argument type="service" id="acme.talk.repo" /><call method="setLogger"><argument type="service" id="acme.talk.logger"on-invalid="ignore" /></call></service></services></container>
  • 90. Symfony2 – Property InjectionDependency Injection – Was, wie warum?<?xml version="1.0" ?><container xmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/serviceshttp://symfony.com/schema/dic/services/services-1.0.xsd"><services><service id="acme.talk.repo"class="AcmeTalkBundleServiceTalkRepository" /><service id="acme.talk.service"class="AcmeTalkBundleServiceTalkService"><property name="talkRepository" type="service"id="acme.talk.repo" /></service></services></container>
  • 91. Dependency Injection – Was, wie warum?
  • 92. Flow3 – Constructor InjectionDependency Injection – Was, wie warum?<?phpnamespace AcmeDemoController;use TYPO3FLOW3Annotations as FLOW3;/*** @FLOW3Scope("session")*/class StandardController extends TYPO3FLOW3MVCControllerActionController {/*** @var AcmeDemoServiceTalkServiceInterface*/protected $talkService;public function __construct(AcmeDemoServiceTalkService $talkService) {$this->talkService = $talkService;}public function indexAction() {}}
  • 93. Flow3 – Setter Injection (manuell)Dependency Injection – Was, wie warum?<?phpnamespace AcmeDemoController;use TYPO3FLOW3Annotations as FLOW3;/*** @FLOW3Scope("session")*/class StandardController extends TYPO3FLOW3MVCControllerActionController {/*** @var AcmeDemoServiceTalkServiceInterface*/protected $talkService;public function setTalkService(AcmeDemoServiceTalkService $talkService) {$this->talkService = $talkService;}public function indexAction() {}}
  • 94. Flow3 – Setter Injection (manuell)Dependency Injection – Was, wie warum?File Objects.yaml in Packages/Application/Acme.Demo/Configuration# @package AcmeAcmeDemoControllerStandardController:properties:talkService:object: AcmeDemoServiceTalkService
  • 95. Flow3 – Setter Injection (automatisch)Dependency Injection – Was, wie warum?<?phpnamespace AcmeDemoController;use TYPO3FLOW3Annotations as FLOW3;/*** @FLOW3Scope("session")*/class StandardController extends TYPO3FLOW3MVCControllerActionController {/*** @var AcmeDemoServiceTalkServiceInterface*/protected $talkService;public function injectTalkService(AcmeDemoServiceTalkService $talkService) {$this->talkService = $talkService;}public function indexAction() {}}
  • 96. Dependency Injection – Was, wie warum?Fokus aufs Wesentliche. Keine Ablenkung.
  • 97. Dependency Injection – Was, wie warum?Wiederverwendung steigern.
  • 98. Dependency Injection – Was, wie warum?Hilft den Code besser zu verstehen.
  • 99. Dependency Injection – Was, wie warum?Wieder Spaß bei der Arbeit ;)
  • 100. Dependency Injection – Was, wie warum?Kein Standard. Kein Tooling.
  • 101. Dependency Injection – Was, wie warum?Es braucht Zeit um DI zu verstehen.
  • 102. Dependency Injection – Was, wie warum?Konfiguration vs. Laufzeit
  • 103. Vielen Dank!