Real world dependency injection - DPC10
-
Upload
stephan-hochdoerfer -
Category
Business
-
view
4.047 -
download
2
Transcript of Real world dependency injection - DPC10
Real World Dependency InjectionStephan Hochdörfer, bitExpert AG
"Dependency Injection is a key element of agile architecture"
Ward Cunningham
Agenda
1. About me
2. What is Dependency Injection?
3. Real World examples
4. Pros & Cons
5. Questions
About me
Stephan Hochdörfer, bitExpert AG
Department Manager Research Labs
enjoying PHP since 1999
@shochdoerfer
What is Dependency Injection?
What is Dependency?
What is Dependency Injection?
What is Dependency?
Application Layer Data Access layer Business logic layer ...
External components Framework classes Webservices ...
What is Dependency Injection?
Why are Dependencies bad?
What is Dependency Injection?
Why are Dependencies bad?
„new“ is evil!
What is Dependency Injection?
Why are Dependencies bad?
Tightly coupled code
Hard to re-use components
Hard to test components, no isolation
What is Dependency Injection?
Requiredclass
Mainclass
Simple Dependency
What is Dependency Injection?
Requiredclass
Mainclass
Requiredclass
Requiredclass
Complex Dependency
What is Dependency Injection?
Requiredclass
Mainclass
Requiredclass
Requiredclass
Database
Externalresource
Requiredclass
Requiredclass
Webservice
Very complex Dependency
What is Dependency Injection?
Requiredclass
Mainclass
Requiredclass
Requiredclass
Database
Externalresource
Requiredclass
Requiredclass
Webservice
Very complex Dependency
What is Dependency Injection?
Requiredclass
Mainclass
Requiredclass
Requiredclass
Database
Externalresource
Requiredclass
Requiredclass
Webservice
Very complex Dependency
What is Dependency Injection?
How to Manage Dependencies?
What is Dependency Injection?
How to Manage Dependencies?
You don`t need to. The Framework does it all!
What is Dependency Injection?
How to Manage Dependencies?
Simple Container vs. Full stacked Framework
What is Dependency Injection?
What is Dependency Injection?
What is Dependency Injection?
What is Dependency Injection?
Consumer
What is Dependency Injection?
What is Dependency Injection?
Consumer Dependencies
What is Dependency Injection?
What is Dependency Injection?
Consumer Dependencies Container
What is Dependency Injection?
What is Dependency Injection?
Consumer Dependencies Container
What is Dependency Injection?
Types of Dependency Injection
Type 1: Constructor injection
<?php
class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $oSampleDao;
public function __construct(ISampleDao $poSampleDao) {$this->oSampleDao = $poSamleDao;
}}?>
What is Dependency Injection?
Types of Dependency Injection
Type 2: Setter injection
<?php
class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $oSampleDao;
public function setSampleDao(ISampleDao $poSampleDao) {$this->oSampleDao = $poSamleDao;
}}?>
What is Dependency Injection?
Types of Dependency Injection
Type 3: Interface injection
<?php
class MySampleService implements IMySampleService, IApplicationContextAware{ /** * @var IApplicationContext */ private $oCtx;
public function setApplicationContext(IApplicationContext $poCtx) {$this->oCtx = $poCtx;
}}?>
What is Dependency Injection?
Configuration Types
Type 1: Annotations
<?php
class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $oSampleDao;
/** * @Inject */ public function __construct(ISampleDao $poSampleDao) {
$this->oSampleDao = $poSamleDao; }}?>
What is Dependency Injection?
Configuration Types
Type 1: Annotations
<?php
class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $oSampleDao;
/** * @Inject * @Named('TheSampleDao') */ public function __construct(ISampleDao $poSampleDao) {
$this->oSampleDao = $poSamleDao; }}?>
What is Dependency Injection?
Configuration Types
Type 2: External configuration via XML
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.bitexpert.de/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.bitexpert.de/schema/
http://www.bitexpert.de/schema/bitFramework-beans.xsd">
<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>
What is Dependency Injection?
Configuration Types
Type 2: External configuration via YAML
services: SampleDao: class: SampleDao arguments: ['app_sample', 'iSampleId', 'BoSample'] SampleService: class: SampleService arguments: [@SampleDao]
What is Dependency Injection?
Configuration Types
Type 3: PHP Configuration
<?phpclass BeanCache extends bF_Beanfactory_Container_PHP_ACache {
protected function createSampleDao() {$oBean = new SampleDao('app_sample', 'iSampleId', 'BoSample');return array("oBean" => $oBean, "bSingleton" => "1");
}
protected function createMySampleService() {$oBean = new MySampleService($this->getBean('SampleDao'));return array("oBean" => $oBean, "bSingleton" => "1");
}?>
What is Dependency Injection?
Cache, Cache, Cache!
XML no Caching XML with Caching PHP PHP compiled
0
20
40
60
80
100
120
140
160
180
Requests per Second meassured via Apache HTTP server benchmarking tool
Real world examples
"High-level modules should not depend on low-level modules. Both should depend on abstractions."
Robert C. Martin
Real World examples
Unittesting made easy
<?phprequire_once 'PHPUnit/Framework.php';
class ServiceTest extends PHPUnit_Framework_TestCase { public function testSampleService() { $oSampleDao = $this->getMock('ISampleDao');
// run test case$oService = new MySampleService($oSampleDao);$bReturn = $oService->doWork();
// check assertions$this->assertTrue($bReturn);
}}?>
Real World examples
One class, multiple configurations
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.bitexpert.de/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.bitexpert.de/schema/
http://www.bitexpert.de/schema/bitFramework-beans.xsd">
<bean id="ExportLive" class="MyApp_Service_ExportManager"><constructor-arg ref="DAOPageLive" />
</bean>
<bean id="ExportWorking" class="MyApp_Service_ExportManager"><constructor-arg ref="DAOPageWorking" />
</bean>
</beans>
Implementation
Live Working
Real World examples
One class, multiple configurations II<?phpclass Promio_Action_Account_Auth extends bF_Mvc_Action_AFormAction {
private $oAccountManager;private $iType;
public function __construct(Promio_Service_IAccountManager $poAccountManager) {$this->oAccountManager = $poAccountManager;
}
public function setType($piType) {$this->iType = (int) $piType;
}
protected function processFormSubmission(bF_Bo_ABo $poBOFormBackingObject) {$oMaV = new bF_Mvc_ModelAndView($this->getSuccessView(), true);try {
$poBOFormBackingObject->setType($this->iType);$this->oAccountManager->save($poBOFormBackingObject);
}catch(bF_Service_ServiceException $oException) {
$oMaV = new bF_Mvc_ModelAndView($this->getFailureView(), true);}return $oMaV;
}}?>
Real World examples
Mocking external services
Connector WebserviceConsumer
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.bitexpert.de/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.bitexpert.de/schema/
http://www.bitexpert.de/schema/bitFramework-beans.xsd">
<bean id="Consumer" class="MyApp_Service_Consumer"><constructor-arg ref="Connector" />
</bean>
</beans>
IConnector interface
Real World examples
Mocking external services
alternativeConnector
Localfilesystem
Consumer
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.bitexpert.de/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.bitexpert.de/schema/
http://www.bitexpert.de/schema/bitFramework-beans.xsd">
<bean id="Consumer" class="MyApp_Service_Consumer"><constructor-arg ref="AltConnector" />
</bean>
</beans>
IConnector interface
Real World examples
Clean, readable code
<?php
class Promio_Action_News_Delete extends bF_Mvc_Action_AAction {/** * @var Promio_Service_INewsManager */private $oNewsManager;
public function __construct(Promio_Service_INewsManager $poNewsManager) {$this->oNewsManager = $poNewsManager;
}
protected function execute(bF_Mvc_Request $poRequest) {try {
$this->oNewsManager->delete((int) $poRequest->getVar('iNewsId'));}catch(bF_Service_ServiceException $oException) {}
$oMaV = new bF_Mvc_ModelAndView($this->getSuccessView(), true);return $oMaV;
}}?>
Real World examples
No framework dependency
<?php
class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $oSampleDao;
public function __construct(ISampleDao $poSampleDao) {$this->oSampleDao = $poSamleDao;
}
public function getSample($piSampleId) {try { return $this->oSampleDao->readByPrimaryKey((int) $piSampleId);}catch(DaoException $oException) {}
}}?>
Pros & Cons
Benefits
Good for agile development Reducing amount of code Helpful for Unit testing
Loose coupling Least intrusive mechanism Switching implementations by changing configuration Separation of glue code from business logic
Clean view on the code Separate configuration from code Getting rid of boilerpate configuration code
Pros & Cons
Cons
To many different implementations, no standard today! 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, …
No JSR 330 for PHP
Simple Containers vs. fully-stacked Framework No dependency from application to Container!
Developers need to be aware of configuration runtime↔
http://joind.in/1553