Atom Feed SITE FEED   ADD TO GOOGLE READER

Google Collections talk, Aug 6 at the Googleplex

The Google Tech Users Group is hosting a talk that will interest Java developers:
Overview:
How the Google Collections Library builds on java.util to provide more building blocks for doing your job.

Where:
Building 42 of the Googleplex, Mountain View, California

When:
6:00pm Food, social, demos and announcements
7:00pm Talk by Kevin Bourrillion

If you'll be in the valley, you can register for the free event. After the talk, please join us for beers 'n' boardgames!

Correctness and my wife

I do this really annoying thing when I'm hanging out with my wife. I correct her when she uses the "wrong" words...

We're walking around town when we see something out of the ordinary - like a humongous fat dog or a friendly hobo or a police chase.
Her: "That was random"
Me: "It was unexpected. Nothing really random about it."
Her: "Ohhkayyy programmer boy. It was random. Get over it.

Our apartment is in a bit of a ghetto. So we're lying in bed and we can hear another loud argument between the neighbours downstairs. That couple has one of those dramatic relationships and they break out in yelling one night every month or so.
Me: Jodie, why are you so anxious? Get some sleep, gotta wake up early in the morning!
Her: "I can't sleep. I'm worried."
Me: "About what?"
Her: "Lots of abstract things. For example, I'm worried that she'll pull a gun on him, and they'll shoot a bullet through the ceiling, and it will hit me!"
Me: "Huh? That's not going to happen. And if it would, it would totally hit you in the ass and then you'd have a cool story."
Her: "But I'm a worrier. I always worry about abstract things like that."
Me: "That's not abstract. It's imaginary! You're worrying about something very explicit and vivid. An abstract worry might be about say, your happiness or the future. But not getting shot in the ass. That's just imaginary."
Her: "Ohhkayyy programmer boy. It was random. Get over it.

As you can see, I'm clearly getting all caught up in anal-retentive word usage and it drives Jodie crazy. I think it's cause I read code all day and argue with my coworkers whether the method should be named safeSubstring() or lenientSubstring(). She was surprised to hear that as somebody who uses computer languages all day, I spend a lot of time thinking about words from English.

I gotta stop code-reviewing our conversations.

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?

Don't create multiple annotations with the same simple name

Nobody reads imports. Good IDEs do their best to pretend imports don't even exist - they'll hide 'em from you, and manage them for you. They'll even add imports on demand when you're writing new code.

Suppose you create your own, say @Inject or @RequestScoped annotation. In the code, it's practically impossible to differentiate between this and a Guice-supplied annotation:
package com.publicobject.pizza;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.publicobject.pizza.annotation.RequestScoped;
import com.publicobject.pizza.annotation.Inject;
import com.publicobject.pizza.geography.GeographyService;
import com.publicobject.pizza.hr.EmployeeRoster;

@RequestScoped
public class PizzaStore {
@Inject PizzaStore(GeographyService geography,
EmployeeRoster workers) { ... }
}

Your head will explode debugging problems if the wrong annotation is applied. Guice can detect some problems (blowing up on a mismatched scope annotation) but it's still risky business.

TypeResolver tells you what List.get() returns

It's diminishingly rare that I get to write code that improves the internals of both Glazed Lists and Guice...

Glazed Lists' BeanProperty


BeanProperty is a convenient utility class that can expose a JavaBeans getter/setter property as its own object. You give it a class (like Baz.class) and a property name (like "bar") and it gives you a full property object - you can use it to read and write the property. It even exposes the property's type:
class Baz {
private String bar;

String getBar() {
return bar;
}
void setBar(T bar) {
this.bar = bar;
}
}

public void testBaz() {
Baz baz = new Baz();
BeanProperty<Baz> bar = new BeanProperty<Baz>(Baz.class, "bar");
assertEquals(String.class, bar.getValueClass());
bar.set(baz, "hello");
assertEquals("hello", baz.getBar());
}

Eric Burke reported a bug where BeanProperty wasn't doing the right thing for generic properties. In this example, we report the value type of Foo.bar as Object.class rather than String.class:
class Foo<T> {
T getBar();
}

class Baz extends Foo<String> {}

In order to get the return type of Baz.getBar(), we need to map Foo's type parameter T to java.lang.String.

Guice's ProviderMethods


The upcoming release of Guice lets you specify bindings with annotated methods:
class BarProviderMethods {
@Provides @Singleton
Bar provideBar() {
Bar result = new Bar();
result.setBaz("hello");
return result;
}
}

...but we run into problems if users specify generic provider methods. Guice wants to bind the return type of the provider method. Unfortunately, due to generics, that type might be insufficient:
class SetProviderMethods<T> {
@Provides
Set<T> provideSetOfT(T onlyElement) {
return ImmutableSet.of(onlyElement);
}
}

Enter TypeResolver


This class takes a generic type (like ArrayList<String>) and exposes precisely what the return types will be:
  public void testTypeResolver() {
Type listOfString = new TypeLiteral<List<String>>() {}.getType();
Method getMethod = List.class.getMethod("get", int.class);

TypeResolver resolver = new TypeResolver(listOfString);
assertEquals(String.class, resolver.getReturnType(getMethod));
}

I suspect this class is generally useful for any app that uses a reasonable amount of reflection. If this is useful to you, grab the source from Guice SVN.

The reasons I'm not on iPhone

It's really tempting. As far as devices go, iPhone 3G is the best there is. It's a generation ahead of its competitors, and the gap is growing. The app store is great for both developers and for its users. But I'm not gonna get one:

Amazon MP3. Lots of good songs with no 'deregister this computer' nonsense. But Amazon MP3 cannot compete with iTunes on Apple's platform—third party apps can't download while I surf the web. This also kills movie and video downloads.

Skype. Voice-over-IP is forbidden on the iPhone 'cause AT&T wants to bill voice traffic at a different rate than data. Even on my home network, AT&T would prefer I pay them for each minute of each call. I want net neutrality but the iPhone won't have any of it.

Flash and Java. That means no Line Rider, Hulu, Naval Command or flexgames.com. Apple would prefer for developers to write iPhone-only apps rather than phone-independent apps. This is good for Apple but bad for developers.

The iPhone is a lock-in platform. Sorry, Apple, but I'm not ready for that level of commitment.