Friday, June 18, 2010

Something that I’ve been thinking about lately is how I can make it easier to use Guava’s methods that operate on Functions, Predicates, etc.

One simple use for Functions is to get properties of objects, allowing you to (among other things) create a transformed view of a collection containing a certain property from each element. For example, transforming a list of Person objects to a String collection of names. Any time you want to do something with a collection of objects based on a certain property of those objects, this is useful.

However, it's rather ugly and awkward to have to create an anonymous inner class inline when calling a method that uses a Function. While you can create static final instances of such functions and methods that return instances of functions, with many classes you could end up with many such instances and methods. One good way to reduce the number of Function objects you need to create and make it easy to work with certain common properties (such as IDs, names, etc.) on many objects is to create interfaces that each expose a single such property:

interface HasId {
Long getId();
}

Not only does this help add consistency to your classes, it allows you to collect behavior that can work on any type of object that has the property the interface exposes. I'd probably name such classes as the plural of the property name ("Ids" and "Names", for example).

This makes working with the IDs of a list of things with IDs as easy as possible:

List<Person> people = ...
for(Long id : Ids.of(people)) { ... }

The GET function is exposed to allow its use for anything you might want a function for, not just tranform. For example, with a HasName interface and Names class similar to the code for IDs, I could do something like this: