If you know me, you probably know that I’m not a huge fan of dependency injection frameworks. I’ve used them for a very long time but lately, especially after learning functional programming, I noticed that I’m not gaining anything useful from them. If you use Java there is ~99% probability that you are using Spring to manage your dependencies. But have you tried asking yourself: why I am doing this?
Recently I came up with a very good blog post which basically describes how to refactor your code so that you can inject your dependencies without usage of DI frameworks. I must confess that I completely agree with author’s opinion and how he has refactored his code. Having lambdas, there is no excuse for not doing this. This is basically the same approach we are doing in our company. We got rid of Spring completely and our code became more lightweight and even more testable. Also we don’t need to pack additional ~10-15 MB of unneeded dependencies.
But why managing dependencies by yourself is better than using DI container? Few reasons come to my mind:
- Your code does not depend on some framework to wire everything up. Because it’s your code, you should know better how to do this.
- Performance mostly is better because there are no proxies, heuristics involved when resolving your dependencies.
- Your code becomes easier to test. No need for additional Spring, Mockito JUnit runners, etc. Also, instead of depending on some objects you should mostly depend on simple functions. Mocking becomes really trivial and straightforward.
- No more meaningless stack traces (especially if you are using Spring)
- It lets you to see your code smell faster. If you are having a hard time to manage your dependencies manually, it is a clear indication that there are issues with your code so you need to refactor it to make things easier. Usually DI containers hide this until the point when you need to refactor too much and we all know that refactoring should be done in small steps.
Just one notice. At first it could be quite hard to grasp why this approach is better, especially if you are doing basic OOP. When you know more functional programming, you will start to realize that there can be simpler answers or alternatives to many problems. The same goes with DI frameworks. You don’t need them (and mostly you don’t find them) in functional languages because language itself is designed to let you use simple approaches or patterns to accomplish things. But you need to learn the basic concepts first (monads, function composition, currying, partial application, lazy evaluation, statelessness, etc.) to start mastering them.