Dependency Injection in PHP - dwx13

  • 988 views
Uploaded on

 

More in: Technology , Business
  • 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
988
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
7
Comments
0
Likes
3

Embeds 0

No embeds

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!