In order to make a Java side project of mine easier to evolve and test, I wanted to add dependency injection. After a quick lookup, I figured that Dagger2 would be a really nice little thing to add to my project. So here is why I’m not using Dagger2 on my project.
Disclaimer: this is only my opinion, Dagger2 seems really good and I’ll most probably use it in a future project where it is more suitable.
My project is split into a core library (to be reused later) and the main project. Quite a bit of the library is built to be sub-classed while enforcing a certain flow, validation and features for the main project.
While tinkering with Dagger2, I did notice a few things that were annoying to me:
- No support for inheritance;
- Complex integration with Eclipse (through Gradle);
- Lack of simple examples
The lack of support for inheritance was already a blocker for me. Still, in order to get a good feel of the library, I decided to try to get around the limitation. Doing so required me to manually inject into my super-class when building my instances. This exposed quite a bit of things that had no right being exposed to the subclass. It also made the code harder to evolve since I would need to update my sub-classes every time I add a dependency into my core library. That would require an API break where there should be none.
I’m new to the whole Gradle ecosystem, and getting it to work correctly with Eclipse was already quite a task (see this post and that post). Integrating Dagger2 into all of that proved to be really painful. I probably missed something somewhere, could simply be missing a bit of documentation somewhere. I do plan on trying to make it work again in the future and document how to get it all running.
Finally, Dagger2 allows support of really complex scenarios, but, sadly, it exposes a lot of complexity when trying to do something simple. This could be due to a lack of simple examples or simply a misunderstanding on my part. One way or another, I do plan on getting back to this to figure out how to use it in simple scenarios.
In the end, I decided to go with something extremely simple that supports only what I need:
- Global Singletons;
- Introspection is used only to inject the dependency manager in the constructor (if needed)
In the end, usage looks roughly like:
// Somewhere initializing the project
DependencyManager dependencies = new DependencyManager();
// Somewhere else with access to the DependencyManager instance
this.eventDispatcher = dependencyManager.resolve(EventDispatcher.class);
I did add a few other helpers in there. Nothing too fancy, just quality of life.