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

Proposal: Dagger 2.0 #366

Closed
gk5885 opened this Issue Dec 10, 2013 · 14 comments

Comments

5 participants
@gk5885
Contributor

gk5885 commented Dec 10, 2013

For a while now, we have floated ideas about full-graph generation and how we might evolve Dagger from half static, half runtime to a fully static, fully generated, fully awesome DI solution. In working with Dagger in a large application on the server side we ran into some particular pain points that shaped how we might want a static solution to look. So, I present a proposal for Dagger 2.0 that hopefully bridges the gaps between what's suitable on Android and what makes sense for very large applications, with ridiculous numbers of bindings.

https://docs.google.com/document/d/1fwg-NsMKYtYxeEWe82rISIHjNrtdqonfiHgp8-PQ7m8/edit?usp=sharing

Everybody should be able to comment. Feedback on this bug and in the doc are both welcome.

I have also developed a prototype for this solution. It works pretty well, but the code is still slightly embarrassing. I will try to get that cleaned up and into a github repository shortly. I'll update the bug when that happens.

@cgruber

This comment has been minimized.

Show comment
Hide comment
@cgruber

cgruber Dec 10, 2013

Collaborator

I'm excited.

Collaborator

cgruber commented Dec 10, 2013

I'm excited.

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Dec 10, 2013

Collaborator

It's a lot to take in but exciting indeed! I'll have to pass through the
doc more carefully soon.


Jake Wharton
http://about.me/jakewharton

On Tue, Dec 10, 2013 at 1:54 PM, Christian Edward Gruber <
notifications@github.com> wrote:

I'm excited.


Reply to this email directly or view it on GitHubhttps://github.com/square/dagger/issues/366#issuecomment-30271953
.

Collaborator

JakeWharton commented Dec 10, 2013

It's a lot to take in but exciting indeed! I'll have to pass through the
doc more carefully soon.


Jake Wharton
http://about.me/jakewharton

On Tue, Dec 10, 2013 at 1:54 PM, Christian Edward Gruber <
notifications@github.com> wrote:

I'm excited.


Reply to this email directly or view it on GitHubhttps://github.com/square/dagger/issues/366#issuecomment-30271953
.

@adriancole

This comment has been minimized.

Show comment
Hide comment
@adriancole

adriancole Dec 11, 2013

Contributor

Interesting design WIP. Thanks for putting it together!

Contributor

adriancole commented Dec 11, 2013

Interesting design WIP. Thanks for putting it together!

@gk5885

This comment has been minimized.

Show comment
Hide comment
@gk5885

gk5885 Dec 13, 2013

Contributor

OK, here's the (still somewhat messy) code: https://github.com/gk5885/dagger/tree/pipe-dream

I recommend taking a look at how this all comes together in the sample. I'm working thorough the features that enable the more interesting bits of graph composition. I'll update this issue and the sample code when I get that stuff running.

Contributor

gk5885 commented Dec 13, 2013

OK, here's the (still somewhat messy) code: https://github.com/gk5885/dagger/tree/pipe-dream

I recommend taking a look at how this all comes together in the sample. I'm working thorough the features that enable the more interesting bits of graph composition. I'll update this issue and the sample code when I get that stuff running.

@cgruber

This comment has been minimized.

Show comment
Hide comment
@cgruber

cgruber Feb 14, 2014

Collaborator

Just as a process FYI, the first few commits have gone in internally (by @gk5885) in Google's internal repo, just starting to lay out the APIs. Very quickly I'm going to branch off the 1.x stuff (per our discussions with Jesse and Bob), so we can start moving forward on 2.x as the main trunk of development, making the 1.x branch effectively a maintenance branch (though still aggressively maintained until we decide otherwise as a project.) So expect to see stuff before the end of the quarter.

Collaborator

cgruber commented Feb 14, 2014

