Your SlideShare is downloading. ×
Real World Dependency Injection - IPC11 Spring Edition
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Real World Dependency Injection - IPC11 Spring Edition

1,238
views

Published on


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,238
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
25
Comments
0
Likes
1
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. Real World Dependency Injection
  • 2. Real World Dependency Injection About me  Stephan Hochdörfer, bitExpert AG  Department Manager Research Labs  enjoying PHP since 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • 3. Real World Dependency Injection What are Dependencies?
  • 4. What are Dependencies? Application Framework add. Libraries Real World Dependency Injection
  • 5. What are Dependencies? Controller Service / Model Datastore(s) UtilsPHP extensions Real World Dependency Injection
  • 6. Are Dependencies bad? Real World Dependency Injection
  • 7. Are Dependencies bad? Dependencies are not bad! Real World Dependency Injection
  • 8. Are Dependencies bad? They are useful! Real World Dependency Injection
  • 9. Are Dependencies bad? Hard-coded dependencies are bad! Real World Dependency Injection
  • 10. Tightly coupled code Real World Dependency Injection
  • 11. No reuse of components Real World Dependency Injection
  • 12. No isolation, not testable! Real World Dependency Injection
  • 13. Real World Dependency Injection Development gets overcomplicated!
  • 14. Real World Dependency Injection „new“ is evil!
  • 15. <?php class 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') ); } } Real World Dependency Injection „new“ is evil!
  • 16. Real World Dependency Injection „new“ is evil! <?php class 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') ); } }
  • 17. "High-level modules should not depend on low-level modules. Both should depend on abstractions." Robert C. Martin Real World Dependency Injection
  • 18. Interfaces act as contracts Real World Dependency Injection
  • 19. Real World Dependency Injection „new“ is evil! <?php class 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') ); } }
  • 20. How to Manage Dependencies? Real World Dependency Injection
  • 21. Manually resolve dependencies? Real World Dependency Injection
  • 22. Automatic wiring required! Simple Container vs. Full stacked DI Framework Real World Dependency Injection
  • 23. What is Dependency Injection? Real World Dependency Injection
  • 24. What is Dependency Injection? Consumer Real World Dependency Injection
  • 25. What is Dependency Injection? Consumer Dependencies Real World Dependency Injection
  • 26. What is Dependency Injection? Consumer Dependencies Container Real World Dependency Injection
  • 27. What is Dependency Injection? Consumer Dependencies Container Real World Dependency Injection
  • 28. How to inject a Dependency? Real World Dependency Injection
  • 29. Constructor Injection <?php class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao; public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } } Real World Dependency Injection
  • 30. Setter injection <?php class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao; public function setSampleDao(ISampleDao $sampleDao){ $this->sampleDao = $sampleDao; } } Real World Dependency Injection
  • 31. Interface injection <?php interface IApplicationContextAware { public function setCtx(IApplicationContext $ctx); } Real World Dependency Injection
  • 32. Interface injection <?php class MySampleService implements IMySampleService, IApplicationContextAware { /** * @var IApplicationContext */ private $ctx; public function setCtx(IApplicationContext $ctx) { $this->ctx = $ctx; } } Real World Dependency Injection
  • 33. Real World Dependency Injection How to wire it all up?
  • 34. Real World Dependency Injection Annotation based wiring <?php class MySampleService implements IMySampleService { private $sampleDao; /** * @Inject */ public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } }
  • 35. Real World Dependency Injection Annotation based wiring <?php class MySampleService implements IMySampleService { private $sampleDao; /** * @Inject * @Named('TheSampleDao') */ public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } }
  • 36. External configuration - 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> Real World Dependency Injection
  • 37. External configuration - YAML services: SampleDao: class: SampleDao arguments: ['app_sample', 'iSampleId', 'BoSample'] SampleService: class: SampleService arguments: [@SampleDao] Real World Dependency Injection
  • 38. External configuration - PHP <?php class 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; } } Real World Dependency Injection
  • 39. Why Dependency Injection? Real World Dependency Injection DI vs. Registry vs. Service Locator
  • 40. Real World Dependency Injection Ready to unlock the door?
  • 41. Unittesting made easy Real World Dependency Injection
  • 42. Unittesting made easy <?php require_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); } } Real World Dependency Injection
  • 43. One class, multiple configurations Real World Dependency Injection
  • 44. One class, multiple configurations Page ExporterPage Exporter Released / Published Pages Released / Published Pages Real World Dependency Injection
  • 45. One class, multiple configurations Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection
  • 46. One class, multiple configurations <?php abstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Real World Dependency Injection
  • 47. One class, multiple configurations <?php abstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Remember: The contract! Real World Dependency Injection
  • 48. One class, multiple configurations <?php class PublishedPageExporter extends PageExporter { public function __construct() { $this->setPageDao(new PublishedPageDao()); } } class WorkingCopyPageExporter extends PageExporter { public function __construct() { $this->setPageDao(new WorkingCopyPageDao()); } } Real World Dependency Injection
  • 49. "Only deleted code is good code!" Oliver Gierke One class, multiple configurations Real World Dependency Injection
  • 50. One class, multiple configurations <?php class PageExporter { public function __construct(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Real World Dependency Injection
  • 51. One class, multiple configurations <?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> Real World Dependency Injection
  • 52. One class, multiple configurations <?php // create ApplicationContext instance $ctx = new ApplicationContext(); // retrieve live exporter $exporter = $ctx->getBean('ExportLive'); // retrieve working copy exporter $exporter = $ctx->getBean('ExportWorking'); Real World Dependency Injection
  • 53. One class, multiple configurations II Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection
  • 54. One class, multiple configurations II Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection HTMLHTML
  • 55. One class, multiple configurations II Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection PDFPDFHTMLHTML
  • 56. One class, multiple configurations II <?xml version="1.0" encoding="UTF-8" ?> <beans> <bean id="ExportLive" class="PageExporter"> <constructor-arg ref="PublishedPageDao" /> <constructor-arg ref="HTMLExporter" /> </bean> <bean id="ExportWorking" class="PageExporter"> <constructor-arg ref="WorkingCopyPageDao" /> <constructor-arg ref="PDFExporter" /> </bean> </beans> Real World Dependency Injection
  • 57. One class, multiple configurations III Real World Dependency Injection
  • 58. One class, multiple configurations III http://editor.loc/page/[id]/headline/ http://editor.loc/page/[id]/content/ http://editor.loc/page/[id]/teaser/ Real World Dependency Injection
  • 59. <?php class EditPart extends Mvc_Action_AFormAction { private $pagePartsManager; private $type; public function __construct(IPagePartsManager $pm) { $this->pagePartsManager = $pm; } public function setType($ptype) { $this->type = (int) $type; } protected function process(Bo_ABo $formBackObj) { } } One class, multiple configurations III Real World Dependency Injection
  • 60. One class, multiple configurations III <?xml version="1.0" encoding="UTF-8" ?> <beans> <bean id="EditHeadline" class="EditPart"> <constructor-arg ref="PagePartDao" /> <property name="Type" const="PType::Headline" /> </bean> <bean id="EditContent" class="EditPart"> <constructor-arg ref="PagePartDao" /> <property name="Type" const="PType::Content" /> </bean> </beans> Real World Dependency Injection
  • 61. Mocking external service access Real World Dependency Injection
  • 62. Mocking external service access Booking serviceBooking service Real World Dependency Injection
  • 63. Mocking external service access Booking serviceBooking service WS- Connector WS- Connector Real World Dependency Injection
  • 64. Mocking external service access Booking serviceBooking service WS- Connector WS- Connector WebserviceWebservice Real World Dependency Injection
  • 65. Mocking external service access Booking serviceBooking service WS- Connector WS- Connector WebserviceWebservice Remember: The contract! Real World Dependency Injection
  • 66. Mocking external service access Booking serviceBooking service FS- Connector FS- Connector FilesystemFilesystem Real World Dependency Injection
  • 67. Mocking external service access Booking serviceBooking service FS- Connector FS- Connector FilesystemFilesystem fullfills the contract! Real World Dependency Injection
  • 68. Clean, readable code Real World Dependency Injection
  • 69. Clean, readable code <?php class 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()); } } Real World Dependency Injection
  • 70. No framework dependency Real World Dependency Injection
  • 71. No framework dependency <?php class 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) {} } } Real World Dependency Injection
  • 72. Benefits Loose coupling, reuse of components! Real World Dependency Injection
  • 73. Benefits Can reduce the amount of code! Real World Dependency Injection
  • 74. Benefits Helps developers to understand the code! Real World Dependency Injection
  • 75. Cons – No JSR330 for PHP Bucket, Crafty, FLOW3, Imind_Context, PicoContainer, Pimple, Phemto, Stubbles, Symfony 2.0, Sphicy, Solar, Substrate, XJConf, Yadif, Zend_Di (Proposal), Lion Framework, Spiral Framework, Xyster Framework, … Real World Dependency Injection
  • 76. Cons – Developers need mindshift Configuration ↔ Runtime Real World Dependency Injection
  • 77. http://joind.in/3522
  • 78. Image Credits http://www.sxc.hu/photo/1028452