Graph visualization doesn't display Lazy bindings well.
The following module:
@Module(library = true)
class LazyModule {
@Provides Foo provideFoo() {
return new Foo();
}
@Provides Bar provideBar(Lazy<Foo> foo) {
return new Bar();
}
@Provides Baz provideBaz(Foo foo) {
return new Baz();
}
}
produces the .dot file:
digraph G1 {
concentrate = true;
n2 [label="Bar"];
n3 [label="Lazy<Foo>"];
n2 -> n3;
n4 [label="Baz"];
n5 [label="Foo"];
n4 -> n5;
}
which doesn't show any relationship between Foo and Lazy<Foo>. I'd expect either
(a) there should be an arrow from Foo -> Lazy<Foo>, indicating that to produce a Foo, you need a Lazy<Foo>; or
(b) Foo and Lazy<Foo> should be the same node.
Hmm. Other way around - Lazy<Foo> requires Foo. Or rather, technically, it requires Provider<Foo>. But from a sort of structural dependency, Lazy<Foo> is a wrapper of foo, and providers are all implicit, so I"m not sure how to best represent that in the digraph.
It might be reasonable that if Lazy<Foo> and Foo both occur in the graph, we can add Provider<Foo> and have them both point at that. But I'm not sure. Is it not clear what the graph intention is?
The simplest way I can see is to simply have Lazy<Foo> point at Foo, because by the point where you get() on Lazy<T> it will either HAVE created or WILL create Foo before get() returns. That suggests to me that Lazy<Foo> -> Foo.
Another option woudl be that Lazy<Foo> isn't a node, but we special case it, and it becomes a specialized edge in the digraph - where we link Baz -----> Foo and Bar ---lazy--> Foo (or something along those lines)
I see what you mean - I think you could make an argument for either direction for the arrow; I was thinking of the lazy.get() call as fake method that looks like
Foo provideTheRealFoo(Lazy<Foo> lazy) { ... }
(I sorta view all providers, e.g. from T to U, as maps from Lazy<T> to Lazy<U>, which leads me to this viewpoint.)
But you're right, it could be viewed the other way, and they both naturally depend on a Provider.
Given that there are multiple ways of thinking about this, I like the idea of having a specialized "lazy" edge.
Oh no.
@Provide Foo provideFoo(Lazy<Foo> lazy) { }
That should break, hard. That is a circular dependency, specifically, and should fail at compile time. If it doesn't, we need to file a bug. I think there is no plausible way to think of it as Foo -> Lazy<Foo> given what lazy is... it's simply a lazy creator. You're depending on Foo... but only actually demanding it when you use it.
Anyway, I'll play with digraphs manually and see if I can come up with something visually useful.
Heh, no, I didn't mean as a @Provides method, just a way to think about dependencies.
You can think about Lazy<T> as a monad, with provider methods looking like T -> Lazy<U>; you can ask gak about all the horrible ways I've been trying to use Dagger :)
Thanks for taking a look!
So how about something like this:
digraph G1 {
concentrate = false;
n2 [label="A"];
n3 [label="B"];
n4 [label="C"];
n5 [label="D"];
n6 [label="E"];
n7 [label="F"];
n8 [label="G"];
n2 -> n3 [fontsize="10", style="dashed", fontcolor="goldenrod", color="goldenrod" label="<lazy>"];
n4 -> n3 [fontsize="10", style="dashed", fontcolor="goldenrod", color="goldenrod" label="<lazy>"];
n5 -> n2 [fontsize="10", style="dotted", fontcolor="blueviolet", color="blueviolet" label="<provider>"];
n4 -> n5;
n4 -> n2 [fontsize="10", style="dotted", fontcolor="blueviolet", color="blueviolet" label="<provider>"];
n6 -> n3 [fontsize="10", style="dashed", fontcolor="goldenrod", color="goldenrod" label="<lazy>"];
n8 -> n7;
n8 -> n2 [fontsize="10", style="dotted", fontcolor="blueviolet", color="blueviolet" label="<provider>"];
n7 -> n3 [fontsize="10", style="dashed", fontcolor="goldenrod", color="goldenrod" label="<lazy>"];
n4 -> n6;
}
Note - concentrate = false results in slightly better lines in larger graphs. Otherwise, they end up merging where they shouldn't, like a normal dependency laying over a lazy/provided dependency, so it's obscured.
I separated provider and lazy by both colour and line style, as well as adding a little label.
I like it!