Update from Forestry.io

Harsh Shandilya updated content/posts/my-dagger-story.md
This commit is contained in:
Harsh Shandilya 2020-01-05 15:39:52 +00:00 committed by Forestry.io
parent a9fdea2c15
commit 69102cebe0
1 changed files with 14 additions and 16 deletions

View File

@ -8,19 +8,19 @@ tags = ["android", "dagger"]
title = "My Dagger Story"
+++
[Dagger] is infamous for very good reasons. It's complicated to use, the documentation is an absolute shitshow, and simpler 'alternatives' exist. While [Koin] and to a lesser extent [Kodein] do the job, they're still service locators at their core and don't automatically inject dependencies like Dagger does.
[Dagger](https://dagger.dev) is infamous for very good reasons. It's complicated to use, the documentation is an absolute shitshow, and simpler 'alternatives' exist. While [Koin](http://insert-koin.io/) and to a lesser extent [Kodein](https://kodein.org/di/) do the job, they're still service locators at their core and don't automatically inject dependencies like Dagger does.
## Background
Before I start, some introductions. I'm the sole developer of [Viscerion](https://play.google.com/store/apps/details?id=me.msfjarvis.viscerion), an Android client for [WireGuard](https://www.wireguard.com/). It is a fully [open source](https://github.com/msfjarvis/viscerion) project just like the upstream Android client which served as the base for it. I forked Viscerion as a playground project that'd let me learn new Android tech in an unencumbered way and be something that I'd actually use, hence guaranteeing some level of sustained interest. I do still contribute major fixes back upstream, so put down your pitchforks :P
Like I said before, Viscerion is a learning endeavour, so I decided to learn. I rewrote most of the app in Kotlin, implemented some UI changes to make the app more friendlier to humans and added a couple features here and there.
Like I said before, Viscerion is a learning endeavour, so I decided to learn. I rewrote most of the app in Kotlin, implemented some UI changes to make the app more friendlier to humans and added a couple features here and there.
And then I decided to tackle the Dependency Injection monster.
## The beginnings
The dependency injection story always begins with the search for a library that does it for you. You look at Dagger, go to the documentation, look up what a Thermosiphon is, then scratch Dagger off the list and move on. Kotlin users will then end up on one of [Koin] or [Kodein] and that'll be the end of their story.
The dependency injection story always begins with the search for a library that does it for you. You look at Dagger, go to the documentation, look up what a Thermosiphon is, then scratch Dagger off the list and move on. Kotlin users will then end up on one of [Koin](http://insert-koin.io/) or [Kodein](https://kodein.org/di/) and that'll be the end of their story.
That was mine as well! Before Viscerion was forked, the app used to have Dagger (albeit sorely underused as I can tell now that I know a fair bit about it) but then it was [swapped out](https://github.com/WireGuard/wireguard-android/commit/712b6c6f600ef6eb683d356a6e9a05e9415b7e12) for singleton access from the Application class. I really, really wanted to try out the fancy 'Dependency Injection' thing everybody loved so I did some searching around, went through the aforementioned motions and [settled on Koin](https://github.com/msfjarvis/viscerion/pull/131).
@ -28,36 +28,34 @@ It was great! I could get any dependency anywhere and that allowed me to write a
## The turning point
Around mid-December 2019, [Arun](https://twitter.com/arunkumar_9t2) released the 0.1 version of his Dagger 2 dependency graph visualizer, [Scabbard](https://arunkumar.dev/introducing-scabbard-a-tool-to-visualize-dagger-2-dependency-graphs/). It looked **awesome**. I [retweeted it](https://twitter.com/MSF_Jarvis/status/1210856668310863872) and shoved in my residual Dagger hate for good measure because what else is the internet for. I was [confident](https://twitter.com/MSF_Jarvis/status/1210866037056397312) that Dagger shall never find a place in my code and my friend [Sasikanth](https://twitter.com/its_sasikanth) (super smart dude, definitely worth following) was [hell-bent on ensuring otherwise](https://twitter.com/MSF_Jarvis/status/1210935581288517632?s=20).
Around mid-December 2019, [Arun](https://twitter.com/arunkumar_9t2) released the 0.1 version of his Dagger 2 dependency graph visualizer, [Scabbard](https://arunkumar.dev/introducing-scabbard-a-tool-to-visualize-dagger-2-dependency-graphs/). It looked **awesome**. I [retweeted it](https://twitter.com/MSF_Jarvis/status/1210856668310863872) and shoved in my residual Dagger hate for good measure because isn't that what the internet is for. I was [confident](https://twitter.com/MSF_Jarvis/status/1210866037056397312) that Dagger shall never find a place in my code and my friend [Sasikanth](https://twitter.com/its_sasikanth) (super smart dude, definitely worth following) was [hell-bent on ensuring otherwise](https://twitter.com/MSF_Jarvis/status/1210935581288517632?s=20).
Together, we dug up my previous efforts and I started [a PR](https://github.com/msfjarvis/viscerion/pull/214) so he could review it and help me past the point I dropped out last time. He helped [me on GitHub](https://github.com/msfjarvis/viscerion/pull/214#pullrequestreview-336919368), privately on Telegram and together in about 2 days Viscerion was completely Koin-free and ready to kill. I put down my thoughts about the migration briefly [on the PR](https://github.com/msfjarvis/viscerion/pull/214#issuecomment-569541678), which I'll reproduce and expand on below.
>- Dagger is ridiculously complex without a human to guide you around.
> * Dagger is ridiculously complex without a human to guide you around.
I will die on this hill. Without Sasikanth's help I would have never gotten around to even *trying* Dagger again.
I will die on this hill. Without Sasikanth's help I would have never gotten around to even _trying_ Dagger again.
>- Koin's service locator pattern makes it far too easy to write bad code because you can inject anything anywhere.
> * Koin's service locator pattern makes it far too easy to write bad code because you can inject anything anywhere.
Again, very strong opinion that I will continue to have. Being able to inject lifecycle sensitive dependencies like `Context` to an `object` felt wrong and still does.
>- Dagger can feel like a lot of boilerplate but some clever techniques can mitigate that.
> * Dagger can feel like a lot of boilerplate but some clever techniques can mitigate that.
Because the Dagger documentation wasn't helpful, I didn't realise that a @Provides annotated method and an @Inject'ed constructor was an either-or situation -- I didn't need to write both for a class to be injectable. Sasikanth [with the rescue again](https://github.com/msfjarvis/viscerion/pull/214#discussion_r361800427).
Because the Dagger documentation wasn't helpful, I didn't realise that a `Provides` annotated method and an `@Inject`ed constructor was an either-or situation and I didn't need to write both for a class to be injectable. Sasikanth [with the rescue again](https://github.com/msfjarvis/viscerion/pull/214#discussion_r361800427).
>- Writing `inject` methods for every single class can feel like a drag because it is.
> * Writing `inject` methods for every single class can feel like a drag because it is.
[I mean...](https://github.com/msfjarvis/viscerion/blob/master/app/src/main/java/com/wireguard/android/di/AppComponent.kt#L69-L101)
>- Injecting into Kotlin `object`s appears to be a no-go. I opted to [refactor out the staticity where possible](https://github.com/msfjarvis/viscerion/pull/214/commits/9eb532521f51d0f7bb66a2a78aa1fc5688128a22), [pass injected dependencies to the function](https://github.com/msfjarvis/viscerion/commit/e23f878140d4bda9e2c54d6c2684e07994066fd6#diff-28007a5799b03e7b556f5bb942754031) or [fall back to 'dirty' patterns](https://github.com/msfjarvis/viscerion/pull/214/commits/fc54ec6bb8e99ec639c6617765e814e12d91ea1a#diff-74f75ab44e1cd2909c4ec4d704bbbab7R65) as needed. Do what you feel like.
> * Injecting into Kotlin `object`s appears to be a no-go. I opted to [refactor out the staticity where possible](https://github.com/msfjarvis/viscerion/pull/214/commits/9eb532521f51d0f7bb66a2a78aa1fc5688128a22), [pass injected dependencies to the function](https://github.com/msfjarvis/viscerion/commit/e23f878140d4bda9e2c54d6c2684e07994066fd6#diff-28007a5799b03e7b556f5bb942754031) or [fall back to 'dirty' patterns](https://github.com/msfjarvis/viscerion/pull/214/commits/fc54ec6bb8e99ec639c6617765e814e12d91ea1a#diff-74f75ab44e1cd2909c4ec4d704bbbab7R65) as needed. Do what you feel like.
I have no idea if that's even a good ability to begin with, so I chose to change myself rather than fight the system.
>- I still do not _love_ Dagger. Fuck you Google.
> * I still do not _love_ Dagger. Fuck you Google.
This, I probably don't subscribe to anymore. Dagger was horrible to get on board, but I am now in a position where I can find someone who's stuck like I was and help them come over the same way my friends helped me.
## To summarize
[Dagger]: https://dagger.dev
[Koin]: http://insert-koin.io/
[Kodein]: https://kodein.org/di/
Like RxJava, Dagger has become an industry standard of sorts and a required skill at a lot of Android positions so eventually you will end up needing to learn it anyway, so why wait? Dagger is not _terrible_, just badly presented. People have tried for years to make it easier to access but something about its complexity just doesn't click through to new users. I can't speak for people who've learned Java through books and/or college courses, but as a self-taught programmer who learnt by writing code and getting screamed at by the compiler, it was hard but not impossible.