72
Real World Dependency Injection Stephan Hochdörfer, bitExpert AG

Real World Dependency Injection - oscon13

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Real World Dependency Injection - oscon13

Real World Dependency InjectionStephan Hochdörfer, bitExpert AG

Page 2: Real World Dependency Injection - oscon13

Real World Dependency Injection

About me

Stephan Hochdörfer

Head of IT at bitExpert AG, Germany

enjoying PHP since 1999

[email protected]

@shochdoerfer

Page 3: Real World Dependency Injection - oscon13

Real World Dependency Injection

I so <3 Dependency Injection.

Page 4: Real World Dependency Injection - oscon13

Real World Dependency Injection

Separation of Concerns

Page 5: Real World Dependency Injection - oscon13

Design by Contract

Real World Dependency Injection

Page 6: Real World Dependency Injection - oscon13

Real World Dependency Injection

Dependency Injection

Page 7: Real World Dependency Injection - oscon13

Real World Dependency Injection

Dependency Injection

"[...] pattern that allows the removal of hard-coded dependencies and

makes it possible to change them, whether at run-time or compile-time."

(Wikipedia)

Page 8: Real World Dependency Injection - oscon13

Real World Dependency Injection

What are Dependencies?

Page 9: Real World Dependency Injection - oscon13

Real World Dependency Injection

Are dependencies bad?

Page 10: Real World Dependency Injection - oscon13

Real World Dependency Injection

Dependencies: Tight coupling

Page 11: Real World Dependency Injection - oscon13

No code reuse!

Real World Dependency Injection

Page 12: Real World Dependency Injection - oscon13

No isolation, not testable!

Real World Dependency Injection

Page 13: Real World Dependency Injection - oscon13

Real World Dependency Injection

Dependency hell!

Page 14: Real World Dependency Injection - oscon13

What is Dependency Injection?

Real World Dependency Injection

Page 15: Real World Dependency Injection - oscon13

What is Dependency Injection?

Real World Dependency Injection

new DeletePage(new PageManager());

Page 16: Real World Dependency Injection - oscon13

What is Dependency Injection?

Consumer

Real World Dependency Injection

Page 17: Real World Dependency Injection - oscon13

What is Dependency Injection?

Consumer Dependencies

Real World Dependency Injection

Page 18: Real World Dependency Injection - oscon13

What is Dependency Injection?

Consumer Dependencies Container

Real World Dependency Injection

Page 19: Real World Dependency Injection - oscon13

What is Dependency Injection?

Consumer Dependencies Container

Real World Dependency Injection

Page 20: Real World Dependency Injection - oscon13

s

Real World Dependency Injection

„new“ is evil!

Page 21: Real World Dependency Injection - oscon13

<?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'));

}}

Real World Dependency Injection

„new“ is evil!

Page 22: Real World Dependency Injection - oscon13

Real World Dependency Injection

„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'));

}}

Page 23: Real World Dependency Injection - oscon13

"High-level modules should not depend on low-level modules.

Both should depend on abstractions."Robert C. Martin

Real World Dependency Injection

Page 24: Real World Dependency Injection - oscon13

Real World Dependency Injection

„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'));

}}

Page 25: Real World Dependency Injection - oscon13

How to manage Dependencies?

Real World Dependency Injection

Page 26: Real World Dependency Injection - oscon13

How to manage Dependencies?

Simple container vs. Full stacked DI Framework

Real World Dependency Injection

Page 27: Real World Dependency Injection - oscon13

The container acts as glue point!

Real World Dependency Injection

Page 28: Real World Dependency Injection - oscon13

How to inject dependencies?

Real World Dependency Injection

Page 29: Real World Dependency Injection - oscon13

Constructor Injection<?php

class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao;

public function __construct(ISampleDao $sampleDao) {$this->sampleDao = $sampleDao;

}}

Real World Dependency Injection

Page 30: Real World Dependency Injection - oscon13

Setter Injection<?php

class MySampleService implements IMySampleService { /** * @var ISampleDao */ private $sampleDao;

public function setSampleDao(ISampleDao $sampleDao){$this->sampleDao = $sampleDao;

}}

Real World Dependency Injection

Page 31: Real World Dependency Injection - oscon13

Interface Injection<?php

interface IApplicationContextAware { public function setCtx(IApplicationContext $ctx);}

Real World Dependency Injection

Page 32: Real World Dependency Injection - oscon13

Interface Injection<?php

class MySampleService implements IMySampleService,IApplicationContextAware { /** * @var IApplicationContext */ private $ctx;

public function setCtx(IApplicationContext $ctx) {$this->ctx = $ctx;

}}

Real World Dependency Injection

Page 33: Real World Dependency Injection - oscon13

Property Injection

Real World Dependency Injection

Page 34: Real World Dependency Injection - oscon13

Property Injection

Real World Dependency Injection

"NEIN NEIN NEIN!"David Zülke

Page 35: Real World Dependency Injection - oscon13

How to wire it all up?

Real World Dependency Injection

Page 36: Real World Dependency Injection - oscon13

Real World Dependency Injection

Annotations<?php

