Warning: This is quite an old article. Since then on this topic I have posted another about Dependency Injection: Dependency Inversion and Interface Segregation using Laravel’s Service Container
Good evening everyone.
I’ve been meaning to write a post about this for a little while, it’s a common discussion point within developers working on enterprise level software. The argument regarding dependency injection vs. facades; how they’re applied and how they relate to most software systems you work with.
The first point I would like to make on this particular topic is that they are both useful, they both have their place.
For those of you who are not exactly aware of what these concepts are I have broken it down a little bit below; but if you’re not comfortable or familiar with the topic it probably is worth doing some research on before you make your mind up.
In essence, dependency injection is where you declare your class usages in a single place as a dependency, those dependencies are injected into where they are used. The concept behind this is that should you wish to swap out your dependency it should be easy. Take the following example;
I have a class named PermissionChecker. This class is used throughout many Controllers in an MVC framework. Whenever I want to check if someone has a permission I simply call upon functionality within the permission checker, which returns me a true or false.
The basic problem here is when I want to change the PermissionChecker, which contains all of my permission-based logic, it is painful, because I have to go through and replace or remove every instance of the PermissionChecker and hope that it doesn’t break anything, and I test everything heavily.
This is where Dependency Injection (DI) comes in. I create an instance of my PermissionChecker (PC) within the DI container. There are various open source DI solutions out there from Pimple to the DependencyInjector by Symfony. Anyway, the long and short of it is that the declaration of the usage of PC is in a single place, so should I wish to change it for SupremePermissionChecker (SPC) then it is easy and done in a single place, assuming the interfaces through which it is accessed remain the same.
This is the perfect solution to an age old problem!
But beware! There is an issue with DI, in my experience, and that is that either you become so dependent on it that it becomes difficult to utilise functionality and you end up writing lots of code which, in practicality, does very little. Or potentially you can end up over injecting, some parts of your system will be tightly coupled to one another by design, the issue with DI here simply compounds this issue, because the tightly coupling in a lot of days makes the DI redundant; as you couldn’t swap out the dependency even if you wanted to.
Now please don’t, for a second, think that I am slating dependency injection, because I’m really not. I think it is a very useful tool, it’s not my tool of choice but it does have a lot of advantages.
Additionally; don’t think the next thing I am going to mention is mutually exclusive to Dependency Injection either, they can be used in tandem without any issues.
So a facade is where you create a class which hides more complex logic behind it. Taking the same example I might have a PermissionChecker class which facades other functionality, for example fetching a user, fetching permission records which it can cross reference against the permission we are checking into.
In essence a facade is a way of abstracting your functionality a layer further. You have your system which utilises your facade, and your facade utilises whatever it needs to.
The reason I prefer this methodology, personally, is because you end up with all of your facades talking to one another. Which makes your Controllers very readable as you end up with something not dissimilar to:
if ( $permissionChecker->hasPermission(‘make-payment’) ){
$paymentThing->makePayment( $account, $sortCode );
}
Which I feel is very “English” in that it’s quite easy to read it and understand what’s going on. Additionally the advantage, for me, is that if Developer A (DA) and Developer B (DB) are both working on functionality within the same version it is easy. DA can be modifying whatever he wants in PC whilst DB can be happily working away on changing the payment gateway PaymentThing is using, as long as the interfaces remain the same then it’s all good.
To add to the mix, remember where I said earlier the two weren’t mutually exclusive? PaymentThing and PermissionChecker could well have both been dependency injected into their current context, so they could be switched out.
My only real question there is: why? If my functionality is all hidden behind facades, which provide easy interfaces to use, if ever I want to change them or do anything with them, I do it behind the facade and I’m fine. With that in mind, does Dependency Injection become a bit overkill?
Both of these concepts, as with all concepts, methodologies and rules within web development, are designed to make maintaining my software easier, rather than having invisible dependencies and entangled tight coupling which is impossible to defuse. That’s a developer’s nightmare when someone says “can’t we just take the payment functionality from X project and put it into Y project?”.
I think we have to sometimes be careful in web development and programming in general that we’re not making more work for ourselves. If facades are working for the separation of concerns, does it matter if the dependencies are scattered through the code, because somewhere that once needed to make a payment will always need to make a payment, and if that requirement changes, the code will need to change anyway, so we cut out the bit that says make a payment. We don’t have to remove the dependency or do anything else.
When I want to include payments into a new set of functionality on the site all I have to do is utilise the use statement to bring in the Facade, which handles everything else, and use the functionality contained therein.
Maybe I am missing the point and the value. And I would rather have Dependency Injection than nothing, but I would rather have an easy-to-utilise set of Facades, than have to Dependency Inject everything I want to use, and remember to rip it out when I don’t.
I’d love to hear other developers’ opinions on this one though, as it is something of a bone of contention in the community.
Take care all!
Johno
I tend to avoid both of these design patterns, as I find they hide the actual implementation. According to me hiding the implementation increases the cyclomatic complexity by making it harder for junior and mid level developers to understand the logic behind the code. if a team member cannot understand the logic, the code will easily become obsolete, and will be thrown away once the original developer is no longer around.
I actually do agree with you here and even heavyweight/senior/lead developers can find it sometimes difficult to follow more complex code of the amount of abstraction for the sake of dependency management is excessive. I read an article that was aimed at debunking, or at least making on reconsider, the SOLID principles by offering alternatives. The main theme was “just write good code”, which sounds arrogant to start with but I found myself agreeing. If it’s fast enough to produce, hits the spec (security and performance etc), and is easy to follow and maintain everything else is secondary, in my opinion