Import as an antipattern - Demystifying Dependency Injection in Python

Import as an antipattern - Demystifying Dependency Injection in Python

Dependency Injection in Python is commonly seen as over-engineering, but I think this is a myth. DI is simple and powerful and can yield great benefits to the overall quality of your code.

Dependency Injection (DI) is a technique quite common in other programming languages that has never quite fitted into the Python programmer's mindset. Usually disregarded as over-engineering and complex, most of its alleged flaws have little to do with the underlying concepts but more with implementation details of large scale frameworks that obscure its core principles.

In my experience DI is simple and powerful and can greatly improve our design making our code is easier to test, extend and maintain.

In this talk I will start with a brief standard example and challenge common idioms that introduce coupling and reduce maintainability and extensibility. I will then introduce concepts like interfaces, inversion of control and DI and apply them showcasing how the design and overall quality of the code improves.

Along the way I will demonstrate how recent additions to Python and its tooling can help when applying these techniques and also address the common misconception among Python developers suggesting large complex frameworks are required to apply DI.

I will then share some examples of Dependency Injection in well known libraries and some hands-on stories where I have benefited from it in my day-to-day work. And finally I will provide some guidelines on identifying situations where DI shines and where its application might be less obvious or should be delayed until further domain knowledge is introduced.

With this talk I hope to demystify the Dependency Injection in the Python ecosystem as well as introduce and clarify important design concepts for a beginner to intermediate audience.

2a187b83624c217024219aeed34bcc33?s=128

Yeray Díaz Díaz

September 15, 2019
Tweet

Transcript

  1. import as an anti-pattern Demystifying Dependency Injection in Python Yeray

    Díaz PyCon UK September 2019 @yera_ee
  2. ! I’m Yeray • Freelance Software Engineer based in London

    • Co-organizer of London Python Meetup • Moderator and contributor for PyPI
  3. Dependency
 Injection

  4. Dependency
 Injection Worst name ever?

  5. Dependency… Injection? Daniel Frank https://xkcd.com/327/

  6. What do programmers think? Daniel Frank https://twitter.com/yera_ee/status/1072540888264597506

  7. What do programmers think? Daniel Frank https://twitter.com/yera_ee/status/1072540888264597506

  8. How does DI make you feel?

  9. None
  10. None
  11. None
  12. None
  13. None
  14. None
  15. None
  16. None
  17. None
  18. None
  19. None
  20. None
  21. None
  22. None
  23. None
  24. None
  25. None
  26. Coupling

  27. Where did it all go wrong?

  28. Where did it all go wrong?

  29. Where did it all go wrong?

  30. import is an anti-pattern

  31. None
  32. None
  33. “Depend on abstractions, not concretions”

  34. What is an abstraction? •A formal interface definition •A series

    of objects that implement that interface •Encapsulating the lower level details
  35. In our case

  36. In our case

  37. Or even better…

  38. And now…

  39. And now…

  40. And now…

  41. And now…

  42. And now…

  43. And now… Dependency Injection!

  44. Going concrete

  45. Going concrete

  46. FileProcessor Google Storage What just happened?

  47. FileProcessor GCSFileRepo FileRepoABC

  48. FileProcessor GCSFileRepo FileRepoABC

  49. FileProcessor GCSFileRepo FileRepoABC Inversion of Control

  50. What just happened? •FileProcessor now has one responsibility: compute the

    hash of file contents •It no longer instantiates the repo, this responsibility is moved to the caller
  51. Where do dependencies come from? • One place where all

    instances of all dependencies are created • The Composition Root • Usually at the entry point of our application
  52. Composition root

  53. Composition root

  54. Composition root

  55. Composition root

  56. Benefits of DI • Interception • Lifetime • Composition

  57. Interception

  58. Interception

  59. Interception Liskov Substitution Principle

  60. But of course…

  61. But of course… Boundary test

  62. Boundary tests •Isolated from changes in the business logic •We

    test that it implements the interface correctly •Will not change at all if the interface is stable •Possibility for integration tests
  63. Lifetime

  64. Lifetime

  65. Lifetime

  66. Composition

  67. Composition

  68. Composition

  69. Composition Open ̶Closed Principle

  70. Bonus principles • Dependency Inversion 
 Principle • Single Responsibility


    Principle • Interface Segregation
 Principle
  71. Bonus principles • Dependency Inversion 
 Principle • Single Responsibility


    Principle • Interface Segregation
 Principle ✅
  72. Bonus principles • Dependency Inversion 
 Principle • Single Responsibility


    Principle • Interface Segregation
 Principle ✅ ✅
  73. Bonus principles • Dependency Inversion 
 Principle • Single Responsibility


    Principle • Interface Segregation
 Principle ✅ ✅
  74. Pure DI •DI Frameworks aim to simplify the composition •DI

    containers vs Pure DI •DI containers are NOT required
  75. Where does DI shine?

  76. Where does DI shine? •Where the abstraction is clear

  77. Where does DI shine? •Where the abstraction is clear •Runtime

    dependencies and boundaries
  78. Where does DI shine? •Where the abstraction is clear •Runtime

    dependencies and boundaries •Business logic abstractions may be harder to define and costly to backtrack
  79. Conclusions •Every import of an external library is creating coupling

    •Consider the responsibility that’s being fulfilled •Abstract only if it’s obvious •You do not need to go all-in with frameworks, DI can be applied gradually
  80. Further reading https://www.manning.com/books/dependency-injection-principles-practices-patterns

  81. Further reading https://www.sandimetz.com/99bottles

  82. Further reading https://www.destroyallsoftware.com/talks/boundaries

  83. Thank you! Yeray Díaz @yera_ee