So here's a hello-worldish example, entirely off the top of my head:
----
Foo <- consumable
Bar <- consumable (product of a transformation)
FooProcessor <- collaborator
Logger <- collaborator
LookupService <- collaborator
@Named("lookup.url") String processor <- configuration
----
And the classes would look sort of like this (assuming you used AssistedInject
to create your Foo objects.
----
interface FooProcessor {
Bar transformFoo(Foo foo);
}
interface Foo {
Integer getBaz();
}
interface Bar {
Integer getTransformedBaz();
}
/** Factory interface used by AssistedInject to auto-wire a factory */
interface FooFactory {
Foo create(Integer baz);
}
class FooImpl {
private final Integer baz;
private final Logger logger;
@Inject public FooImpl( @AssistedInject Integer baz, Logger logger) {
this.baz = baz; // "Injected" through the factory create method.
this.logger = logger; // Injected from Guice
}
}
class FooProcessorImpl {
// fields
@Inject FooProcessorImpl(Logger logger, LookupService lookupService) {
// field assignments
}
public Bar transformFoo(Foo foo) {
Precondition.notNull("foo", foo);
return new BarImpl(lookupService.lookup(foo.getBaz()) * SOME_CONSTANT);
}
}
class LookupService {
// fields
@Inject public LookupService(@Named("lookup.url") String lookupUrl) {
// field assignments
}
public Integer lookup(Integer int) {
// lookup integer from remote service via the lookup url.
}
}
----
So, Foo and Bar are passed around on the call stack, and consumed and created
by the collaborators (one collaborator of which is an auto-generated FooFactory
implementation created by the AssistedInject extension system). The
collaborators delegate different responsibilities to each other, and the
configuration contextualizes collaborators.
LookupService injects configuration - a named value, presumably wired into
Guice via Names.bindProperties(Properties p) or jCommander+gCommander or
something similar.
This is just how I think of things - a useful breakdown. But, generally, I
find that when I segregate responsibilities like this, I have far more
composable code, and it becomes quickly clear whether something shoudl be
injected or managed by factories or other services.
cheers,
Christian.
On May 12, 2012, at 12:29 PM, Bubba 42 wrote:
> Many thanks guys for the input.
>
> Is there an example (Hello World level of complexity) which
> illustrates the collaborators, configuration, and consumables
> stereotypes?
>
> I'd be happy to put one together if it'd benefit folks -- but would
> need help.
>
> Thanks.
>
> On May 11, 5:23 pm, Christian Edward Gruber <[email protected]>
> wrote:
>> Please don't inject value classes, generally speaking.
>>
>> I tend to think of dependencies in three kinds - collaborators,
>> configuration, and consumables. Consumables are value classes that are
>> consumed by and transformed by your collaborators, in the context of your
>> configuration. Generally consumables are passed on the function call stack
>> through parameters, whereas collaborators should be injected (for
>> testability, decoupling, and all the various other reasons). Configuration
>> may be passed through either, but pick a strategy and go with it.
>>
>> That's my basic position. AssistedInject is wonderful, but slightly missed
>> named - think of it as "Assisted Auto-Wiring of Factories." It's a good
>> thing.
>>
>> The above isn't to say you "can't" do it, and several frameworks built on
>> top of guice or other DI systems do just that, but it's tricky and very
>> likely to get subtle implicit behaviour that's hard for other developers to
>> reason about. Common cases are for things like "User" objects to be
>> injected into session-scoped objects. In that case, a user is not
>> consumable data, but "configuration" - the context in which other things are
>> mutated and created by the collaborators. But it's important that you get
>> your mind clear about what's what in your system so you can apply a
>> consistent strategy to it all.
>>
>> Christian
>>
>> On May 11, 2012, at 7:05 AM, jordi wrote:
>>
>>
>>
>>
>>
>>
>>
>>> In case you really need to inject value classes, Guice does that for you
>>> for free. If you @Inject a Person (non-scoped), every time will give a new
>>> Person.
>>
>>> But I can't figure out why a simple value class should be managed by Guice.
>>> In this case I'm sure that's easier and clearer to just use a regular,
>>> old-fashioned new.
>>
>>> If what you're looking for is to inject a Service in conjunction with some
>>> value class, take a look at Assisted Inject [1]
>>
>>> hth,
>>> jordi
>>
>>> [1]http://code.google.com/p/google-guice/wiki/AssistedInject
>>
>>> On Thu, May 10, 2012 at 10:45 PM, Bubba 42 <[email protected]> wrote:
>>> Hi,
>>
>>> I've been unable to find a suitable answer to this question.
>>
>>> If I understand this correctly: Dependency Injection can be used to
>>> instantiate service objects -- object that essentially abstract away
>>> some computational service ... for example (an instance of this class
>>> would essentially be stateless, save for resources that it might be
>>> plugged into such as SimpleMath.properties, and I would expect that
>>> there would be small number of instances of this class per application
>>> instance say under 5):
>>
>>> class SimpleMath {
>>
>>> public int addTwoNumbers (int n1, int n2) {
>>> return n1 + n2;
>>> }
>>
>>> public int multiplyTwoNumbers (int n1, int n2) {
>>> return n1 * n2;
>>> }
>>
>>> }
>>
>>> Now can DI be used to instantiate value objects (for the lack of a
>>> better word). By a value object I mean an object that has state and
>>> the methods are impacted by that state, for example (as opposed to the
>>> previous class I would expect there to be hundreds or thousands of
>>> instances of this class):
>>
>>> class Person {
>>
>>> int age;
>>> int weight;
>>> String fname;
>>> String lname;
>>> // and so on
>>
>>> public String hail() {
>>> return "Hello to you to, I am " + fname + " " + lname;
>>> }
>>
>>> public String howOldAreYou() {
>>> return "I don't really like talking about my age but I'm " + age +
>>> " years young";
>>> }
>>
>>> // and so on
>>
>>> }
>>
>>> Thanks.
>>
>>> --
>>> 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
>>> athttp://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
>>> athttp://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.