dependency injection

39
dependency injection The pattern

Upload: marc-morera

Post on 23-Dec-2014

378 views

Category:

Technology


3 download

DESCRIPTION

Dependency injection pattern, explained with a simple and common real life example.

TRANSCRIPT

Page 1: Dependency injection

dependency injectionThe pattern

Page 2: Dependency injection

@BeFactory

by Marc Morera

Page 3: Dependency injection

class Carpenter { public function work() { $hammer = new Hammer(); $hammer->chop(); } } !$carpenter = new Carpenter(); $carpenter->work();

Page 4: Dependency injection

Problems?

Page 5: Dependency injection

Let’s talk about responsibility

Page 6: Dependency injection

• Any carpenter should ignore how to build a hammer, but how to use it.

• The carpenter goes to a hardware store to get some nice brown and big hammer.

Page 7: Dependency injection

• Not testable

• High coupling

Page 8: Dependency injection

class Carpenter { public function work(Hammer $hammer) { $hammer->chop(); } } !$hammer = new Hammer(); $carpenter = new Carpenter(); $carpenter->work($hammer);

Page 9: Dependency injection

• So can we just have a carpenter without a hammer?

• No way!

• A carpenter ALWAYS have a hammer.

• No hammer, no carpenter.

Page 10: Dependency injection

class Carpenter { private $hammer; ! public function __construct(Hammer $hammer) { $this->hammer = $hammer; } ! public function work() { $this->hammer->chop(); } } !$hammer = new Hammer(); $carpenter = new Carpenter($hammer); $carpenter->work();

Page 11: Dependency injection

2 years later…

• All carpenters are upgraded.

• No hammers anymore.

• All carpenters will use a simple small red mallet

Page 12: Dependency injection

• We want to make sure all objects that every carpenter will use to chop, will be suitable for that.

• How can ensure this?

Page 13: Dependency injection

Interfaces

Page 14: Dependency injection

interface ToolInterface { public function chop(); } !class Hammer implements ToolInterface { public function chop() { } } !class Mallet implements ToolInterface { public function chop() { } }

Page 15: Dependency injection

class Carpenter { private $tool; ! public function __construct(ToolInterface $tool) { $this->tool = $tool; } ! public function work() { $this->tool->chop(); } } !$carpenter = new Carpenter(new Hammer); $carpenter = new Carpenter(new Mallet); $carpenter->work();

Page 16: Dependency injection

• Very testable and easily mockable

• Low coupling

• Seems to be the best solution ever

Page 17: Dependency injection

But…is this implementation a good one?

Page 18: Dependency injection

NO.

Page 19: Dependency injection

• This is purely what means dependency injection.

• Every dependency of an object is injected

• … into the constructor if is needed for the class to be built

• … in a method if is just needed for this method

Page 20: Dependency injection

Think about a full project with this code

$iron = new Iron; $wood = new Wood; $plastic = new Plastic(new Blue); $hammer = new Hammer($iron, $wood, $plastic); $paintCan = new Paint(new Red); $carpenter = new Carpenter($hammer, $glasses, $paintCan); !$nail = new Nail($iron); $carpenter->work($iron);

Page 21: Dependency injection

• Not maintainable

• Not scalable

• Responsibility of building a carpenter is now distributed by all controllers.

Page 22: Dependency injection

Container

Page 23: Dependency injection

What container should provide?

• Definition

• Customization

• Instantiation

Page 24: Dependency injection

• Our container is the provider of all instances.

• It is therefore responsable of building them

Page 25: Dependency injection

Services

• A service is just an instance of an object

• Each service must define the path of the object ( given by the namespace )

• Also can define how to be built ( arguments )

• An argument can be another service ( using @ )

Page 26: Dependency injection

services: iron: class: Iron wood: class: Wood plastic: class: Plastic hammer: class: Hammer arguments: iron: @iron wood: @wood plastic: @plastic carpenter : class: Carpenter arguments: hammer: @hammer

Page 27: Dependency injection

$carpenter = $container->get(‘carpenter’);

Page 28: Dependency injection

Customization

• In this example, every time a Carpenter is requested, a new Hammer will be used.

• If we want to switch to a Mallet, we must change definition.

• We should be able to configure it outside the definition of the container.

Page 29: Dependency injection

services: iron: class: Iron wood: class: Wood plastic: class: Plastic hammer: class: Hammer arguments: iron: @iron wood: @wood plastic: @plastic carpenter : class: Carpenter arguments: hammer: @hammer

Page 30: Dependency injection

Parameters

• Any parameter should be able to be defined in the project

• A parameter is used using “%” keyword.

Page 31: Dependency injection

parameters: tool_class: Hammer services: iron: class: Iron wood: class: Wood plastic: class: Plastic tool: class: %tool_class% arguments: iron: @iron wood: @wood plastic: @plastic carpenter : class: Carpenter arguments: tool: @tool

Page 32: Dependency injection

• Prototype.

• Container. Some objects can be just reused in every request ( an infinite paint can ) - In the real world, a Logger or a simple Text library.

Scopes

Page 33: Dependency injection

Prototype

• One instance per container request

• Container just build an instance and return it

• It’s defined by setting scope: prototype

• For example, a nail

Page 34: Dependency injection

Container

• First time, object is built and stored.

• From next requests, same instance is reused and returned

• Saving memory ( storing objects ) and cpu ( building them )

• It’s defined by setting scope: container. Default behavior

Page 35: Dependency injection

services: paint_can: class: PaintCan scope: container carpenter : class: Painter scope: prototype arguments: paint_can: @paint_can

Page 36: Dependency injection

• Each time a painter is requested, we’ll reuse same paint can object since they all can share it.

Page 37: Dependency injection

Implementations

• Symfony2 - DependencyInjection Component

• Android - Dagger

• Objective C - Typhoon

Page 38: Dependency injection

DI Saves your lifeUse it, dude!

Page 39: Dependency injection

QA?