Just as a process FYI, the first few commits have gone in internally (by @gk5885) in Google's internal repo, just starting to lay out the APIs. Very quickly I'm going to branch off the 1.x stuff (per our discussions with Jesse and Bob), so we can start moving forward on 2.x as the main trunk of development, making the 1.x branch effectively a maintenance branch (though still aggressively maintained until we decide otherwise as a project.) So expect to see stuff before the end of the quarter.

@adriancole

This comment has been minimized.

Show comment
Hide comment
@adriancole

adriancole Feb 15, 2014

Contributor

sounds great.

Contributor

adriancole commented Feb 15, 2014

sounds great.

@johnlcox

This comment has been minimized.

Show comment
Hide comment
@johnlcox

johnlcox Apr 24, 2014

With the ObjectGraph being deprecated will there be something equivalent to ObjectGraph#get(type)?

johnlcox commented Apr 24, 2014

With the ObjectGraph being deprecated will there be something equivalent to ObjectGraph#get(type)?

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton Apr 24, 2014

Collaborator

You'll have to use a @Component interface for creating types.

@Component(module = FooModule.class)
interface FooComponent {
  Foo getFoo();
}

Dagger will generate an implementation of this interface to which you can pass a module.

FooComponent fooComponent = new DaggerComponent_FooComponent(new FooModule());
Foo foo = fooComponent.getFoo();

While it seems like a lot to write for just one type, in practice you won't use it for a single type so the overhead of the code in relation to what you use it for won't be as drastic.

Collaborator

JakeWharton commented Apr 24, 2014

You'll have to use a @Component interface for creating types.

@Component(module = FooModule.class)
interface FooComponent {
  Foo getFoo();
}

Dagger will generate an implementation of this interface to which you can pass a module.

FooComponent fooComponent = new DaggerComponent_FooComponent(new FooModule());
Foo foo = fooComponent.getFoo();

While it seems like a lot to write for just one type, in practice you won't use it for a single type so the overhead of the code in relation to what you use it for won't be as drastic.

@johnlcox

This comment has been minimized.

Show comment
Hide comment
@johnlcox

johnlcox Apr 24, 2014

So what if you just have a Class<?> that you need to get an instance of?

For instance for dagger/jersey integration: https://github.com/johnlcox/dagger-servlet/blob/master/dagger-jersey/src/main/java/com/leacox/dagger/jersey/DaggerComponentProviderFactory.java#L180

johnlcox commented Apr 24, 2014

So what if you just have a Class<?> that you need to get an instance of?

For instance for dagger/jersey integration: https://github.com/johnlcox/dagger-servlet/blob/master/dagger-jersey/src/main/java/com/leacox/dagger/jersey/DaggerComponentProviderFactory.java#L180

@cgruber

This comment has been minimized.

Show comment
Hide comment
@cgruber

cgruber Apr 24, 2014

Collaborator

You'll make an interface, like:

@Component(...)
interface MyApplicationGraph {
  public Thing1 getParticularThing();
  public void injectFoo(Foo foo);
  //...
}

And that is your graph. Dagger 2.0 generates the implementation, which you just use. We are considering a sort of compatibility thingy, where we turn ObjectGraph into an interface with the get(Class<?> clazz) method. In the generated implementations, the get() method (and inject() method) would simply have a conditional that routes those methods to the appropriate strongly typed getter/injector method on your interface, or throw an exception.

Generally, the new pattern would not be to bother with that, but it would allow for some existing infrastructure to be re-used while more robust infrastructure is built up.

Ultimately, the @Component interface YourGraph { ... } is more powerful, in that it permits you to offer complex types (with concrete type variables, like List<String>) which we couldn't offer through the generalized get() method. So this above-mentioned mapping would largely be intended for backward compatibility with existing infrastructure.

Collaborator

cgruber commented Apr 24, 2014

You'll make an interface, like:

@Component(...)
interface MyApplicationGraph {
  public Thing1 getParticularThing();
  public void injectFoo(Foo foo);
  //...
}

