Well, I actually put mine at the bottom of the class, personally. But to ease clarity, I could see putting them close to the constructor. But only if they're factory interfaces. IF you have a concrete factory (as in, you're not using assisted injection but hand-coding factories) then I think they'd clutter the top of a class.

Your style will vary, my point primarily being that you keep the things that change together close together by convention. Makes life easier.

Christian.


On 7 Nov 2012, at 16:10, Alex opn wrote:

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.

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