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.

Reply via email to