Atom Feed SITE FEED   ADD TO GOOGLE READER

Two use cases - two names?

Today I did something I've never done before - I created a method that's an 'alias' to another method. I still think this is the right thing to do, but I still find it kind of weird...

Getting Providers


Binder.getProvider() allows your module to get a Provider<T> while the injector is still being created. The returned provider can't be used until the injector is ready, but that usually isn't a deal breaker:
public class ListOfFiltersModule extends AbstractModule {
public void configure() {
/* get the filters set, perhaps bound with multibindings */
final Provider<Set<Filter>> filterSetProvider
= getProvider(new TypeLiteral<List<Filter>>(){});

/* use that provider in a provider instance binding */
bind(new TypeLiteral<List<Filter>>() {}).toProvider(
new Provider<List<Filter>>() {
public List<Filter> get() {
Set<Filter> filtersUnordered = filterSetProvider.get();
List<Filter> result = new ArrayList<Filter>();
result.addAll(filtersUnordered);
Collections.sort(filteresUnordered, FILTER_ORDER);
return Collections.unmodifiableList(result);
});
}
}

For this purpose, this works pretty good.

Listing Dependencies


There's another use case for getProvider - making dependencies explicit. It's handy to include the list of bindings that a module wants right in the module. This helps Guice to fail-faster if a required binding is missing. More importantly, it makes the dependency obvious to the maintainers of the code:
public class DeLoreanModule extends Module {
public void configure() {
/* bindings needed from other modules */
getProvider(FluxCapacitor.class);
getProvider(TimeCircuits.class);

/* our bindings */
bind(Car.class).toProvider(DmcCarProvider.class);
}

This is okay, but a clarifying comment is necessary here. Otherwise the getProvider call looks out of place - the maintainers you're trying to help may delete this "unnecessary" call!

requireBinding


Giving getProvider a better name for use case #2 makes the intentions more explicit. It also means we can axe the now-redundant comment:
public class DeLoreanModule extends Module {
public void configure() {
requireBinding(FluxCapacitor.class);
requireBinding(TimeCircuits.class);

bind(Car.class).toProvider(DmcCarProvider.class);
}

Behind-the-scenes, all requireBinding() does is call through to getProvider() to ensure that key is bound. But this is just an implementation detail - we could later change requireBinding to do something different if there was a preferred alternative.

Multiple Names


We have two use cases and two names. But only one implementation! I think it's legit, but it's a bit surprising. Where else does this come up?
I think it is perfectly ok to do this, since it is really just using one method to implement another, even if it is only a straight redirection. As you pointed out: it could change later.

BTW: I think there should be another difference: the getProvider(..) should have a return value, requireBinding(..) shouldn't. That can be of importance if someone has a policy of never throwing return values away.
I agree with Peter on the return value. Another reason to consider making requireBinding() void is that obtaining a Provider is not its purpose, and (as Peter pointed out) your implementation may change and it may no longer be convenient to return a Provider.
You guys called it. requireBinding() returns void.
I had the same discussion with myself.

Recently I've named two methods:

load(Id id) and
findById(Id id)

where findById only uses load().

Semantically load() and findBy() are different things, so I added two methods. Still feels strange and I'm undecided.

Peace
-stephan
(And I'm not sure when using domain objects like Id instead of Long, the method should be findBy(Id id) - corresponding to your other post about wording and naming methods)

Peace
-stephan