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.

Reply via email to