class MySampleService implements IMySampleService { private $sampleDao;

/** * @Inject */ public function __construct(ISampleDao $sampleDao) {

$this->sampleDao = $sampleDao; }}

Page 37: Real World Dependency Injection - oscon13

Real World Dependency Injection

Annotations<?php

class MySampleService implements IMySampleService { private $sampleDao;

/** * @Inject * @Named('TheSampleDao') */ public function __construct(ISampleDao $sampleDao) {

$this->sampleDao = $sampleDao; }}

Page 38: Real World Dependency Injection - oscon13

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

Page 39: Real World Dependency Injection - oscon13

External configuration - YAML

services: SampleDao: class: SampleDao arguments: ['app_sample', 'iSampleId', 'BoSample'] SampleService: class: SampleService arguments: [@SampleDao]

Real World Dependency Injection

Page 40: Real World Dependency Injection - oscon13

External configuration - 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;

}}

Real World Dependency Injection

Page 41: Real World Dependency Injection - oscon13

Internal vs. external configuration

Real World Dependency Injection

Page 42: Real World Dependency Injection - oscon13

Internal vs. external configuration

Real World Dependency Injection

Class configuration

vs.

Instance configuration

Page 43: Real World Dependency Injection - oscon13

Real World Dependency Injection

Why use I use DI in my daily work?

Page 44: Real World Dependency Injection - oscon13

Unittesting made easy

Real World Dependency Injection

Page 45: Real World Dependency Injection - oscon13

Unittesting made easy<?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);

}}

Real World Dependency Injection

Page 46: Real World Dependency Injection - oscon13

One class, multiple configurations

Real World Dependency Injection

Page 47: Real World Dependency Injection - oscon13

One class, multiple configurations

Page ExporterPage Exporter

Released / PublishedPages

Released / PublishedPages

WorkingcopyPages

WorkingcopyPages

Real World Dependency Injection

Page 48: Real World Dependency Injection - oscon13

One class, multiple configurations<?phpabstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; }}

Real World Dependency Injection

Page 49: Real World Dependency Injection - oscon13

One class, multiple configurations<?phpabstract class PageExporter { protected function setPageDao(IPageDao $pageDao) { $this->pageDao = $pageDao; }}

Remember: The contract!

Real World Dependency Injection

Page 50: Real World Dependency Injection - oscon13

One class, multiple configurations<?phpclass 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

Page 51: Real World Dependency Injection - oscon13

"Only deleted code is good code!"Oliver Gierke

One class, multiple configurations

Real World Dependency Injection

Page 52: Real World Dependency Injection - oscon13

One class, multiple configurations<?phpclass PageExporter { public function __construct(IPageDao $pageDao) { $this->pageDao = $pageDao; }}

Real World Dependency Injection

Page 53: Real World Dependency Injection - oscon13

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

Page 54: Real World Dependency Injection - oscon13

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

Page 55: Real World Dependency Injection - oscon13

Mocking external service access

Real World Dependency Injection

Page 56: Real World Dependency Injection - oscon13

Mocking external service access

Booking serviceBooking service WS-Connector

WS-Connector WebserviceWebservice

Real World Dependency Injection

Page 57: Real World Dependency Injection - oscon13

Mocking external service access

Booking serviceBooking service WS-Connector

WS-Connector WebserviceWebservice

Real World Dependency Injection

Remember: The contract!

Page 58: Real World Dependency Injection - oscon13

Mocking external service access

Booking serviceBooking service FS-Connector

FS-Connector FilesystemFilesystem

Real World Dependency Injection

Page 59: Real World Dependency Injection - oscon13

Mocking external service access

Booking serviceBooking service FS-Connector

FS-Connector FilesystemFilesystem

fullfills thecontact!

Real World Dependency Injection

Page 60: Real World Dependency Injection - oscon13

Clean, readable code

Real World Dependency Injection

Page 61: Real World Dependency Injection - oscon13

Clean, readable 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());}

}

Real World Dependency Injection

Page 62: Real World Dependency Injection - oscon13

No framework dependencies

Real World Dependency Injection

Page 63: Real World Dependency Injection - oscon13

No framework dependencies<?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) {}

}}

Real World Dependency Injection

Page 64: Real World Dependency Injection - oscon13

Real World Dependency Injection

Getting rid of the „noise“

Page 65: Real World Dependency Injection - oscon13

Real World Dependency Injection

Increase code reuse!

Page 66: Real World Dependency Injection - oscon13

Real World Dependency Injection

Helps to understand the code!

Page 67: Real World Dependency Injection - oscon13

Real World Dependency Injection

Brings back the fun again :)

Page 68: Real World Dependency Injection - oscon13

Real World Dependency Injection

No standard. No tooling support.

Page 69: Real World Dependency Injection - oscon13

Real World Dependency Injection

It takes some time to unterstand DI.

Page 70: Real World Dependency Injection - oscon13

Real World Dependency Injection

Configuration vs. Runtime

Page 71: Real World Dependency Injection - oscon13

Real World Dependency Injection

DI is not slow!

Page 72: Real World Dependency Injection - oscon13

Thank you!