I thought I’d post about a development problem which seems to occur very often, and often frustrates me. Often we come across a situation where we need to pass an object to something, and the object we have is of a different type (but similar). For instance, if I’d like my Cat to be trained to fetch sticks for me:

// within method
void receive(Cat cat)
{
dogHandler.train(/* hmm, what do I do here? */ ..);
}
interface DogHandler
{
void train(Dog dog);
}

This code is maybe not a great example (as dog handlers often won’t be keen on training cats, and possibly these objects would be too different), maybe you could replace Cat with DocumentSearchResult and Dog with Document or something. This problem often occurs with one object which represents another, but is not actually an instance of the object – but the solution is the same so I’ll keep my cats & dogs.
Bean Approach
This is possibly the most common solution to the problem, and the reason I am writing this post. If the interface represents a concrete thing (as opposed to a trait etc) then often someone will create a simple class which just implements the interface, and stores properties to back it:

public interface Dog
{
boolean chasesCats();
int getWeight();
}
public class SimpleDog /*or maybe DogBean?*/ implements Dog
{
boolean chasesCats;
int weight;
public SimpleDog(boolean chasesCats, int weight)
{
this.chasesCats = chasesCats;
this.weight = weight;
}
public boolean chasesCats() { return chasesCats; }
public int getWeight( return weight; }
}

This bean object can then be created with the properties of the object you are trying to convert, i.e:

void receive(Cat cat)
{
Dog dogProperties = new SimpleDog(false, cat.getWeight());
dogHandler.train(dogProperties);
}

Adapter Approach
The alternative is to adapt the Cat to fit the Dog interface. This would be done like so:

public class CatDisguisedAsDog implements Dog
{
Cat cat;
public CatDisguisedAsDog(Cat cat)
{
this.cat = cat;
}
public boolean chasesCats() { return false; }
public int getWeight( return cat.getWeight(); }
}

This can then be used as so:

void receive(Cat cat)
{
Dog disguised = new CatDisguisedAsDog(cat);
dogHandler.train(disguised);
}

So, which approach to use?
It seems to me that method #1 is used far too often. I believe this is probably because it’s conceptually simpler, as it’s basically the procedural approach (you can do this with structs in C, but you’ll have a harder time writing Adapters!). However, it actually has a huge number of disadvantages, most of which I have witnessed first-hand in large systems.
Debuggability
I have seen plenty of NPEs which occur because some piece of code accesses a property of one of these bean classes, gets a null and blows up. The problem here is that maybe the null shouldn’t have been there, now you’ve got to backtrack through the code to find out exactly what put the null in there. Yes you should be checking the constraints of your bean upon construction, but often this is overlooked, and leads to errors in earlier processing surfacing somewhere completely different.
Additionally I find it more useful to hit a breakpoint in a class to find out (from the stack) why it is being used, as opposed to it be shunted into another class and passed along.
Performance
There are two aspects to performance here. One is simply the raw manipulation of data. In the bean case, the VM must copy a number of fields from one place to another, and with large amounts of objects, this has a performance overhead. The adapter does not have this problem – class creation (just like the bean) and additionally a single copy of the object reference – which should not change if the object grows. Ok, it does have an extra layer of indirection when you make a call, but (a) you’ve already had to make that call with the bean method, and (b) you can cache in the adapter if you really want to.
The other performance problem, which is often the big one, is lazy evaluation. What if the work required to calculate the weight of the Dog was a heavy operation, and required a DB call or something? What if the DogHandler didn’t care about the weight? The bean approach always requires all the properties defined on the interface to be populated, even though they may never be used. Not so for adapter, which will evaluate the properties lazily.
Maintainability
This one is certainly more arguable, but I believe adapters lead to a cleaner and more maintainable design. Effectively control flow always occurs in a single direction, and is encapsulated in adapter classes. Using the bean style means that changes to the target interface (Dog) requires changes to code which may simply be passing them on (and twice – due to the 2way flow – pulling from Cat, pushing to SimpleDog), and everywhere these are used changes will be necessary. Yes you could pass the Cat into the SimpleDog and extract the properties there, but that would just be an eagerly caching adapter no?
Collections and Adapters
So what about collections? Nothing changes right? You can just put either your adapter or bean into another list and pass it along? Not quite. Once you are adapting objects, it’s a good idea to adapt your collections too. A great library to use for this is google-collections (commons-collections also supports it but is not typesafe and the forked typesafe version is not so popular). Google collections will allow you to define how you’d like your objects transformed, and they will be transformed lazily, upon retrieval.

void receive(List cats)
{
List catsInDisguise = Lists.transform(cats, new Function(){
public Dog apply(Cat cat){
return new CatDisguisedAsDog(cat);
}
};
dogHandler.trainAll(catsInDisguise);
}

Doing things this way can give you even more performance benefits. Imagine if the dogHandler only ever trained the first 10 dogs? Using a transformed collection like this, you’d only ever create 10 adapters. Shuttling the adapters into a separate list would mean having to create them for each and every cat, whether or not they’re ever used. What if the list of cats is spooling from somewhere which loads the cats lazily? Then this could be an even more significant penalty.
Yes the syntax is not the prettiest using anonymous classes (blame Java), but you could always define the Function object on you adapter itself if you wanted (or even autogenerate it with a little dynamic proxy magic). This is effectively a functional style (look, no looping code!), but I think this is great example of it’s usefulness.
Exceptions
There are, as always, exceptions to what I am saying. Sometimes you may want beans because they get sent over RMI, and callbacks into an adapter would often be slower. You may also have transactional issues with delaying the execution of certain tasks (I think that it should be one transaction per request though, which would never have a problem with this). You may also want your bean to be mutable, but not affect the state of the underlying object, in which case you’d always need a copy. These do tend to be rarer cases though, and in most cases an adapter is certainly the better option.

Fresh ideas, announcements, and inspiration for your team, delivered weekly.

Subscribe now

Fresh ideas, announcements, and inspiration for your team, delivered weekly.

Subscribe now