We are preparing to begin using Guice in our insurance data conversion platform and I have encountered an interesting scenario that does not seem to be directly addressed in the Guice docs or any postings I have found.
Our platform uses the Encapsulated Context (EC) pattern in several important areas. For example, imagine we are processing a set of 10 policies. Whenever we begin processing a new policy, we wish to construct a PolicyContext
object and initialize properties such as policy number, state, and company. This PolicyContext
is a dependency for many classes that are involved in the conversion process.
Note that PolicyContext
(and other *Context
objects within our app) is a value object that is tightly focused in a specific domain area (representing basic, ubiquitously needed policy information). I would be interested to know whether the pattern gurus among you still consider this to be an anti-pattern (as discussed by Misko Hevery in http://misko.hevery.com/2008/07/18/breaking-the-law-of-demeter-is-like-looking-for-a-needle-in-the-haystack/ ) even though these are purely value objects and certainly don’t represent the “kitchen sink.”
Currently, we are managing PolicyContext
in the worst possible way: we have a static global variable, policyContext
, and policyContext.initialize(String company, String state, String policyNum)
is called whenever we start processing a new policy.
My goal is for Guice to manage these context objects in an architecturally optimal manner so that, conceptually, whenever we begin processing a new policy:
- Guice discards the old
PolicyContext
. - Guice construct a new, immutable
PolicyContext
(no smelly initialize method) usingcompany/state/policyNum
params coming from a database. - Guice injects the already constructed
PolicyContext
into all the classes that require it.
Here is my tentative approach:
- Create a custom scope—something akin to the Guice batch scope sample at http://code.google.com/p/google-guice/wiki/CustomScopes--where the boundaries of the batch are externally determined. With this scope, where we begin processing a new policy, we can 1) end the previous “batch” and begin a new one. Q: Any reason I can’t use the Guice batch scope sample exactly as listed at the aforementioned URL?
Since
PolicyContext
has no dependencies, we would use AssistedInject for all constructor parameters (which seems a bit odd). Assuming we take that approach and generate aPolicyContextFactory
, it follows that where we start processing a new policy we would have code such as:… scope.exit(); scope.enter(); @Inject private PolicyContextFactory policyContextFactory; policyContextFactory.create(company, state, policyNum); // the parameters come from a database record. // Note that we don’t need to actually store the created instance; it will be injected elsewhere into various class constructors. …
Does this seem optimal? I know there may be simpler approaches (e.g. creating a new, PolicyContext
specific injector, whenever we process a new policy, which effectively creates a new PolicyContext
). However, this is a core aspect of the architecture, so I really don’t want to compromise.
Another option, I know, would be to abstain from using DI in this scenario and just use a static PolicyContextManager
class with separate create
and get
methods, where the former method is the factory that discards the current PolicyContext
and creates/stores a new one, while the latter method simply returns the “active” PolicyContext
). But my code will just end up doing manual DI because I’ll be writing lots of code like methodThatNeedsPolicyContext(PolicyContextManager.get(), …)
. Since we intend to start using Guice anyway, this approach doesn’t seem to be optimal.
BTW, for those attempting to cultivate a deeper understanding of DI, I highly recommend “Dependency Injection” by Dhanji Prasanna. This book, which focuses on Guice and Spring, was absolutely indispensable, as it goes so much deeper than anything else I have encountered.
Thanks for your help!