I think speaking in alphabets may drive everyone bonkers. :) In concrete terms, the application is meant to simulate delivering educational content based on a student's response. Better responses mean more difficult content; worse responses mean easier content. "Class A" is the entry point to the simulator, whereas "Class D" is what simulates the actual correct/incorrect responses. A user may want to simulate a 50% correct response rate during one run, and 80% on a subsequent run (without getting a new instance). That means "D" has to change based on what the user wants. The rest of the simulator (A, B, C) doesn't care about how those responses get generated, but since class A is the public face of the API, that's how a user would indicate what percentage the next run should perform at. Thus, my problem.
I thought I had written a fairly OO design, but getting that percentage value from A down to D proved to be my undoing. And you're right, this really isn't a Guice problem, it's a DI problem. So I need to rethink. Thanks again! Ryan On Dec 10, 11:57 am, bklough <[email protected]> wrote: > Right on. Was trying to be quick, not ornery. :-D > > This is where my brain bulks: "I want class C (and indirectly, A and > B) to operate differently on what D is, based on what the customer > gave me." This is counter-intuitive to me, from an OO standpoint. A > Car doesn't operate differently because it was given a SquareTire. It > drives like crap, but car.drive() does exactly what it did before, > albeit with poor performance results. If it doesn't, refactor. ;-) > > Hate to say it, but your issue isn't related to Guice at all. > > It sounds like you need an Adapter for D either way. Adapters > specific to the type of D get created (however) when D enters your > domain. The Adapter delegates to D's methods, or uses D however it > wants to provide common behavior the rest of the Alphabet (A's, B's, > etc :-) needs. The point is once D enters your domain, regardless of > how, wrap it with whatever you need to in order to make it behave as > you expect. > > If you can do whatever it is you're looking to do by manual DI, Guice > can help you. If not . . . > > Good luck and a Hearty Happy Friday!!! > > On Dec 10, 9:10 am, Ryan <[email protected]> wrote: > > > > > > > > > Hi Brian, thanks for taking a shot at it. I'm not offended at all. > > You're right that this is a potential code smell, and I've been > > rethinking my design to see if I can improve it. My question about > > your solution revolves around these two lines: > > > public DProvider(Whatever dNeeds) { .. } > > ... > > D newD = createDBasedOnWhateverRuntimeCriteria(); > > > In my program, D is essentially a domain object created external to > > the system (say, through customer input). I want class C (and > > indirectly, A and B) to operate differently on what D is, based on > > what the customer gave me. My API to the outside world exposes only > > class A, so that's the only way the new D gets into the system. > > > Using a Provider is exactly what I would want (and my first choice), > > if I can can change what D returns each time get() is invoked. The > > problem is, how do I get that information to DProvider (from A) at > > runtime? I could add a static method to A that DProvider could > > invoke, but that's nasty non-OO stuff. Fred's solution works because > > the scope.seed() method allows me to change what "D.class" was bound > > to at runtime. The Provider approach is much preferred, but I don't > > have control over the Provider's construction. > > > As I've gone the rounds with this and tried everyone's solutions, I'm > > thinking at this point my real problem is that A knows about D, and it > > probably shouldn't. So maybe I need to go back to the drawing board > > and avoid this conundrum altogether. > > > Thanks again for trying, > > Ryan > > > On Dec 9, 8:40 pm, Brian Lough <[email protected]> wrote: > > > > lol. Freehand strikes. Naturally the .get() method needs to have code > > > prior to the != null if an external force/trigger can instantiate another > > > D > > > instance. I'm usually dealing with listener threads that replace the > > > contents of currentD out from under me whenever. Cheers! > > > > On Thu, Dec 9, 2010 at 7:36 PM, Brian Lough <[email protected]> wrote: > > > > No offense, IMHO, what you're trying to do just smells bad. There's a > > > > unnecessary coupling of these classes causing these gyrations that I > > > > can't > > > > put my finger on. I'm swapping one runtime instance for another easily > > > > way > > > > down in dependency chains just by using sub-classes of Provider and > > > > .get(). > > > > D is the wonky one, so maybe this will lead somewhere....(typing > > > > freehand > > > > so..) > > > > > public class DProvider implements Provider<D> { > > > > > private AtomicReference<D> currentD = new AtomicReference<D>(null); > > > > > @Inject > > > > public DProvider(Whatever dNeeds) { .. } > > > > public D get() { > > > > if (currentD.get() != null) { > > > > return currentD.get(); > > > > } > > > > > D oldD = currentD.get(); > > > > oldD.releaseResources(); > > > > D newD = createDBasedOnWhateverRuntimeCriteria(); > > > > currendD.set(newD); > > > > return newD; > > > > } > > > > > Anyone requiring an instance of D, regardless of position in the > > > > dependency > > > > chain, gets DProvider injected. As long as they get their D instance > > > > via > > > > injectedDProvider.get() anytime they access a method of D, they're > > > > certain > > > > to get whatever runtime instance you've swapped in/out. > > > > > Hope this helps. Took a shot. :-D- Hide quoted text - > > > - Show quoted text - -- 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.
