November 22, 2010

Collection Utility Methods on the Object

Originally published 16 Apr 2006

I’ve been experimenting lately with a technique that I’m still unsure about. It has a little smell to it, but it has some benefits. The technique is to add static collection-related utility methods on an object. That is, I’ll add a static method that takes a collection of that object on the object itself.

Take the classic Shape example:

   public class Shape {
      // here’s a typical instance method
      public void draw();

      // here's what I’m talking about.
      public static void draw(Collection shapes) {
         for (Iterator it = shapes.iterator(); it.hasNext; ) {
            Shape shape = (Shape) it.next();
            shape.draw();
         }
      }
   }

Now, I haven’t done this kind of thing much; maybe once or twice. The first time I did it was because I noticed some duplication. The exact looping code was shared by multiple clients. I wanted to remove the duplication, but I didn’t know where to put it, so I stuck it on the object itself. The clients became (in the context of this example):

   someShapeClientMethod() {
      Shape.draw(myShapes);
      ...
   }

I think this actually improves clarity (although I could have accomplished the same thing by creating a helper draw() method in the client). This also has the benefit of grouping the iteration logic close to its source, e.g.,Shape here.

The real world example where I first used this was a query.  I had a collection of objects and I wanted to find a specific one. Say, I had a collection of Shapes and I wanted to know who was the biggest:

public static Shape getBiggest(Collection shapes);
 
I think this technique is most applicable under the following circumstances:
  1. For good reason, multiple clients share the code and you want to remove the duplication.
  2. The number of such utility methods is very small. Otherwise, it would be better to group the methods in another, separate utility class (e.g., Shapes or ShapeUtils).
What bothers me most is that I can’t recall seeing this technique used anywhere. That could mean that there’s something really bad about it. One problem is that it clutters the object with additional methods. That’s why I think it should be used judiciously. Also, from a purist view, do these methods really belong on the object?

What do you think?

No comments:

Post a Comment