factories inside the classes itself near constructor! clever :)!
On Wed, Nov 7, 2012 at 10:06 PM, Christian Gruber <[email protected]>wrote: > Well, for starters, you've now created a dependency on the injector, which > is valid but I find makes code substantially more confusing in the > long-run. It also means that we could never EVER analyze your code > statically to determine if your wiring was correct (that is, all > dependencies are bound) because you've internalized the logic of the > dependency fulfillment into a code-path instead of a declaration. > > Also, you can't see the dependencies from without - say, from method > signatures or otherwise, so it's harder to reason things through. You can > always look at the code, but the constructor signature is now meaningless - > it doesn't semantically include the dependencies - it includes a piece of > infrastructure. > > You're right - there's a bit more work to do from the outside with > assisted injection in terms of maintaining dependency lists. But the > clarity in the code I find to be valuable. > > In practice, I don't find it that difficult to keep these things clear. > > public class Foo { > > //private variables > > // factory interface near constructor. > public interface Factory { > Foo create(Consumable someValue); > } > > Foo(Dependency dep, OtherDependency dep2, @Assisted Consumable > someValue) { > ... > } > > } > > This way, if I need to change that list, I change the two nearly beside > each other - easy to see. > > The other problem is that with assisted injection, you now can separate > different KINDS of injected things - collaborating services, configuration > values, consumables, and pass them around differently. Consumables (value > types, local differences) have quite different life cycles from services, > etc. So if you do what you're suggesting, you absolutely start to need to > play scope games. Because if you have values that aren't just created once > for each request being part of the object's lifecycle, you now have to > create narrower and narrower @Scopes in order to support these shorter > lifetimes. > > Sometimes things really just need to be on the call-stack. And having a > factory break as part of a factory call is a far clearer error (and > stack-trace) than a deep failure of injection. They might be systemically > equivalent, but their meaning to the coder is different, and finding the > errors later are quite different. > > Generally, anything you might want to use Guice as a factory for, I tend > to recommend using assisted injection, because it creates separate, > traceable factories for each type. Yes, it's "more work" in one sense - > but I think it's a better organization of code. > > Injecting the injector is something that is possible, and sometimes > necessary to support legacy code. But I think the problems outweigh the > ease you think it'll buy you - especially for down-stream maintainers. > > Christian > > > On 7 Nov 2012, at 15:50, Gili wrote: > > Hi, >> >> I've been using Guice over the past couple of years and it worked quite >> well for me. However, every once in a while I run across a recurring >> problem and I'd like to get your feedback on it. The problem arises when I >> run across a constructor that requires a mix of Guice-injected and >> user-supplied values. For example: >> >> public MyService(UriInfo uriInfo, String userName) >> >> This is precisely the use-case AssistedInject is meant to address but the >> more I run into this code, the more I am leaning towards using the Service >> Locator pattern [1] instead. AssistedInject requires me to construct and >> bind one factory per class. This means that every time I add/remove a >> class, I need to add/remove a binding. It means every time I add/remove >> user-supplied parameters, I need to also add/remove parameters from the >> factory. Initially it didn't seem like a big deal but time I've questioned >> the cost/benefit of this approach. The resulting code is harder to read >> and >> maintain, and for what? Nowadays I replace: >> >> @Inject >> public MyService(First first, Second second, Third third, @Assisted >> String userName) >> >> with >> >> @Inject >> public MyService(Injector injector, String userName) >> { >> this.first = injector.getInstance(First.**class); >> this.second = injector.getInstance(Second.**class); >> this.third = injector.getInstance(Third.**class); >> } >> >> and simply inject classes on-demand using injector. Essentially I'm using >> Guice as a Service Locator. The way I see it: >> >> - The classes/constructors are a lot easier to maintain. >> - No need to enumerate the injected parameters in the Javadoc. I've >> >> always found it annoying to have the Javadoc cluttered with parameters the >> user doesn't really care about (besides the fact it was a lot of work to >> keep such documentation up-to-date). >> - This still implements the inversion of control pattern so the code is >> easily testable. >> - The dependencies might not be listed as constructor parameters, but >> >> they still visible near the top of the constructor. >> - To clarify, I only advocate this approach when mixing injected and >> >> user-supplied parameters. I still use normal constructor injection when >> all >> parameters come from Guice. >> >> So really, what's the harm? I'd love to get your feedback on this. >> >> Thanks, >> Gili >> >> [1] http://martinfowler.com/**articles/injection.html#** >> UsingAServiceLocator<http://martinfowler.com/articles/injection.html#UsingAServiceLocator> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "google-guice" group. >> To view this discussion on the web visit https://groups.google.com/d/** >> msg/google-guice/-/HSTXZ7On-**acJ<https://groups.google.com/d/msg/google-guice/-/HSTXZ7On-acJ> >> . >> To post to this group, send email to [email protected]. >> To unsubscribe from this group, send email to google-guice+unsubscribe@** >> googlegroups.com <google-guice%[email protected]>. >> For more options, visit this group at http://groups.google.com/** >> group/google-guice?hl=en<http://groups.google.com/group/google-guice?hl=en> >> . >> > > -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to google-guice+unsubscribe@** > googlegroups.com <google-guice%[email protected]>. > For more options, visit this group at http://groups.google.com/** > group/google-guice?hl=en<http://groups.google.com/group/google-guice?hl=en> > . > > -- You received this message because you are subscribed to the Google Groups "google-guice" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.
