On Tuesday, May 10, 2011 10:47:51 AM UTC+2, dhoffer wrote:
>
> 1. Hum, perhaps I'm doing more work than I need to...perhaps just out
> of habit of previously using manual factories...but I think I got this
> from the Guice online docs.  Here is what I do:
>
> Class A takes 4 parameters where all are interfaces of course.  I add
> @Inject annotation to the constructor and optionally scope annotation
> to the class.  I then create a module for this class that extends from
> AbstractModule that implements configure.  In this method I create and
> maintain 4 bind() method calls that map the interface to the actual
> class.  I assume the order of these bind statements much match the
> order in the constructor.  Repeat for every IoC class in the
> application.
>

You're doing it wrong. Modules are not factories, they're configuration.

1. the bind() order is not significant
2. using a module per "class requiring injection", you'll probably have 
duplicate bindings (classes Foo and Bar have a dependency on Baz, following 
your "rule", both FooModule and BarModule will 
bind(Baz.class).to(BazImpl.class), this will cause an error) or conflicts 
(FooModule binds Baz to BazImpl whereas BarModule binds Baz to AnotherBaz).
If you want to make very fine-grained modules (really not sure that's a best 
practice), you'd rather have one per "interface some other class depends on" 
(i.e. interface Baz), but then you could in simple cases just as easily use 
an @ImplementedBy annotation.

You have to think at a wider level than "one class", think "module" instead 
(I'm not talking about Guice modules, but application/feature modules).
As an example, we have "api modules" (Maven modules, think of them as JARs 
or Eclipse projects if you prefer) comprised mostly of interfaces (we have 
one for managing entities in a simple datastore, one for indexing and 
searching them, one for validating them, one for dispatching events on a 
bus, etc.) Then we have "implementation modules" where the storage is 
implemented using Morphia/MongoDB, the indexing/searching backed by Solr, 
validation by Hibernate Validator and JSR303, and the event bus by HornetQ. 
In each of these "implementation modules", we have only a single Guice 
module that binds each interface from the "api module" to the concrete 
implementation of the "implementation module" (Indexer to a SolrIndexer 
backed by a SolrServer, EntityManager to a MorphiaEntityManager backed by a 
Morphia Datastore, etc.)
Then we have several applications (a webapp and a bunch or "executables") 
that make use of these modules, each one creates a Guice Injector installing 
the required modules; the code only depends on the interfaces from the "api 
modules" though.

I guess I just don't get your comment 'bind()ings are about *what* to
> inject, not *where* to inject them.'
>
It's not where I use an EntityManager that I decide which one I'll use (i.e. 
it's not in a FooModule along side a Foo class with an "@Inject 
EntityManager em" field, that I bind(EntityManager.class)), it's at the 
application level that I instead decide which modules I'll install, those 
modules providing the bindings (some classes need an EntityManager, and the 
bootstrap code for the app chooses to use the MorphiaStorageModule that 
binds EntityManager to an implementation based on Morphia).

It seems you need some way to
> specify the *where* too.
>
If you need several implementations of a given interface to be injected at 
different places in your app, then you have to annotate those places. For 
instance, we have several Solr indexes –Solr cores–, one used for "suggest 
as you type" and one for "advanced search", because they need different Solr 
configurations. In our app, both are accessed through a Searcher interface. 
We created a "binding annotation" (or you could use @Named if your prefer) 
so that anywhere I need a "searcher for suggest-as-you-type" I declare a 
"@ForIndex(Index.Suggest) Searcher" field or constructor argument, and 
anywhere I need a "searcher for advanced search" I declare a 
"@ForIndex(Index.AdvancedSearch) Searcher" field or constructor argument.
In the SolrSearchModule, we then have two bindings (in the form of @Provides 
methods):
@Provides @ForIndex(Index.Suggest) Searcher provideSuggestSearcher(...other 
dependencies...) { ... }
@Provides @ForIndex(Index.AdvancedSearch) Searcher 
provideAdvancedSearchSearcher(...other dependencies...) { ... }

See, it's about *what* you depend on/inject, not about *where* you inject 
it.

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