Some things I don't like about Guice.

1,904 views
Skip to first unread message

dhoffer

unread,
May 10, 2011, 12:38:22 AM5/10/11
to google-guice
Okay I'm new to Guice so maybe I'm missing something but since I
converted one app to use Guice I've found some things that I just
don't like, I'm wondering if folks have found solutions or have
suggestions.

1. No IDE help. I use IDEA and as of yet it is not Guice aware so all
my refactoring/code support is broke. And I have to build the modules
by hand which is just as hard as making the factory manually before I
used Guice. So to me Guice just moves the problem around. At least
when I made manual factories the IDE could keep changes in sync.

2. Loss of compile time checking. Just by running the compiler I
can't tell if my code is complete, by that I mean have all the right
modules/parameters, I don't find out something is wrong until
runtime. Prior to this, using manual factories, this was a given.
Perhaps I need to add a unit test that forces Guice to create an
instance of the class so it least I could know during the test phase
that the module/factory is correct?

3. Can't keep track of all the modules. As best I can tell nothing in
the module code even says what class it's a factory for. There is too
much annotation magic going on, apparently @Inject is enough for Guice
to 'know' that someplace in vast numbers of Guice modules there should
be one that has the right mix of input parameters?

What am I doing wrong? I feel like this is a couple steps in the
wrong direction.

Josh Kamau

unread,
May 10, 2011, 12:42:32 AM5/10/11
to google...@googlegroups.com
Did you mean you found some things that you just like about guice?

Regards.
Josh.


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.


Mingfai

unread,
May 10, 2011, 2:47:37 AM5/10/11
to google...@googlegroups.com
hi,


1. No IDE help.  I use IDEA and as of yet it is not Guice aware so all
my refactoring/code support is broke.  And I have to build the modules
by hand which is just as hard as making the factory manually before I
used Guice.  So to me Guice just moves the problem around.  At least
when I made manual factories the IDE could keep changes in sync.

perhaps you could elaborate on how your refactoring is broken by Guice.

If you inject by type (and optionally custom annotation), the refactoring function of any IDE could change anything that Guice needs to know. Say you have an "@Inject MyInterface myInterface;", when you rename the MyInterface to MyInterface2, the refactoring won't break Guice's configuration.

There are many things IDE won't do it for you. If you heavily use @Named, your IDE can't refactor the name for you as it is only a String. One simple solution is to use a constant, another option is to use custom annotation. Take an extreme example, if you inject everything as Object like "@Inject @Named("XXX") Object anything;", you could create a mess with Guice. But normally, you use a proper type so your IDE can recognize, and annotation is optional. Another thing IDE won't refactor for you is when you inject an interface, your IDE won't know the concrete implementation. To me, it is expected and obviously not a problem, you could use "Find Usages" in IDEA to locate to relevant module easily.

For other frameworks like Spring that put the configuration in XML, you do need IDE support. For Guice, it's all Java and it doesn't really need IDE support. What IDE help you expect?

 

2. Loss of compile time checking.  Just by running the compiler I
can't tell if my code is complete, by that I mean have all the right
modules/parameters, I don't find out something is wrong until
runtime.  Prior to this, using manual factories, this was a given.
Perhaps I need to add a unit test that forces Guice to create an
instance of the class so it least I could know during the test phase
that the module/factory is correct?

yes, you should do unit testing anyway. For me, when i write a new module, i usually start with write a new test case to test the module. But, IMHO, moving to Guice doesn't really reduce your compile time checking. For your custom factories, if you code them incorrectly, you won't know the problem until runtime as well.

 

3. Can't keep track of all the modules.  As best I can tell nothing in
the module code even says what class it's a factory for.  There is too
much annotation magic going on, apparently @Inject is enough for Guice
to 'know' that someplace in vast numbers of Guice modules there should
be one that has the right mix of input parameters?

What am I doing wrong?  I feel like this is a couple steps in the
wrong direction.

You won't easily know what class a module is providing unless you design your module in a consistent way and/or with documentation. there are many place you could configure binding, e.g. in the configure() method, bind a provider class (class XXX implements Provider<YYY>), use @Provides in the module class, from a child/binder module (such as MapBinder) , using custom injection etc. if you want to know where is a the provider of a particular interface, you could just use the search function of your IDE. (e.g. Find Usages for IDEA)

For me, i like to use (up to) one module per package for my own classes, and a Guice module will provide only class in the same package or sub-packages. when i use a third-party library, I usually create a module dedicate for providing injection for classes from that library. This gives me a good idea where those injections come from, and allow me to unit test them independently.

