Perfecting Dependency Injection

Perfecting Dependency Injection

It’s in code bases all around the world, but are we getting all the value that the Dependency Injection pattern has to offer? Large dependency graphs, brittle test suites and hidden complexity have lead me to believe that we aren't. However, I think we can! In this talk we will cover when to use this pattern, how to use it and the pitfalls that we should be watching out for. We’ll also cover some alternatives to Dependency Injection, just in case you decide that it is not for you.

Ef23f25f04300452581b4a19a93a6a97?s=128

Matt Baker

May 11, 2017
Tweet

Transcript

  1. Perfecting Dependency Injection Matt Baker @mattc_baker

  2. Please leave me feedback! @mattc_baker

  3. Motivation for talk @mattc_baker

  4. What is Dependency Injection? @mattc_baker

  5. “Dependency Injection is a set of software design principles and

    patterns that enable us to develop loosely coupled code” - Mark Seemann @mattc_baker
  6. @mattc_baker Loose coupling protects our components from rippling changes

  7. Our beautiful class @mattc_baker

  8. Our beautiful class’s tight coupling @mattc_baker

  9. Deterministic @mattc_baker 1 1 + 2

  10. Nondeterministic @mattc_baker FlightSqlRepository SQL Database

  11. You’re being a control freak @mattc_baker

  12. We need to let go of control @mattc_baker

  13. Inverting control of FlightSqlRepository @mattc_baker

  14. Method Injection @mattc_baker

  15. Constructor Injection should be your default @mattc_baker

  16. Three ways to inject dependencies @mattc_baker Constructor Injection Method Injection

    Property Injection
  17. Some changes have been requested Log a message every time

    we save a new flight successfully Email customer every time we save a new flight successfully Email customer every time we fail to save a new flight @mattc_baker Publish a message every time we save a new flight successfully
  18. FlightBooker constructor after changes @mattc_baker

  19. BookFlight implementation after change @mattc_baker

  20. How many dependencies is too many dependencies? @mattc_baker

  21. Facade Services, or presenting many things as one @mattc_baker

  22. Discovering Facade Services Save flights Email customer IFlightRepository ILogger IMessagePublisher

    IEmailSender @mattc_baker
  23. FlightSaver Facade Service @mattc_baker

  24. FlightSaver Facade Service Save method @mattc_baker

  25. FlightBooker constructor after Facade Service @mattc_baker

  26. BookFlight method after Facade Service @mattc_baker

  27. Consuming FlightBooker, passing the buck @mattc_baker

  28. @mattc_baker

  29. Going a little deeper... @mattc_baker

  30. Wouldn’t this be nice? Impossible without tight coupling? @mattc_baker

  31. All I want is a parameterless constructor @mattc_baker

  32. Inversion of Control Container @mattc_baker

  33. IoC Container wiring @mattc_baker

  34. What dependencies does FlightBooker need? @mattc_baker

  35. Service Location, maybe an anti-pattern? @mattc_baker

  36. Alternatively, use a Composition Root @mattc_baker

  37. Favor Composition Roots @mattc_baker

  38. IoC Container and a Composition Root @mattc_baker

  39. Isn’t that still Service Location? @mattc_baker

  40. Handling changes with the Composition Root Add a timestamp to

    every log that is written @mattc_baker
  41. ILogger implementation @mattc_baker

  42. Change Logger directly @mattc_baker Logger Logger Timestamp

  43. Intercepting calls to the logger @mattc_baker Logger Timestamp Logger

  44. ILogger implementation @mattc_baker

  45. Create another ILogger implementation @mattc_baker

  46. Intercepting calls using the Decorator pattern @mattc_baker Logger Timestamp Logger

  47. Back in the Composition Root @mattc_baker

  48. Compose the new implementation in the Composition Root @mattc_baker

  49. Interception! @mattc_baker

  50. One more change Get rid of calls to message publisher

    in FlightSaver. @mattc_baker
  51. Cross cutting concerns in FlightSaver facade @mattc_baker

  52. Implement IFlightSaver again @mattc_baker

  53. Body of Save method @mattc_baker

  54. Compose new IFlightSaver implementation @mattc_baker

  55. Previous FlightSaver constructor with IMessagePublisher @mattc_baker

  56. Updated FlightSaver constructor @mattc_baker

  57. Previous FlightSaver Save implementation @mattc_baker

  58. Updated FlightSaver Save implementation @mattc_baker

  59. Compose your cross-cutting concerns with Interception! @mattc_baker Logging Caching Message

    Publishing
  60. What about some alternatives? @mattc_baker

  61. Domain events @mattc_baker

  62. Registering Events and their Handlers @mattc_baker

  63. FlightBooker implementation with no dependencies @mattc_baker

  64. LogEmitted @mattc_baker

  65. Sending data in is easy @mattc_baker Getting data out is

    hard
  66. Ditch the IoC Container for Poor Man’s Dependency Injection @mattc_baker

  67. Volatile dependencies = static abstractions @mattc_baker

  68. @mattc_baker Things to keep in mind - Don’t be a

    Control Freak - Favor Constructor Injection - Only inject volatile, or nondeterministic, dependencies - Don’t inject more than X dependencies - Solve Constructor Over-Injection with Facade Services - Avoid Service Location - Use Interception for your cross-cutting concerns - Use Interception for your cross-cutting concerns - If you choose to use Dependency Injection, use it everywhere in your application - Use a Composition Root - Use only one Composition Root - Keep your Composition Root close to your entry point
  69. Questions? @mattc_baker

  70. “Dependency Injection is a set of software design principles and

    patterns that enable us to develop loosely coupled code” - Mark Seemann @mattc_baker
  71. Thank you! @mattc_baker