Slide 1

Slide 1 text

A few quick words about me James Mallison @J7mbo

Slide 2

Slide 2 text

@J7mbo

Slide 3

Slide 3 text

Dependency Injection and Dependency Inversion in PHP @J7mbo

Slide 4

Slide 4 text

OOP, DI, DiP, IoC, DIC, SOLID, WTF @J7mbo

Slide 5

Slide 5 text

@J7mbo

Slide 6

Slide 6 text

@J7mbo

Slide 7

Slide 7 text

@J7mbo

Slide 8

Slide 8 text

@J7mbo

Slide 9

Slide 9 text

@J7mbo

Slide 10

Slide 10 text

@J7mbo

Slide 11

Slide 11 text

Object Instantiation Http Request DOM Search @J7mbo

Slide 12

Slide 12 text

@J7mbo

Slide 13

Slide 13 text

Please be True… @J7mbo

Slide 14

Slide 14 text

@J7mbo

Slide 15

Slide 15 text

Asking for objects to be passed in is Dependency Injection Calling Code @J7mbo

Slide 16

Slide 16 text

Inversion of Control @J7mbo

Slide 17

Slide 17 text

The old way Object finds the objects it needs for itself, then calls them. The new way Dependencies are handed to the object when created. Inversion of Control @J7mbo

Slide 18

Slide 18 text

Calling getContents() will now return this HTML Passing in our $fakeClient @J7mbo Our actual code

Slide 19

Slide 19 text

Dependency Injection provides Control and Loose Coupling Inversion of.. @J7mbo

Slide 20

Slide 20 text

1 year later… @J7mbo

Slide 21

Slide 21 text

“High-level modules should not depend on low-level modules. Both should depend on abstractions” @J7mbo

Slide 22

Slide 22 text

Inversion of Control Dependencies are given to your object on creation (via Dependency Injection) Dependency Inversion Depend on abstractions rather than concretes @J7mbo

Slide 23

Slide 23 text

@J7mbo

Slide 24

Slide 24 text

Now uses a ConferenceRepository Instead (DB) New 2017 version @J7mbo

Slide 25

Slide 25 text

“Polymorphism is the provision of a single interface to entities of different types” @J7mbo

Slide 26

Slide 26 text

Recap • Dependency Injection is simply passing in object dependencies as parameters instead of instantiating them in the object using them • Doing this gives you Inversion of Control, as the control over object creation is no longer delegated to the object using them • Using interfaces, we can adhere to the Dependency Inversion Principle and depend on abstractions • Code always starts off procedural, and builds objects up before executing them in an object oriented manner • If you use don’t do this, other people will hate you because they can’t mock your objects easily in their tests (so your code is not testable) @J7mbo

Slide 27

Slide 27 text

@J7mbo

Slide 28

Slide 28 text

Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented) (hopefully) Composition Root Objects built Match route to controller + action Create controller object Run action (method) with any request parameters Developer creates a controller Does whatever they want @J7mbo

Slide 29

Slide 29 text

Framework (Object Oriented) (hopefully) @J7mbo

Slide 30

Slide 30 text

Dependency Injection Container (DiC) @J7mbo

Slide 31

Slide 31 text

Get the Conference object here @J7mbo

Slide 32

Slide 32 text

External requirements should be visible from an object’s constructor and method signatures @J7mbo

Slide 33

Slide 33 text

Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented) (hopefully) Composition Root Objects defined and registed in container Match route to controller + action Container Creates controller (with dependencies) Container runs action with any request parameters Developer creates a controller DI’s registered dependencies Does whatever they want ‘Object Graph’ @J7mbo

Slide 34

Slide 34 text

@J7mbo

Slide 35

Slide 35 text

@J7mbo

Slide 36

Slide 36 text

@J7mbo

Slide 37

Slide 37 text

Create the BulgariaPHP2016 object @J7mbo

Slide 38

Slide 38 text

@J7mbo

Slide 39

Slide 39 text

Problem - Interfaces We still can’t ask for an interface and adhere to DiP - we can only ask for concretes

Slide 40

Slide 40 text

Encounter “Conference” Create “BulgariaPHP2016” Search interface-to-concrete mapping / ‘binding’

Slide 41

Slide 41 text

@J7mbo

Slide 42

Slide 42 text

Automatic Injection for concrete classes @J7mbo

Slide 43

Slide 43 text

@J7mbo

Slide 44

Slide 44 text

@J7mbo

Slide 45

Slide 45 text

See ‘Conference’ Create ‘BulgariaPHP2016’ @J7mbo

Slide 46

Slide 46 text

@J7mbo

Slide 47

Slide 47 text

@J7mbo

Slide 48

Slide 48 text

Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented) (hopefully) Composition Root Relationships (object graph) defined in configuration file Match route to controller + action Injector Creates controller (with dependencies) Developer creates a controller DI’s registered dependencies Does whatever they want • Not coupled to container • Remove code / move code about at any time • Concentrate on writing SOLID code @J7mbo

Slide 49

Slide 49 text

Dev Code (Object Oriented) (hopefully) Developer creates a controller DI’s registered dependencies Does whatever they want • Not coupled to container • Remove code / move code about at any time • Concentrate on writing SOLID code @J7mbo

Slide 50

Slide 50 text

Automatic Injection - Positives • Auto-injection for concretes, because we don’t interface everything • Auto-injection for interfaces that have a single concrete available (look through composer-loaded classes?) • Configured auto-injection through ‘aliasing’ or ‘binding’ a concrete to an interface • Edge cases - specifying instances for specific modules

Slide 51

Slide 51 text

Automatic Injection - Negatives • Likely requires framework and infrastructure set up from the beginning of the project • Reflection is slow (but you can cache these like Composer’s optimised autoloader for production (-o)); Auryn caches

Slide 52

Slide 52 text

@J7mbo

Slide 53

Slide 53 text

• Your objects should specify external requirements needed in their constructor and method signatures • Dependency Injection is simply passing in external requirements as parameters • Using interfaces for functionality that might change provides polymorphism (switch out concrete implementation any time) • Depending on abstractions rather than concretes (interfaces), and having your object graph composed ‘higher’ in the codebase (composition root), provides Inversion of Control and helps you adhere to the Dependency Inversion Principle @J7mbo

Slide 54

Slide 54 text

Where next? AOP and PHP7’s Anonymous Classes @J7mbo

Slide 55

Slide 55 text

‘Decorate’ existing Controller Delegate controller method call,
 but add additional functionality (logging) @J7mbo

Slide 56

Slide 56 text

@J7mbo

Slide 57

Slide 57 text

@J7mbo

Slide 58

Slide 58 text

@J7mbo

Slide 59

Slide 59 text

Anonymous Class Logging for any method call here @J7mbo

Slide 60

Slide 60 text

How can I apply this? • Choose a framework that supports automatic recursive DI • Choose a micro-framework or components that allow you to substitute the ‘controller resolver’ to provide this • Legacy codebase? Don’t have to use an auto-injector, just design your interfaces well adhere to DIP when you can • In your next project, make this a primary consideration of your software architecture @J7mbo

Slide 61

Slide 61 text

Current Framework Solutions? @J7mbo • Symfony has autowire: true as of version 2.8+ • Other frameworks have it out-of-the-box • Micro-frameworks (like Silex) allow you to replace how the controller is instantiated ($app[controller.resolver]) and you can write the code to use an injector like Auryn

Slide 62

Slide 62 text

• The ‘gang of four book’ (GoF) • The Clean Coder (Robert C. Martin) • Post your code on CodeReview (and survive) @J7mbo

Slide 63

Slide 63 text

@J7mbo Thanks https://joind.in/talk/648b2 @j7mbo (PHP6 jokes, oop, confs, software engineering)