And that is your graph. Dagger 2.0 generates the implementation, which you just use. We are considering a sort of compatibility thingy, where we turn ObjectGraph into an interface with the get(Class<?> clazz) method. In the generated implementations, the get() method (and inject() method) would simply have a conditional that routes those methods to the appropriate strongly typed getter/injector method on your interface, or throw an exception.

Generally, the new pattern would not be to bother with that, but it would allow for some existing infrastructure to be re-used while more robust infrastructure is built up.

Ultimately, the @Component interface YourGraph { ... } is more powerful, in that it permits you to offer complex types (with concrete type variables, like List<String>) which we couldn't offer through the generalized get() method. So this above-mentioned mapping would largely be intended for backward compatibility with existing infrastructure.

@gk5885 gk5885 closed this Apr 24, 2014

@gk5885 gk5885 reopened this Apr 24, 2014

@cgruber

This comment has been minimized.

Show comment
Hide comment
@cgruber

cgruber Apr 24, 2014

Collaborator

Actually, arbitrary last-minute instantiation via dagger was never viable - if you don't express the class Foo via @Module(injects=Foo.class) then you can't ask graph.get(Foo.class) for an instance anyway. In this case, you just make a method public Foo getFoo(). But for arbitrary classes, that was never how Dagger was designed.

Collaborator

cgruber commented Apr 24, 2014

Actually, arbitrary last-minute instantiation via dagger was never viable - if you don't express the class Foo via @Module(injects=Foo.class) then you can't ask graph.get(Foo.class) for an instance anyway. In this case, you just make a method public Foo getFoo(). But for arbitrary classes, that was never how Dagger was designed.

@cgruber

This comment has been minimized.

Show comment
Hide comment
@cgruber

cgruber Apr 24, 2014

Collaborator

Hmm. Looking at the Jersey example, it seems like it is actually building a lot of reflective API on top of Dagger... but I think the ObjectGraph-compatibility approach might suit there. That said, this is particularly intense reflective analysis on what is supposed to be a compile-time framework... I'm thinking some of it could be potentially replaced with generics - instead of all the reflective lookup just have DaggerInjectedComponentProvider and have your component be T, instead of ObjectGraph. But that's off the top of my head. I'm going to build (or collaborate on) some similar infrastructure around servlet engines and for android internally in the next six to eight weeks, and I think we'll learn a lot about how to best harness Dagger 2.0 in other infrastructure.

Collaborator

cgruber commented Apr 24, 2014

Hmm. Looking at the Jersey example, it seems like it is actually building a lot of reflective API on top of Dagger... but I think the ObjectGraph-compatibility approach might suit there. That said, this is particularly intense reflective analysis on what is supposed to be a compile-time framework... I'm thinking some of it could be potentially replaced with generics - instead of all the reflective lookup just have DaggerInjectedComponentProvider and have your component be T, instead of ObjectGraph. But that's off the top of my head. I'm going to build (or collaborate on) some similar infrastructure around servlet engines and for android internally in the next six to eight weeks, and I think we'll learn a lot about how to best harness Dagger 2.0 in other infrastructure.

@johnlcox

This comment has been minimized.

Show comment
Hide comment
@johnlcox

johnlcox Apr 24, 2014

That definitely makes sense. The dagger-jersey project was a quick attempt at getting dagger integration with Jersey and it works, but does require marking a lot of classes as injects on the module.

johnlcox commented Apr 24, 2014

That definitely makes sense. The dagger-jersey project was a quick attempt at getting dagger integration with Jersey and it works, but does require marking a lot of classes as injects on the module.

@JakeWharton

This comment has been minimized.

Show comment
Hide comment
@JakeWharton

JakeWharton May 9, 2015

Collaborator

This happened.

Collaborator

JakeWharton commented May 9, 2015

This happened.

@JakeWharton JakeWharton closed this May 9, 2015

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