Guice mainly inject by type and annotation. Say if you have a class Apple with default constructor, the injection "@Inject Apple apple;" will work without any configuration. Say if you want to inject an interface Fruit (where Apple implements Fruit), you need to configure a binding in some way, e.g. in a module with " binder.bind(Fruit.class).to(Apple.class)" or use Just-In-Time binding annotation. For both cases, @Inject is enough because Guice could locate the binding by type. Say if you have multiple Fruit that you want to inject in different place, you will need to use annotation to tell Guice which is which. e.g.
   @Inject @Named("apple") Fruit apple; // configure by binder.bind(Fruit.class).annotatedWith(Names.named("apple")).to(Apple.class)

if you are not sure if you are using Guice properly, maybe you could just post your scenario and ask for other ppl's comment. We can't tell whether your are doing wrong without a concrete case.

regards,
mingfai

David Hoffer

unread,
May 10, 2011, 3:25:08 AM5/10/11
to google...@googlegroups.com
Thanks for the reply...

Regarding 1 at a minimum I need the code/refactoring support one would
get if using manual factories. E.g. If I add a constructor parameter
or change parameter order I need it to keep the module/factory in
sync. In IDEA reordering would change it everywhere, adding something
new would have a default value. So it should at least add another
bind() to the module where I have to fill out the types (and fail to
compile until I do). As it is now I have to manually keep both in
sync. My IDE has become Notepad.

As a bonus the IDE should create the module as else the module really
doesn't save any coding. But I understand this is not a Guice problem
it's a desired IDE feature.

1b. Another example, with Guice I can't even ask the IDE to find uses
of a constructor so I can find where it's used/created because that
usage is hidden behind the magic of annotations. Again my IDE has
become Notepad.

2. In the module for a class (which is its factory) I can have
completely wrong bind statements and the compiler doesn't care. It's
not until runtime that errors are seen. Unit tests generally use
mocks (that's why its IoC) so that won't catch the error either. I
can add another test...really an integration test that causes Guice to
create a live instance...that should catch any problems...but I'm
concerned about that working in the general case because sometimes
that will require lots of application code to fire up...not what is
desired in a unit test.

I guess my point here is that with manual factories those didn't need
to be unit tested because with the compiler's help those are
binary...you either have one or you don't...nothing really to test.
With Guice lots can go wrong in the factory (Module). And because I
have no IDE help to maintain the module...lots does go wrong.

3. I'll review and see if I can make improvements in how I manage
modules. To start I just had one package for these for the app...that
was no good so now I name the module the same as the class with Module
suffix and put in the same package as the class, that way I know where
it is. I have one master class where I new up all the modules and add
to Guice.createInjector(). Not sure yet how this will work.

Thanks again for you help...

-Dave

Thomas Broyer

unread,
May 10, 2011, 4:17:04 AM5/10/11
to google...@googlegroups.com


On Tuesday, May 10, 2011 9:25:08 AM UTC+2, dhoffer wrote:
Thanks for the reply...

Regarding 1 at a minimum I need the code/refactoring support one would
get if using manual factories.  E.g. If I add a constructor parameter
or change parameter order I need it to keep the module/factory in
sync.  In IDEA reordering would change it everywhere, adding something
new would have a default value.  So it should at least add another
bind() to the module where I have to fill out the types (and fail to
compile until I do).  As it is now I have to manually keep both in
sync.  My IDE has become Notepad.


bind()ings are about *what* to inject, not *where* to inject them. Adding a parameter to an @Inject-ed constructor doesn't mean you need a bind()ing, unless your new parameter's *type* needs a bind()ing; but that's when you create the *type* that you need to add the bind()ing, not when you use it.

Guice is all about not having to maintain "factories": if you need a new dependency in a class, just add an argument to your @Inject-ed constructor, or an @Inject-ed field or method; you don't have to go through hoops of maintaining some factory.

Maybe you'd like your IDE to warn you if your app is missing a dependency binding, but that's hard to do because Guice is about modularity: you wouldn't want your IDE to warn you of a missing dependency if you're developping a library where the dependency is meant to be provided by the "context/environment" the library is used in (e.g. some library depends on a JMS queue or JDBC connection, and the app that uses the library has to provide the binding)
 

As a bonus the IDE should create the module as else the module really
doesn't save any coding.  But I understand this is not a Guice problem
it's a desired IDE feature.

1b. Another example, with Guice I can't even ask the IDE to find uses
of a constructor so I can find where it's used/created because that
usage is hidden behind the magic of annotations.  Again my IDE has
become Notepad.


Because the class should only be instantiated by Guice, and you should let Guice inject it (i.e. not pass it around yourself), you can simply search for uses of the class itself.

2. In the module for a class (which is its factory)


No, the module only provides "configuration", the "factory" is the Injector you build with it (and other modules).
 

I can have
completely wrong bind statements and the compiler doesn't care.


How's it different from having "completely wrong" code in a factory method?
 

It's
not until runtime that errors are seen.  Unit tests generally use
mocks (that's why its IoC) so that won't catch the error either.  I
can add another test...really an integration test that causes Guice to
create a live instance...that should catch any problems...but I'm
concerned about that working in the general case because sometimes
that will require lots of application code to fire up...not what is
desired in a unit test.

I guess my point here is that with manual factories those didn't need
to be unit tested because with the compiler's help those are
binary...you either have one or you don't...nothing really to test.
With Guice lots can go wrong in the factory (Module).  And because I
have no IDE help to maintain the module...lots does go wrong.


Can you give a concrete example? (code!)

David Hoffer

unread,
May 10, 2011, 4:47:51 AM5/10/11
to google...@googlegroups.com
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.

I guess I just don't get your comment 'bind()ings are about *what* to
inject, not *where* to inject them.' It seems you need some way to
specify the *where* too.

-Dave

Peter Reilly

unread,
May 10, 2011, 5:15:41 AM5/10/11
to google...@googlegroups.com
On Tue, May 10, 2011 at 9:47 AM, David Hoffer <dhof...@gmail.com> 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.
ekk,
you certainly do not need to do that.
For most classes you do not need to have anything in an AbstractModule.
I use it mostly to add in old non-guiced classes and for these I normally
use a @Provides annotation on a method in the module.

Peter

David Hoffer

unread,
May 10, 2011, 5:28:39 AM5/10/11
to google...@googlegroups.com
Hum what do I need then?  When do I need an AbstractModule?

This link is one of many that show doing it the way I described...
http://code.google.com/p/google-guice/wiki/GettingStarted

-Dave

Thomas Broyer

unread,
May 10, 2011, 5:53:13 AM5/10/11
to google...@googlegroups.com


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.

Mingfai

unread,
May 10, 2011, 6:08:21 AM5/10/11
to google...@googlegroups.com
On Tue, May 10, 2011 at 3:25 PM, David Hoffer <dhof...@gmail.com> wrote:
Thanks for the reply...

Regarding 1 at a minimum I need the code/refactoring support one would
get if using manual factories.  E.g. If I add a constructor parameter
or change parameter order I need it to keep the module/factory in
sync.  In IDEA reordering would change it everywhere, adding something
new would have a default value.  

Changing constructor parameter order shouldn't affect Guice at all.

Guice uses the one constructor with @Inject or a default constructor (constructor without any argument). If you remove the default constructor (without @Inject constructor), it will be break Guice without any compile time warning. Let's say you have a class with an @Inject constructor already. When you add a parameter to that constructor, you got to make sure Guice can wire the parameter. If not, Guice's injection will fail in runtime again (with proper error message). So it's true some checking are done in runtime in compare to the manual way.

When you use a Dependency Injection framework, for the objects you decide to let the DI framework to manage, you don't call the constructors directly in your code. so you are not expected to search/refactor the constructor usage.

I think the above compile time checking is not a meaningful benefit in compare to the benefit of dependency injection. Take an example from Guice's getting start page:
http://code.google.com/p/google-guice/wiki/GettingStarted
Assume at the beginning RealBillingService has a one CreditCardProcessor paramater only, and then you decide to add one more parameter namely TransactionLog. In your "manual factory", where do the TransactionLog come from? creating the TransactionLog could be complex, the tranactionLog could have a lot of fields and has a lot of dependencies and may require a correct construction sequence. Without a IoC framework, you need to code them all in your factory. With a DI framework, you focus on your application logic rather than infrastructure code. You have the flexibility to change the implementation.


 
So it should at least add another
bind() to the module where I have to fill out the types (and fail to
compile until I do).  As it is now I have to manually keep both in
sync.  My IDE has become Notepad.

I don't expect any IDE could be so intelligent to help/warn me in the above cases. In a project that use Guice, there could be classes that are not injected by Guice, and I don't want the IDE to warn me or do anything when I'm changing the constructor of those classes. And there could be multiple Guice module classes and there is no way for an IDE to know which one you want to put the binding configuration at.


 

As a bonus the IDE should create the module as else the module really
doesn't save any coding.  But I understand this is not a Guice problem
it's a desired IDE feature.

1b. Another example, with Guice I can't even ask the IDE to find uses
of a constructor so I can find where it's used/created because that
usage is hidden behind the magic of annotations.  Again my IDE has
become Notepad.

if you name all modules as *Module, you could do a Find Usage of a particular class/interface in all "*Module.java" files so it roughly can locate the relevant configuration quickly.



regards,
mingfai

David Hoffer

unread,
May 10, 2011, 9:30:17 AM5/10/11
to google...@googlegroups.com
I think I'm starting to 'get' it.  Having just one Module with the 'configuration' sure is a lot simpler.  In cases where I need to map to a specific implementation I used this approach:

@Named("MyImpl")
&
bind(IMyInterface.class).annotatedWith(Names.named("MyImpl")).to(MyImpl.class);

That seems pretty simple.  I still think/hope the IDE can be smart and make sure that if I annotate with @Inject it will let me know and/or help me make sure all the parameters have been specified in the 'configuration'.

Thanks for the explanations it really helps. 

-Dave

--

Maaartin G

unread,
May 10, 2011, 10:21:20 AM5/10/11
to google...@googlegroups.com
On Tuesday, May 10, 2011 3:30:17 PM UTC+2, dhoffer wrote:
I think I'm starting to 'get' it.  Having just one Module with the 'configuration' sure is a lot simpler.  In cases where I need to map to a specific implementation I used this approach:

@Named("MyImpl")
&
bind(IMyInterface.class).annotatedWith(Names.named("MyImpl")).to(MyImpl.class);

Actually, you need Named (or another binding annotation) only if you need *different* bindings in a single application.
 
That seems pretty simple.  I still think/hope the IDE can be smart and make sure that if I annotate with @Inject it will let me know and/or help me make sure all the parameters have been specified in the 'configuration'.

I doubt it's possible. The IDE would need to do most of what Guice does at startup. Moreover, it'll only assure that you bind it somehow - which can be mostly achieved using @ImplementedBy and @ProvidedBy. It can't help you to assure you did it correctly (since only you and your test cases know what "correct" means).

David Hoffer

unread,
May 10, 2011, 10:34:10 AM5/10/11
to google...@googlegroups.com
Right I meant to say I only use Named if *different* implementations are needed.

Thanks,
-Dave

Brian Pontarelli

unread,
May 10, 2011, 11:42:02 AM5/10/11
to google...@googlegroups.com
As a side note, I have a number of applications without modules and a number of libraries without modules as well. If I only have one implementation, I generally use @ImplementedBy and reduce the module overhead. I've also found that for libraries, using @ImplementedBy allows me to easily override (when needed) the libraries default implementations inside an application that uses the library.

-bp

scott

unread,
May 11, 2011, 2:47:51 AM5/11/11
to google-guice
David,
You make some valid points about some of the drawbacks of using Guice
and probably IoC in general, I've struggled to get the concept of
dependency injection to catch on in my office because of some of the
reasons you mention.

Its really a trade-off, by using an IoC container to wire your classes
together you might be losing some compile-time checking that you would
have by calling constructors directly, or calling factory methods, but
that route will lead you down a path to a very tightly coupled
application, that is not able to adapt to changing requirements or the
addition of new functionality. You could say similar things about
using interfaces, using lots of interfaces in your code makes it
somewhat harder to read and follow what's going on, but I think most
agree that using interfaces in logical places is beneficial and helps
to create a loosely coupled application. Another huge benefit of using
IoC is the vast improvements you'll see in the testability of your
code.

With respect to your complaint about not finding out about missing
bindings until runtime (2), this is definitely true, but I've found
that you discover the missing bindings pretty quickly as soon as you
try to start your application for the first time, and maybe run a
happy path scenario test. Misko talks about this a little bit in his
unit testing tech talk (http://www.youtube.com/watch?v=wEhu57pih5w).
Guice also supports a "PRODUCTION" mode (or Stage:
http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/Stage.html)
which will create all singletons eagerly and help expose missing
bindings at startup.

I sympathize with your issues of keeping track of modules, working on
a large project we struggled with module organization also as we
started using Guice in more and more places. We started with a module
per application approach, but this caused a lot of duplicate code in
different modules and forced developers to have to understand the guts
of other developer's code. We finally settled on a module per
"service" strategy, service is a pretty vague term in this context but
it's generally composed of a group of related classes. With this
approach, if one developer decides to use a service written by
another, they know they need to install the module associated with
that service. It seems to be working reasonably well so far, but
you'll likely have to experiment with different approaches and
determine the one that works well for your development environment.

David Hoffer

unread,
May 11, 2011, 4:27:46 AM5/11/11
to google...@googlegroups.com
Hi Scott,

Thanks for the feedback.  See my replies below...

-Dave

On Wed, May 11, 2011 at 9:47 AM, scott <scott...@gmail.com> wrote:
David,
You make some valid points about some of the drawbacks of using Guice
and probably IoC in general, I've struggled to get the concept of
dependency injection to catch on in my office because of some of the
reasons you mention.

Its really a trade-off, by using an IoC container to wire your classes
together you might be losing some compile-time checking that you would
have by calling constructors directly, or calling factory methods, but
that route will lead you down a path to a very tightly coupled
application, that is not able to adapt to changing requirements or the
addition of new functionality. You could say similar things about
using interfaces, using lots of interfaces in your code makes it
somewhat harder to read and follow what's going on, but I think most
agree that using interfaces in logical places is beneficial and helps
to create a loosely coupled application. Another huge benefit of using
IoC is the vast improvements you'll see in the testability of your
code.

[dh] I'm a IoC believer have been for a long time, so for me the move to Guice is not about adopting IoC, interfaces and mock testing, done that, the issue is using Guice or manually coding things.  I still get the same decoupled tested design.  What seems to get lost using Guice is how things are wired up.  Doing things the old way I would have one really large method that boot-strapped the app, i.e. it simply created all the top level instances and injected where they needed to go.  Factories were injected for objects created at runtime.  One thing I read that Guice allows that I could not with the manual approach is circular dependencies...but I'm not sure I need that...I've only even wanted that once/twice.

Also with the manual approach the issue of scope was explicit, it did what was coded.  With Guice I understand I have a choice I can make things that would have naturally been single instances...either Singletons or new Instances...not yet clear what is best here.

With respect to your complaint about not finding out about missing
bindings until runtime (2), this is definitely true, but I've found
that you discover the missing bindings pretty quickly as soon as you
try to start your application for the first time, and maybe run a
happy path scenario test. Misko talks about this a little bit in his
unit testing tech talk (http://www.youtube.com/watch?v=wEhu57pih5w).
Guice also supports a "PRODUCTION" mode (or Stage:
http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/Stage.html)
which will create all singletons eagerly and help expose missing
bindings at startup.

[dh] I'm going to try to write a unit test that causes Guice to create the object to see if this helps in this regard.  I really don't want to wait until after deployment/runtime to find problems.

I sympathize with your issues of keeping track of modules, working on
a large project we struggled with module organization also as we
started using Guice in more and more places. We started with a module
per application approach, but this caused a lot of duplicate code in
different modules and forced developers to have to understand the guts
of other developer's code. We finally settled on a module per
"service" strategy, service is a pretty vague term in this context but
it's generally composed of a group of related classes.  With this
approach, if one developer decides to use a service written by
another, they know they need to install the module associated with
that service. It seems to be working reasonably well so far, but
you'll likely have to experiment with different approaches and
determine the one that works well for your development environment.

[dh] OK.

I've only used Guice on one small app, I've got another that is much bigger and makes extensive use of generics...one of these days I aim to see how Guice works with heavily typed interfaces/classes.


On May 9, 11:38 pm, dhoffer <dhoff...@gmail.com> wrote:
> Okay I'm new to Guice so maybe I'm missing something but since I
> converted one app to use Guice I've found some things that I just
> don't like, I'm wondering if folks have found solutions or have
> suggestions.
>
> 1. No IDE help.  I use IDEA and as of yet it is not Guice aware so all
> my refactoring/code support is broke.  And I have to build the modules
> by hand which is just as hard as making the factory manually before I
> used Guice.  So to me Guice just moves the problem around.  At least
> when I made manual factories the IDE could keep changes in sync.
>
> 2. Loss of compile time checking.  Just by running the compiler I
> can't tell if my code is complete, by that I mean have all the right
> modules/parameters, I don't find out something is wrong until
> runtime.  Prior to this, using manual factories, this was a given.
> Perhaps I need to add a unit test that forces Guice to create an
> instance of the class so it least I could know during the test phase
> that the module/factory is correct?
>
> 3. Can't keep track of all the modules.  As best I can tell nothing in
> the module code even says what class it's a factory for.  There is too
> much annotation magic going on, apparently @Inject is enough for Guice
> to 'know' that someplace in vast numbers of Guice modules there should
> be one that has the right mix of input parameters?
>
> What am I doing wrong?  I feel like this is a couple steps in the
> wrong direction.

Reply all
Reply to author
Forward
0 new messages