Dependency Injection and Dependency Inversion in PHP

Dependency Injection and 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.

E189f89d366442f943d49e00566b6d51?s=128

James Mallison

October 03, 2015
Tweet

Transcript

  1. Dependency Injection and Dependency Inversion in PHP @J7mbo

  2. Your goal on a project?

  3. Professional Integrity

  4. “I want a plumber who takes a pride in his

    work, who bothers to learn and gain experience, who takes what he does seriously” “I expect to pay extra for expertise, but it's a wise investment compared to hiring a cowboy plumber and having to pay later to fix up the botch job he left me with”
  5. “Integrity is "doing the right thing even when no one

    is looking", and I see Software Craftsmanship as striving for integrity in the systems we create.” David Starr (elegantcode.com)
  6. None
  7. A little bit about me…

  8. OOP, DI, DiP, IoC, DIC, SOLID, WTF

  9. None
  10. None
  11. None
  12. None
  13. None
  14. None
  15. None
  16. None
  17. Object Instantiation

  18. Object Instantiation Http Request

  19. Object Instantiation Http Request Disgusting DOM Searching

  20. Object Instantiation Http Request Disgusting DOM Searching Sorting Algorithm

  21. None
  22. Please be True…

  23. None
  24. None
  25. Asking for objects to be passed in is Dependency Injection

    Calling Code
  26. Inversion of Control

  27. I have to mock this… And this… This too.. srsly

  28. Calling getContents() will now return this HTML Passing in my

    $fakeClient
  29. Dependency Injection provides Control

  30. 1 year later…

  31. “High-level modules should not depend on low-level modules. Both should

    depend on abstractions”
  32. None
  33. None
  34. “Polymorphism is the provision of a single interface to entities

    of different types”
  35. Recap • Dependency Injection is simply passing in object dependencies

    as parameters instead of instantiating them in the object using them
  36. 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
  37. 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 • 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)
  38. 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 • 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)
  39. 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)
  40. None
  41. Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented)

    (hopefully) Composition Root Objects built
  42. Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented)

    (hopefully) Composition Root Objects built Match route to controller + action Create controller Run action with any request parameters
  43. Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented)

    (hopefully) Composition Root Objects built Match route to controller + action Create controller Run action with any request parameters Developer creates a controller Does whatever they want
  44. Framework (Object Oriented) (hopefully)

  45. Framework (Object Oriented) (hopefully)

  46. Dependency Injection Container (DiC)

  47. Get the Conference object here

  48. External requirements should be visible from an object’s constructor and

    method signatures
  49. Bootstrap (Procedural) Framework (Object Oriented) (hopefully) Dev Code (Object Oriented)

    (hopefully) Composition Root Objects defined and registed in container ‘Object Graph’
  50. 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 ‘Object Graph’
  51. 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’
  52. None
  53. None
  54. None
  55. Create the PhpNw15Conference object

  56. None
  57. None
  58. None
  59. None
  60. Automatic Injection for concrete classes

  61. None
  62. None
  63. See ‘Conference’ Create ‘PhpNw15Conference’

  64. None
  65. None
  66. 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
  67. Dev Code (Object Oriented) (hopefully) Developer creates a controller DI’s

    registered dependencies Does whatever they want
  68. Dev Code (Object Oriented) (hopefully) Developer creates a controller DI’s

    registered dependencies Does whatever they want
  69. 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
  70. None
  71. None
  72. • Your objects should specify external requirements needed in their

    constructor and method signatures
  73. • Your objects should specify external requirements needed in their

    constructor and method signatures • Dependency Injection is simply passing in external requirements as parameters
  74. • 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)
  75. • 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
  76. What next? AOP and PHP7’s Anonymous Classes

  77. ‘Decorate’ existing Controller Delegate controller method call,
 but add additional

    functionality (logging)
  78. None
  79. None
  80. None
  81. Anonymous Class Automatic
 Decoration

  82. 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
  83. Why bother?

  84. • The ‘gang of four book’ (GoF) • The Clean

    Coder (Robert C. Martin) • Post your code on CodeReview (and survive)
  85. @J7mbo https://joind.in/talk/view/15431