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

Comments

5 participants
@AlexBravo

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

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Jun 16, 2015

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.

Owner

JakeWharton commented Jun 16, 2015

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

This comment has been minimized.

Show comment
Hide comment
@Jogan

Jogan 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.

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

This comment has been minimized.

Show comment
Hide comment
@IgorGanapolsky

IgorGanapolsky Oct 22, 2015

Contributor

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

Contributor

IgorGanapolsky commented Oct 22, 2015

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

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Oct 22, 2015

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.

Owner

JakeWharton commented Oct 22, 2015

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

This comment has been minimized.

Show comment
Hide comment
@IgorGanapolsky

IgorGanapolsky Oct 22, 2015

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).

Contributor

IgorGanapolsky commented Oct 22, 2015

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

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Oct 22, 2015

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.

Owner

JakeWharton commented Oct 22, 2015

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

This comment has been minimized.

Show comment
Hide comment
@IgorGanapolsky

IgorGanapolsky Oct 22, 2015

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).

Contributor

IgorGanapolsky commented Oct 22, 2015

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

This comment has been minimized.

Show comment
Hide comment
@AlexBravo

AlexBravo Oct 23, 2015

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?

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

This comment has been minimized.

Show comment
Hide comment
@IgorGanapolsky

IgorGanapolsky Oct 23, 2015

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).

Contributor

IgorGanapolsky commented Oct 23, 2015

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

This comment has been minimized.

Show comment
Hide comment
@dalewking

dalewking Oct 26, 2015

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)).

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

This comment has been minimized.

Show comment
Hide comment
@IgorGanapolsky

IgorGanapolsky Oct 26, 2015

Contributor

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

Contributor

IgorGanapolsky commented Oct 26, 2015

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

@dalewking

This comment has been minimized.

Show comment
Hide comment
@dalewking

dalewking Oct 26, 2015

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

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

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Nov 6, 2015

Owner

No plans for this.

Owner

JakeWharton commented Nov 6, 2015

No plans for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment