Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bulgaria PHP 2016 - Dependency Injection & Dependency Inversion in PHP

Bulgaria PHP 2016 - Dependency Injection & Dependency Inversion in PHP

Dependency Injection and Dependency Inversion are important tools for writing testable and reusable code. They are available in any object oriented language and PHP is no exception. In this talk we will look at both Dependency Injection and the Dependency Inversion Principle, how they fit in with SOLID, and why they should be used when writing object oriented code.

How are objects wired together? What is an object graph? Is a Dependency Injection Container the right way forward? Can we do this automatically, and are there any patterns or reusable components available to help us achieve reusable and decoupled code? These are some of the topics covered in this talk from both a theoretical and a practical standpoint.

Walking out of the room you should understand why dependency injection is so heavily advocated in programming and how you can use it to write awesome, decoupled code in PHP.

James Mallison

October 08, 2016
Tweet

More Decks by James Mallison

Other Decks in Technology

Transcript

  1. A few quick words
    about me
    James Mallison
    @J7mbo

    View full-size slide

  2. Dependency Injection and
    Dependency Inversion in PHP
    @J7mbo

    View full-size slide

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

    View full-size slide

  4. Object Instantiation
    Http
    Request
    DOM Search
    @J7mbo

    View full-size slide

  5. Please be True…
    @J7mbo

    View full-size slide

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

    View full-size slide

  7. Inversion of Control
    @J7mbo

    View full-size slide

  8. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  11. 1 year later…
    @J7mbo

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  16. 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

    View full-size slide

  17. 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

    View full-size slide

  18. Framework
    (Object Oriented)
    (hopefully)
    @J7mbo

    View full-size slide

  19. Dependency Injection Container
    (DiC)
    @J7mbo

    View full-size slide

  20. Get the Conference
    object here
    @J7mbo

    View full-size slide

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

    View full-size slide

  22. 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

    View full-size slide

  23. Create the
    BulgariaPHP2016 object
    @J7mbo

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. Automatic Injection for concrete classes
    @J7mbo

    View full-size slide

  27. See ‘Conference’
    Create ‘BulgariaPHP2016’
    @J7mbo

    View full-size slide

  28. 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

    View full-size slide

  29. 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

    View full-size slide

  30. 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

    View full-size slide

  31. 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

    View full-size slide

  32. • 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

    View full-size slide

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

    View full-size slide

  34. ‘Decorate’ existing Controller
    Delegate controller
    method call,

    but add additional
    functionality (logging)
    @J7mbo

    View full-size slide

  35. Anonymous Class
    Logging for any
    method call here
    @J7mbo

    View full-size slide

  36. 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

    View full-size slide

  37. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide