Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dagger 2 support #158

Closed
AlexBravo opened this issue Jun 9, 2015 · 13 comments
Closed

Dagger 2 support #158

AlexBravo opened this issue Jun 9, 2015 · 13 comments

Comments

@AlexBravo
Copy link

The differences between Dagger 1 and 2 are not trivial, so would be nice if this sample used Dagger 2 instead of Dagger 1.

@JakeWharton
Copy link
Owner

Right now we're using Dagger 1 internally and probably not upgrading any time soon so I'd prefer to keep this app matching. This will make it easier to include more of our internal structure here in the future. That's not to say we won't upgrade, it's just not a high priority right now.

@Jogan
Copy link

Jogan commented Aug 31, 2015

@AlexBravo I've forked the project and added Dagger 2 support here https://github.com/prolificinteractive/u2020 everything else remains the same other than that.

@IgorGanapolsky
Copy link
Contributor

It would be nice indeed to see u2020 migrated to Dagger2. Is there a reason you are still using Dagger1 internally?

@JakeWharton
Copy link
Owner

It serves our use case much better than Dagger 2. We leverage granular overrides in the runtime and its flexibility for testing that cannot be achieved in v2 without far too much ceremony.

@IgorGanapolsky
Copy link
Contributor

I see. I am wondering why they had to go invent Dagger2 when Dagger1
worked perfectly fine? I mean it's such a headache for other developers to
make this switch....
On Oct 22, 2015 1:16 PM, "Jake Wharton" notifications@github.com wrote:

It serves our use case much better than Dagger 2. We leverage granular
overrides in the runtime and its flexibility for testing that cannot be
achieved in v2 without far too much ceremony.


Reply to this email directly or view it on GitHub
#158 (comment).

@JakeWharton
Copy link
Owner

No one is forcing you to switch. It was created with very specific use cases in mind which were unsolved by Dagger 1. It shouldn't have been called Dagger 2 but something else.

@IgorGanapolsky
Copy link
Contributor

Nobody is forcing me to do anything, I know. But the general sentiment is
that if something is called "Something2", then it must be better than
"Something1". And most developers (naive like myself) will feel the urge
to update to "Something2". You are right, they shouldn't have called it
Dagger2 if it is so drastically different and hard to migrate from Dagger1.

Thanks,
Igor

On Thu, Oct 22, 2015 at 1:18 PM, Jake Wharton notifications@github.com
wrote:

No one is forcing you to switch. It was created with very specific use
cases in mind which were unsolved by Dagger 1. It shouldn't have been
called Dagger 2 but something else.


Reply to this email directly or view it on GitHub
#158 (comment).

@AlexBravo
Copy link
Author

Never mind people who upgrade.
What about the new people who are about to use Dagger for the first time?
Would they use Dagger or Dagger 2?

This needs to be resolved somehow...
Any chances that Dagger 3 will unify the use cases of both Dagger 1 and 2?

@IgorGanapolsky
Copy link
Contributor

That's a great question. I myself was in that boat a few months back. I
was led to believe that Dagger1 is deficient. So I spent time learning
Dagger2. But now I don't know why.
On Oct 22, 2015 8:05 PM, "Alex Bravo" notifications@github.com wrote:

Never mind people who upgrade.
What about the new people who are about to use Dagger for the first time?
Would they use Dagger or Dagger 2?

This needs to be resolved somehow...
Any chances that Dagger 3 will unify the use cases of both Dagger 1 and 2?


Reply to this email directly or view it on GitHub
#158 (comment).

@dalewking
Copy link

The big thing that Dagger 2 has that Dagger 1 does not (unless you are on a very early build of Dagger 1) is the ability to support Proguard obfuscation.

The big problem with Dagger 2 is that it requires compile-time static linking to an injection method on the component which unfortunately has lead many people down very bad paths where people are actually using a dependency injection framework in a manner that is doing service lookup instead of dependency injection. If you see things like components being instantiated within the actual object being injected (or even just slightly hidden behind another method but still bound at compile time) then run away, this is not dependency injection. By the way, most of the Dagger 2 examples do this.

There are some libraries that try to aleviate this see Bullet (https://github.com/tbroyer/bullet) or my preliminary rewrite of Bullet (https://gitlab.com/NobleworksSoftware/NobleInjection/tree/master). These libraries try to add the ability to have a generic injection method on the component (e.g. inject(T t)).

@IgorGanapolsky
Copy link
Contributor

@dalewking I don't understand. It sounds like you're saying Dagger2 is a mistake for most developers to try and use.

@dalewking
Copy link

What I am saying is that it is hard to use Dagger 2 correctly and the way it is designed sort of encourages people to use it incorrectly. It requires extra care and even extra libraries to use it in a good way. This is one of the few articles that I have seen actually discuss the issue: https://blog.gouline.net/2015/05/04/dagger-2-even-sharper-less-square/, see Annoyances section, but the issues is bigger than that and I do not like the runtime reflection solution.

There are two issues, how do you determine the correct component to do the injection and given the correct component how do you call the injection method. What most people end up doing is binding at compile time what component is used and calling the method. Either they actually instantiate the component inside the object being injected or perhaps hide it in a base class. But then substituting what gets injected for unit testing e.g. becomes a near impossibility, thus you are not doing dependency injection.

What I did in my library is two-fold. I provide an injection service singleton (see https://gitlab.com/NobleworksSoftware/NobleInjection/blob/master/android-injection-service/src/main/java/com/nobleworks_software/injection/android/InjectionService.java) that you set up in initialization. Things like an Activity just need to call InjectionService.inject(this); to be injected which is pretty much the best we can get. The activity itself then has no knowledge of what component is used as is should be.

The second part is tackling calling the correct injection method based on an arbitrary class since Java does not do double dispatch. One way is using reflection as explained in that article, my solution is a rewrite of the Bullet library which uses annotation processing to generate a generic wrapper around the Dagger 2 component to give you a generic method to call for injection Bullet had the right idea, but a horrible implementation (but there is a PR based on my work to fix that). This annotation processing could be done much easier and more efficiently inside of Dagger 2.

For some other discussions I have been involved with on the subject see:

google/dagger#213
tbroyer/bullet#2
google/dagger#110

I took an existing Dagger example and rewrote it to use my library. I didn't use u2020, because u2020 didn't really use subcomponents which I wanted to demonstrate. See:

https://gitlab.com/NobleworksSoftware/NobleInjection/tree/master/githubclient-example/src/main

@JakeWharton
Copy link
Owner

No plans for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants