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

Dependency Injection with PHP

Dependency Injection with PHP

Bastian Hofmann

February 28, 2013
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. Have you seen code like this? a mess of spaghetti

    code without any understandable logic, hard to read.
  2. or like this? acient legacy code where nobody knows how

    it works anymore and what it even does, and you are afraid to touch it?
  3. in actual code this may probably look somehow like this,

    look sql queries, views, everything jubmled together in some weirdly named funtions (also really insecure (xss)).
  4. Dependency Inversion and one part of that that I want

    to focus on in this talk is dependency inversion
  5. Dependency Injection Containers and made easier with dependency injection containers

    so that you avoid ending up such a code mess in your project or to help you when you have to refactor such a mess
  6. before that, a few words about me, I work at

    ResearchGate, the social network for researchers and scientists
  7. ResearchGate gives science back to the people who make it

    happen. We help researchers build reputation and accelerate scientific progress. On their terms. ‟ the goal is to give...
  8. .. to have this in the company you are working

    for, and additionally want to work on some very interesting stuff
  9. Questions? Ask by the way, if you have any questions

    throughout this talk, if you don't understand something, just raise your hand and ask. probably my fault anyways since i spoke to quickly or my accent was too bad
  10. ? what about you? php developers? own product/s or agency

    work? large codebases? who is using dependency injection containers already? which?
  11. http://www.doolwind.com/blog/solid-principles-for-game-developers/ dependency inversion is one of the 5 principles of

    SOLID software design, SOLID means: single responsibility, open/closed principle, liskov substitution principle, interface segregation principle, dependency inversion principle
  12. http://qafoo.com/presentations.html I will only touch dependency inversion in this talk,

    if you want to know more about SOLID I recommend this excellent talk from Tobias Schlitt
  13. A B C so you have a module a that

    depend on a module b that depends on a module c. pretty common dependency graph but actually a violation of the dependency inversion principle
  14. A B C interface interface instead a should depend on

    an interface which is in it's own module that is implemented by b, and b should depend on an interface that is implemented by c. so we are inverting the dependency chain
  15. A B C interface if you have two modules depending

    on the same sub-module, you could extract the common interface into its own module
  16. A B Adapter interface C and if c is actually

    3rd party or legacy code that you can't change, you could write an adapter class that implements the interface and extends c. this is actually very good practice because than you easily can change the implementation of c if you want to without touching your other code because the interface can stay the same.
  17. in this example class we have several hardcoded dependencies: Cache,

    Validator and HttpClient, actually also the json_decode call is somewhat a dependency. this makes our class hard to test, we can not mock the dependencies so for testing we actually need a test and an http service, also if we want to change the validator in our whole codebase, that would mean lot's of work
  18. we can inject the dependencies through constructor arguments, easy to

    mock now, but we still depend on concrete implementations here, and not interfaces (abstractions), so still much work if we want to change an implementation
  19. better, lets just depend on interfaces, so if we want

    to change the implementation e.g. of the validator, the only thing we still have to make sure is to implement the same interface (for example through an adapter class)
  20. you can also inject dependencies through a setter, good for

    optional dependencies. in this example we should then add a check if $this->cache is really set
  21. Easier to change that is easier to change with different

    implementations or during refactoring
  22. Only test the class, not the dependencies so we can

    only test our class and not all the dependencies with it
  23. http://www.doolwind.com/blog/solid-principles-for-game-developers/ also all this injection of dependencies makes it easier

    to comply with another of the solid principles called the single responsibility principle, which says that a class only does one thing and not multiple things. the multiple things we could then just refactor out of the class and inject them as dependencies
  24. this is not really nice, especially if we need this

    service in 500 different places in our codebase, adding a dependency afterwards would also be a refactoring nightmare
  25. so instead of creating our service manually each time, we

    can just call this factory method which creates it for us, if we add or change a dependency this is then the only place where we have to add it
  26. Dependency Injection Container which directly leads us to dependency injection

    containers, because in the end the help us or automate the process of creating these factories
  27. rg\injektor inspired by google-guice i want to explain the workings

    of a dic on the container we wrote for researchgate and which is modeled after google-guice, a java dic. which of the dics you choose is mostly a matter of different requirements and taste. since all of them work a bit differently in usage, configuration and performance. one of our goals in writing our own was to make it very easy and unnoticable to use while still being very fast.
  28. $ wget http://getcomposer.org/composer.phar $ php composer.phar install Installing dependencies -

    Installing monolog/monolog (1.1.0) Downloading: 100% ... monolog/monolog suggests installing mlehner/ gelf-php (Allow sending log messages to a GrayLog2 server) Writing lock file Generating autoload files
  29. for convenience it is a good practice to add something

    like this public static property to a class which returns the class name of the class as a string, this gives you ide support like auto completion, usage analysis, refactoring support and so on
  30. @inject rg\injection needs an annotation so that it tries to

    create all dependencies automatically
  31. technically not really necessary but good for clarity, so that

    you know that this classes dependencies are possibly injected automatically
  32. Singletons are evil! not sanely testable, mixture of responsibilites, you

    don‘t know about the state of the singleton at all, same as static functions
  33. Production: Generated Factory Classes why that? normally DIC gets classname,

    reflection, looks at constructor arguments, injectable or not? if class start over recursively, but reflection is slow, so instead of reflection it uses factory classes that are pre generated during deployment like the factory classes we saw earlier
  34. http://twitter.com/BastianHofmann http://profiles.google.com/bashofmann http://lanyrd.com/people/BastianHofmann http://speakerdeck.com/u/bastianhofmann https://github.com/bashofmann https://www.researchgate.net/profile/Bastian_Hofmann/ [email protected] Did you like

    this talk? https://joind.in/7880 thanks, you can contact me on any of these platforms or via mail. if you liked this talk or didn't like it, please rate it on joind.in. this is very important for me for improving my talk, for the organizers for selecting the best talks and speakers and for you to get the best content on the conferences you visit.