Well, if you notice in my example, I didn't remove the annotations from
the injected class.  I simple changed the annotation to indicate the
role that was played by the class (federal vs commercial) rather than
specifying the implementation.  Then the module maps from role ->
implementation.

So, @Named("xxx") annotations don't get in the way of the rule, but what
"xxx" actually is might get in the way.

As a quick example to help aid in understanding.  Say that we want to
move commercial sales to the high pricing strategy.  All I would need to
do is modify one line in the module (or maybe more if there are multiple
classes involved in "high pricing strategy"):

        bind(
IPricingStrategyA.class).annotatedWith(Names.named("commercial")).to(LowPricingStrategyA.class);
becomes
        bind(
IPricingStrategyA.class).annotatedWith(Names.named("commercial")).to(HighPricingStrategyA.class);



-Jared

On 09/14/2012 11:57 AM, David Hoffer wrote:
> I think that makes sense.  I like the guiding rule as you put
> it..."keep decisions about which implementation to use at the Module
> level, not at the injected class level."  
>
> Just not sure I can in practice I know how to use Guice fully
> following that rule...as without class level annotations I don't know
> how you could ever use more than one concrete instance of an interface
> in any one application.  (That was my original use of annotations so I
> could have lots of IProcessor instances, for instance.  Now I have
> groups of instances that must be switched out as a group.)
>
> So it seems that the @Named("xxx") annotation gets in the way of that
> rule.  Even in your case what determines what will be injected is
> the commercial/federal annotations.  
>
> Regarding custom annotations...does that solve this?  I have not used
> them yet.  Also I'm not familiar with the robot legs pattern...I'll
> have to investigate that.
>
> -Dave
>
>
>
> On Fri, Sep 14, 2012 at 10:02 AM, Jared Bunting
> <[email protected] <mailto:[email protected]>> wrote:
>
>     I'm also not an expert, but one of my guiding rules is, like
>     Stuart said, to keep decisions about which implementation to use
>     at the Module level, not at the injected class level.  So in this
>     case, I would probably do something like this:
>
>     @Inject
>     public MyClass(IPricingStrategyA pricingStrategyA,
>                                             ICalculator calculator) {
>             this.pricingStrategyA = pricingStrategyA ;
>             this.calculator = calculator;
>        }
>
>     then in the module:
>     protected void configure() {
>             bind( IPricingStrategyA.class).to(LowPricingStrategyA.class);
>             bind( ICalculator.class).to(APRCalculator.class);
>     ...
>
>     If I have some clients that need the low strategy and some that
>     need the high, I might do something like this:
>
>     @Inject
>     public CommercialSales(@Named("commercial") IPricingStrategyA
>     pricingStrategyA,
>                                             ICalculator calculator) {
>             this.pricingStrategyA = pricingStrategyA ;
>             this.calculator = calculator;
>        }
>
>     @Inject
>     public FederalSales(@Named("federal") IPricingStrategyA
>     pricingStrategyA,
>                                             ICalculator calculator) {
>             this.pricingStrategyA = pricingStrategyA ;
>             this.calculator = calculator;
>        }
>
>     then in the module:
>     protected void configure() {
>             bind(
>     
> IPricingStrategyA.class).annotatedWith(Names.named("commercial")).to(LowPricingStrategyA.class);
>            
>     bind( 
> IPricingStrategyA.class).annotatedWith(Names.named("federal")).to(HighPricingStrategyA.class);
>             bind( ICalculator.class).to(APRCalculator.class);
>     ...
>
>     (although in reality I would probably use a custom annotation,
>     rather than @Named, or at the very least, constants for the
>     strings...but you get the point)
>
>     In both of these patterns, you can see that the decision about
>     what implementation to use is all contained in the module, thus
>     keeping it in the same location.
>
>     This could also be accomplished with the robot legs pattern, and
>     there's probably some good arguments for doing it that way.
>
>     -Jared
>
>
>     On 09/14/2012 09:40 AM, David Hoffer wrote:
>>     I'm quite new to Guice so perhaps I'm doing things wrong but I
>>     use this pattern a lot:
>>
>>     @Inject
>>     public MyClass(@Named("LowPricingStrategyA") IPricingStrategyA
>>     pricingStrategyA,
>>                                             ICalculator calculator) {
>>             this.pricingStrategyA = pricingStrategyA ;
>>             this.calculator = calculator;
>>        }
>>
>>     then in the module:
>>     protected void configure() {
>>             bind(
>>     
>> IPricingStrategyA.class).annotatedWith(Names.named("LowPricingStrategyA")).to(LowPricingStrategyA.class);
>>            
>>     bind( 
>> IPricingStrategyA.class).annotatedWith(Names.named("HighPricingStrategyA")).to(HighPricingStrategyA.class);
>>             bind( ICalculator.class).to(APRCalculator.class);
>>     ...
>>
>>     Note that for IPricingStrategyA I have two possible
>>     bindings LowPricingStrategyA & HighPricingStrategyA, the module
>>     doesn't know/specify which will be used, that is determined by
>>     the @Named("LowPricingStrategyA") annotation in MyClass.  Now
>>     imagine the 'pricing strategy group' has 5 pairs of classes A, B,
>>     C, D & E...a High and a Low for each.
>>
>>     What I'm wondering is how to get the control of
>>     this centralized instead of in 5 different classes.
>>
>>     -Dave
>>
>>
>>     On Fri, Sep 14, 2012 at 8:25 AM, Stuart McCulloch
>>     <[email protected] <mailto:[email protected]>> wrote:
>>
>>         On 14 Sep 2012, at 15:16, Christian Gruber wrote:
>>
>>>         I feel like I need a bit more clarity of what you're trying
>>>         to do before commenting properly.  There are a few ways to
>>>         think about what you describe here, but without a concrete
>>>         example in code, it's hard to reason about what might be the
>>>         best solution.  Can you create a simplified example in code
>>>         and paste it here, so we can better help?
>>
>>         IMHO the real control should be in the module (ie. what gets
>>         bound to which key) and not in the concrete class - that
>>         should just declare what it needs (ie. its injected
>>         dependencies). If you have duplicate graphs of objects which
>>         only differ in price strategy then that sounds like the
>>         "robot-legs"
>>         problem: 
>> http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec
>>>
>>>         On Friday, September 14, 2012 at 10:00 AM, dhoffer wrote:
>>>
>>>>         I've got a couple of projects that use Guice that used to
>>>>         use manual DI.  So currently I have one module class with
>>>>         all the bindings.  I often use
>>>>         the annotatedWith(Names.named("MyClass")) approach so I can
>>>>         specify which implementation should be injected.
>>>>
>>>>         But this brings me to the problem.  What if I have the case
>>>>         where several injections much change as a set?  E.g. lets
>>>>         say I'm implementing a couple of pricing strategies where
>>>>         each strategy creates 5 concrete classes...it's critical
>>>>         that all 5 of those are from the same pricing
>>>>         strategy...not 4 from one and 1 from another.  In the old
>>>>         days, pre-Guice, I could just go to my 'application
>>>>         construction method' find the 5 relevant classes put them
>>>>         right next to each other in code...add comments/etc.  E.g.
>>>>         everything was all in one place so it was manageable to
>>>>         find what types are being created and switch things out.
>>>>
>>>>         Now post-Guice I have no centralized control of
>>>>         anything...as the module file doesn't say what is created
>>>>         it just says if 'you' find X use Y.  The real control is in
>>>>         each java class file's @Inject constructor where I add the
>>>>          @Named("MyClass") annotation.
>>>>
>>>>         How can I achieve a more centralized control over the exact
>>>>         classes instantiated?
>>>>
>>>>
>>>>
>>>>         -- 
>>>>         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/-/PHofIXp_71AJ.
>>>>         To post to this group, send email to
>>>>         [email protected]
>>>>         <mailto:[email protected]>.
>>>>         To unsubscribe from this group, send email to
>>>>         [email protected]
>>>>         <mailto:[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]
>>>         <mailto:[email protected]>.
>>>         To unsubscribe from this group, send email to
>>>         [email protected]
>>>         <mailto:[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]
>>         <mailto:[email protected]>.
>>         To unsubscribe from this group, send email to
>>         [email protected]
>>         <mailto:google-guice%[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] <mailto:[email protected]>.
>>     To unsubscribe from this group, send email to
>>     [email protected]
>>     <mailto:[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]
>     <mailto:[email protected]>.
>     To unsubscribe from this group, send email to
>     [email protected]
>     <mailto:google-guice%[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.

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