The Dependency Injection Paradigm

Posted on by Matthias Noback

Paradigm; a nice word that means "a theory or a group of ideas about how something should be done, made, or thought about" (Merriam-Webster). In software development we have them too. From the philosophy and history of science courses I've followed, I remember that scientists working with different paradigms have great difficulty understanding each other, and appreciating each other's work.

Paradigm Shifts

An example of a paradigm is the theory that the sun revolves around the earth. To a certain extent this is a fruitful theory, and it has been used for thousands of years. There's of course another paradigm: the theory that the earth revolves around the sun. This is also a fruitful theory, and it can be used to explain a lot of observations, more than the previous theory. Still, people got angry with each other for moving the earth out of the center of the universe. Paradigm changes, or shifts, occur when the old theory has been stretched too much. It becomes impossible to hold on to it. Then some people start to experiment with a completely different paradigm, one that sounds totally weird, but in the end proves to have more power.

Now back to software development: we have paradigms and paradigm shifts too. For example, PHP went from being a very dynamically typed language to being a more statically typed language. This is weird for some, but great for others since it unlocks new possibilities, like static analysis and automated refactoring.

The DI Paradigm

Another paradigm shift happened years ago when we went from symfony1 to Symfony 2, which introduced the Dependency Injection container. The idea of Dependency Injection was quite new to many developers back then, and we had to talk and read about it a lot before we were ready for this amazing yet weird concept. What got in the way of adoption, I think, was the Yaml or XML syntax for service definitions, an approach that was probably copied from Spring. If we'd start by writing our own service containers in plain PHP, that would've been much easier to learn and do.

What's interesting to me is that Symfony's first DI container was showing some influence from the old paradigm, e.g.

  • Singleton services: most services are instantiated only once, which allows for stateful services, mimicking the actual singletons from before.
  • The container had services that aren't services (e.g. the current HTTP request object).

Nevertheless, we got a taste of DI: expect your dependencies to be injected, instead of having to fetch them yourself. This changes everything!

  • Dependency injection is inversion of control: a service doesn't have to be worried about setting up a dependency, it can just declare it, and it will be taken care of.
  • Depending on an interface gives the developer the option to switch out implementations, for whatever reason.
  • Looking at the constructor signature, you can get some idea of what the service is going to do, and a complete overview of what it needs.
  • If a class is not a service, you can't give it service dependencies. This makes it absolutely clear what type of object a class represents: it's either a service, or some other object like an entity, or a value object.

I was totally convinced that the Dependency injection paradigm was a step forward, out of the land of unclear dependencies and tightly coupled classes. And I thought every other developer would like it too. Surprisingly, the introduction of a new framework - Laravel - revived the old paradigm, and with great success. It's surprising because a paradigm shift isn't often reverted. In science, the paradigm shift indicates a step forward, towards a theory that can explain more phenomena than the previous paradigm could. In programming, it turns out, you can have developers working with different paradigms, and even arguing that neither of those paradigms is a step forward compared to the other.

Crossing the Bridge

When I, as a developer from the DI paradigm, talk to someone who uses another paradigm, I find it really hard to come to some form of understanding. The assumptions, the goals, the theories that each of us uses, are very different. I find this very hard to deal with. We talk about a piece of code and I see lots of problems with it, but there is no common ground that can help us settle the debate. Personally I'm sad about this, because I don't really know how to improve the situation. You can keep fighting, and this happens a lot (e.g. on Twitter, Reddit), but since developers use completely different paradigms, I think that produces only negativity. In the case of "Symfony vs Laravel" it results in a lot of barbaric backstabbing, sub-tweeting, and making fun of each other's important concepts.

To stop fighting means you can start discussing. But I find that to be hardly an option too. It seems that people have no desire to cross the bridge, or to meet somewhere in the middle. Both opponents in the discussion have success stories about their own paradigm, so they will never give it up, and most certainly they won't give it up when they are being convinced to do so. They have to first experience that their paradigm has issues.

Another option, very relevant today, is considering every opinion to be equal: we can all have our own preferred way of programming and we shouldn't try to convince others to do things differently. In programming, as much as it is in real life, this is complete nonsense. Not every opinion is equal: not every opinion is backed by solid reasoning, or experience, or knowledge about the topic.

Bringing this back to scientific paradigm shifts: there is this time between paradigms when there's a lot of friction. At some point the benefits of the new paradigm start to outweigh the benefits of the old paradigm and people will make the jump. Before that, people will be mad at each other a lot."You're so stupid to think that the sun goes around the earth", "It's blasphemy to say that the earth goes around the sun", and so on.

A conclusion? I honestly don't know what to do about it. At least I think it's useful to have this concept of a paradigm in software development and use it to explain why us software developers are divided and end up not understanding each other.

PHP dependency injection Symfony Laravel
This website uses MailComments: you can send your comments to this post by email. Read more about MailComments, including suggestions for writing your comments (in HTML or Markdown).