Real World
Dependency Injection
Real World Dependency Injection
About me
 Stephan Hochdörfer, bitExpert AG
 Department Manager Research Labs
 enjoying PHP since 1999
 S.Hochdoerfer@bitExpert.de
 @shochdoerfer
Real World Dependency Injection
What are Dependencies?
What are Dependencies?
Application
Framework add. Libraries
Real World Dependency Injection
What are Dependencies?
Controller
Service / Model
Datastore(s)
UtilsPHP extensions
Real World Dependency Injection
Are Dependencies bad?
Real World Dependency Injection
Are Dependencies bad?
Dependencies are not bad!
Real World Dependency Injection
Are Dependencies bad?
They are useful!
Real World Dependency Injection
Are Dependencies bad?
Hard-coded dependencies are bad!
Real World Dependency Injection
Tightly coupled code
Real World Dependency Injection
No reuse of components
Real World Dependency Injection
No isolation, not testable!
Real World Dependency Injection
Real World Dependency Injection
Development gets overcomplicated!
Real World Dependency Injection
„new“ is evil!
<?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!
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')
);
}
}
"High-level modules should not
depend on low-level modules.
Both should depend on
abstractions."
Robert C. Martin
Real World Dependency Injection
Interfaces act as contracts
Real World Dependency Injection
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')
);
}
}
How to Manage Dependencies?
Real World Dependency Injection
Manually resolve dependencies?
Real World Dependency Injection
Automatic wiring required!
Simple Container vs. Full stacked
DI Framework
Real World Dependency Injection
What is Dependency Injection?
Real World Dependency Injection
What is Dependency Injection?
Consumer
Real World Dependency Injection
What is Dependency Injection?
Consumer Dependencies
Real World Dependency Injection
What is Dependency Injection?
Consumer Dependencies Container
Real World Dependency Injection
What is Dependency Injection?
Consumer Dependencies Container
Real World Dependency Injection
How to inject a Dependency?
Real World Dependency Injection
Constructor Injection
<?php
class MySampleService implements IMySampleService {
/**
* @var ISampleDao
*/
private $sampleDao;
public function __construct(ISampleDao $sampleDao) {
$this->sampleDao = $sampleDao;
}
}
Real World Dependency Injection
Setter injection
<?php
class MySampleService implements IMySampleService {
/**
* @var ISampleDao
*/
private $sampleDao;
public function setSampleDao(ISampleDao $sampleDao){
$this->sampleDao = $sampleDao;
}
}
Real World Dependency Injection
Interface injection
<?php
interface IApplicationContextAware {
public function setCtx(IApplicationContext $ctx);
}
Real World Dependency Injection
Interface injection
<?php
class MySampleService implements IMySampleService,
IApplicationContextAware {
/**
* @var IApplicationContext
*/
private $ctx;
public function setCtx(IApplicationContext $ctx) {
$this->ctx = $ctx;
}
}
Real World Dependency Injection
Real World Dependency Injection
How to wire it all up?
Real World Dependency Injection
Annotation based wiring
<?php
class MySampleService implements IMySampleService {
private $sampleDao;
/**
* @Inject
*/
public function __construct(ISampleDao $sampleDao)
{
$this->sampleDao = $sampleDao;
}
}
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;
}
}
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
External configuration - YAML
services:
SampleDao:
class: SampleDao
arguments: ['app_sample', 'iSampleId', 'BoSample']
SampleService:
class: SampleService
arguments: [@SampleDao]
Real World Dependency Injection
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
Why Dependency Injection?
Real World Dependency Injection
DI vs. Registry vs. Service Locator
Real World Dependency Injection
Ready to unlock the door?
Unittesting made easy
Real World Dependency Injection
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
One class, multiple configurations
Real World Dependency Injection
One class, multiple configurations
Page ExporterPage Exporter
Released / Published
Pages
Released / Published
Pages
Real World Dependency Injection
One class, multiple configurations
Page ExporterPage Exporter
Released / Published
Pages
Released / Published
Pages
Workingcopy
Pages
Workingcopy
Pages
Real World Dependency Injection
One class, multiple configurations
<?php
abstract class PageExporter {
protected function setPageDao(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
Real World Dependency Injection
One class, multiple configurations
<?php
abstract class PageExporter {
protected function setPageDao(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
Remember:
The contract!
Real World Dependency Injection
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
"Only deleted code is good code!"
Oliver Gierke
One class, multiple configurations
Real World Dependency Injection
One class, multiple configurations
<?php
class PageExporter {
public function __construct(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
Real World Dependency Injection
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
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
One class, multiple configurations II
Page ExporterPage Exporter
Released / Published
Pages
Released / Published
Pages
Workingcopy
Pages
Workingcopy
Pages
Real World Dependency Injection
One class, multiple configurations II
Page ExporterPage Exporter
Released / Published
Pages
Released / Published
Pages
Workingcopy
Pages
Workingcopy
Pages
Real World Dependency Injection
HTMLHTML
One class, multiple configurations II
Page ExporterPage Exporter
Released / Published
Pages
Released / Published
Pages
Workingcopy
Pages
Workingcopy
Pages
Real World Dependency Injection
PDFPDFHTMLHTML
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
One class, multiple configurations III
Real World Dependency Injection
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
<?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
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
Mocking external service access
Real World Dependency Injection
Mocking external service access
Booking serviceBooking service
Real World Dependency Injection
Mocking external service access
Booking serviceBooking service WS-
Connector
WS-
Connector
Real World Dependency Injection
Mocking external service access
Booking serviceBooking service WS-
Connector
WS-
Connector WebserviceWebservice
Real World Dependency Injection
Mocking external service access
Booking serviceBooking service WS-
Connector
WS-
Connector WebserviceWebservice
Remember:
The contract!
Real World Dependency Injection
Mocking external service access
Booking serviceBooking service FS-
Connector
FS-
Connector FilesystemFilesystem
Real World Dependency Injection
Mocking external service access
Booking serviceBooking service FS-
Connector
FS-
Connector FilesystemFilesystem
fullfills the
contract!
Real World Dependency Injection
Clean, readable code
Real World Dependency Injection
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
No framework dependency
Real World Dependency Injection
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
Benefits
Loose coupling, reuse of components!
Real World Dependency Injection
Benefits
Can reduce the amount of code!
Real World Dependency Injection
Benefits
Helps developers to
understand the code!
Real World Dependency Injection
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
Cons – Developers need mindshift
Configuration ↔ Runtime
Real World Dependency Injection
http://joind.in/3522
Image Credits
http://www.sxc.hu/photo/1028452

Real World Dependency Injection - IPC11 Spring Edition

  • 1.
  • 2.
    Real World DependencyInjection About me  Stephan Hochdörfer, bitExpert AG  Department Manager Research Labs  enjoying PHP since 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • 3.
    Real World DependencyInjection What are Dependencies?
  • 4.
    What are Dependencies? Application Frameworkadd. Libraries Real World Dependency Injection
  • 5.
    What are Dependencies? Controller Service/ Model Datastore(s) UtilsPHP extensions Real World Dependency Injection
  • 6.
    Are Dependencies bad? RealWorld Dependency Injection
  • 7.
    Are Dependencies bad? Dependenciesare not bad! Real World Dependency Injection
  • 8.
    Are Dependencies bad? Theyare useful! Real World Dependency Injection
  • 9.
    Are Dependencies bad? Hard-codeddependencies are bad! Real World Dependency Injection
  • 10.
    Tightly coupled code RealWorld Dependency Injection
  • 11.
    No reuse ofcomponents Real World Dependency Injection
  • 12.
    No isolation, nottestable! Real World Dependency Injection
  • 13.
    Real World DependencyInjection Development gets overcomplicated!
  • 14.
    Real World DependencyInjection „new“ is evil!
  • 15.
    <?php class DeletePage extendsMvc_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 DependencyInjection „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 shouldnot depend on low-level modules. Both should depend on abstractions." Robert C. Martin Real World Dependency Injection
  • 18.
    Interfaces act ascontracts Real World Dependency Injection
  • 19.
    Real World DependencyInjection „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 ManageDependencies? Real World Dependency Injection
  • 21.
    Manually resolve dependencies? RealWorld Dependency Injection
  • 22.
    Automatic wiring required! SimpleContainer vs. Full stacked DI Framework Real World Dependency Injection
  • 23.
    What is DependencyInjection? Real World Dependency Injection
  • 24.
    What is DependencyInjection? Consumer Real World Dependency Injection
  • 25.
    What is DependencyInjection? Consumer Dependencies Real World Dependency Injection
  • 26.
    What is DependencyInjection? Consumer Dependencies Container Real World Dependency Injection
  • 27.
    What is DependencyInjection? Consumer Dependencies Container Real World Dependency Injection
  • 28.
    How to injecta Dependency? Real World Dependency Injection
  • 29.
    Constructor Injection <?php class MySampleServiceimplements IMySampleService { /** * @var ISampleDao */ private $sampleDao; public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } } Real World Dependency Injection
  • 30.
    Setter injection <?php class MySampleServiceimplements 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 MySampleServiceimplements IMySampleService, IApplicationContextAware { /** * @var IApplicationContext */ private $ctx; public function setCtx(IApplicationContext $ctx) { $this->ctx = $ctx; } } Real World Dependency Injection
  • 33.
    Real World DependencyInjection How to wire it all up?
  • 34.
    Real World DependencyInjection Annotation based wiring <?php class MySampleService implements IMySampleService { private $sampleDao; /** * @Inject */ public function __construct(ISampleDao $sampleDao) { $this->sampleDao = $sampleDao; } }
  • 35.
    Real World DependencyInjection 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? RealWorld Dependency Injection DI vs. Registry vs. Service Locator
  • 40.
    Real World DependencyInjection Ready to unlock the door?
  • 41.
    Unittesting made easy RealWorld 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, multipleconfigurations Real World Dependency Injection
  • 44.
    One class, multipleconfigurations Page ExporterPage Exporter Released / Published Pages Released / Published Pages Real World Dependency Injection
  • 45.
    One class, multipleconfigurations Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection
  • 46.
    One class, multipleconfigurations <?php abstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Real World Dependency Injection
  • 47.
    One class, multipleconfigurations <?php abstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Remember: The contract! Real World Dependency Injection
  • 48.
    One class, multipleconfigurations <?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 codeis good code!" Oliver Gierke One class, multiple configurations Real World Dependency Injection
  • 50.
    One class, multipleconfigurations <?php class PageExporter { public function __construct(IPageDao $pageDao) { $this->pageDao = $pageDao; } } Real World Dependency Injection
  • 51.
    One class, multipleconfigurations <?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, multipleconfigurations <?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, multipleconfigurations II Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection
  • 54.
    One class, multipleconfigurations II Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection HTMLHTML
  • 55.
    One class, multipleconfigurations II Page ExporterPage Exporter Released / Published Pages Released / Published Pages Workingcopy Pages Workingcopy Pages Real World Dependency Injection PDFPDFHTMLHTML
  • 56.
    One class, multipleconfigurations 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, multipleconfigurations III Real World Dependency Injection
  • 58.
    One class, multipleconfigurations 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 extendsMvc_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, multipleconfigurations 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 serviceaccess Real World Dependency Injection
  • 62.
    Mocking external serviceaccess Booking serviceBooking service Real World Dependency Injection
  • 63.
    Mocking external serviceaccess Booking serviceBooking service WS- Connector WS- Connector Real World Dependency Injection
  • 64.
    Mocking external serviceaccess Booking serviceBooking service WS- Connector WS- Connector WebserviceWebservice Real World Dependency Injection
  • 65.
    Mocking external serviceaccess Booking serviceBooking service WS- Connector WS- Connector WebserviceWebservice Remember: The contract! Real World Dependency Injection
  • 66.
    Mocking external serviceaccess Booking serviceBooking service FS- Connector FS- Connector FilesystemFilesystem Real World Dependency Injection
  • 67.
    Mocking external serviceaccess Booking serviceBooking service FS- Connector FS- Connector FilesystemFilesystem fullfills the contract! Real World Dependency Injection
  • 68.
    Clean, readable code RealWorld Dependency Injection
  • 69.
    Clean, readable code <?php classDeletePage 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 RealWorld Dependency Injection
  • 71.
    No framework dependency <?php classMySampleService 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, reuseof components! Real World Dependency Injection
  • 73.
    Benefits Can reduce theamount of code! Real World Dependency Injection
  • 74.
    Benefits Helps developers to understandthe code! Real World Dependency Injection
  • 75.
    Cons – NoJSR330 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 – Developersneed mindshift Configuration ↔ Runtime Real World Dependency Injection
  • 77.
  • 78.