The Artima Developer Community
Sponsored Link

Sharpening the Saw
Overload Overload
by Matt Gerrans
July 19, 2003
Summary
How much method overloading is a good thing? How much is just bewildering?

Advertisement

Ain't it nifty when you can call a method to draw an image with nothing more than a Graphics object and an Image object? Wouldn't it be nice to be able to tell it where to draw, too? What about being able to specify whether to stretch or crop it? Yes, yes, these things are all nice and there are many more. At what point do all these different choices become more of a burden than a convenience?

Obviously, the possible combinations of overloaded methods explodes as the number of options increases. It is not hard to understand why API programmers can seem to get carried away and offer too many overload choices. Overloading methods provide a clean and simple way to add flexibility to an API, but at some point the simplicity diminishes and the value of overloading rapidly decreases. Where is this point? It probably depends on the particular reader, but also on basic cognitive capabilities of humans in general (the number seven comes to mind as being the place where most eyes begin to glaze over).

I recently needed to use the DrawImage() method of the Graphics object in Microsoft .NET. I was horrified to find that it had no less than 30 overloads! *

I had been coding happily along when I came up against this veritable Medusa of methods. I foolishly stared straight into the face of this beast and became completely derailed. I was dismayed that I had to stop my train of thought and sift through this massive list of overloaded methods to find the one that was right for me.

(It was almost as annoying as not being able to come up with decent metaphors to mix while writing about it.)

Even with this ridiculous number of overloads, I had no option but to choose one that didn't quite match my needs. The one I needed had the parameters I required and several that I didn't (I wanted to resize the destination image, but I didn't care about using the abort callback, or selecting a sub-region in the original image). In other words, there weren't enough overloads! No, I'm not asking for more (please, please, no!), I'm asking for something different.

How Overloading Can Be Reduced?

How do you solve this problem? It connot be intractable. Can it? In any event, the first step toward solving it is at least caring about it.

Some languages don't have this problem. For example, in Python you can't have a bunch of different overloads of the same method. Instead you can use named arguments (it really boils down to using a dictionary). You would have a single drawImage() method whose usages look something like this:

graphics.drawImage( image, x = 100, y = 100, border = True )
and
graphics.drawImage( image, width = 400, height = 200 )
In this case, the parameter for the image object is not named, but all the rest are. This idiom is commonly used in Python libraries, such as graphical libraries, where methods could otherwise have many parameters.

In Java, you could simulate this with a Map, but there would probably be great hue and cry if you suggested this, since it would contain a heterogeneous collection of objects. Its usage and implementation would probably be too clunky anyhow. For example, usage might look like this:

Map params = new HashMap();
params.put( "x", new Integer(100) );
params.put( "y", new Integer(100) );
params.put( "width", new Integer(100) );
params.put( "height", new Integer(100) );
params.put( "border", new Boolean(true) );

graphics.drawImage( image, params ); 
The implementation of the drawImage() method would be even clunkier: You'd have to pick out all the input objects from the Map, by name, then cast them to their appropriate types, unbox some of them, deal with wrong types, etc. and then you'd probably just end up dispatching to private overloads anyhow.

C# could handle the variable parameter list much better than Java, using the params keyword. The method would be implemented like this:

   public class Graphics
   {
      // ...
      public void drawImage( Image image, params object [] options )
      {
         // Unpack all the possible parameters.
      }
      // ...
   }
And then it could be used like this:
   graphics.drawImage( image, "x", 100, "y", 100, "width", 400, "height", 300, "border", true );
or, even better (not quite so verbose):
   graphics.drawImage( image, "x,y,width,height,border", 100, 100, 400, 400, true );
However, in Java and in C#, this is circumventing the whole statically-typed convention that is central to these languages.

Another solution is to create some helper objects to aggregate parameters. This is common in C, where you create a structure, zero it out and populate the relevant elements. Of course, C doesn't have the option of overloaded functions, so other than having zillion parameters, that is really the only option there. I haven't seen this done much in object-oriented languages.

C and C# also have the ability to handle variable-length argument lists. In C, it is not very useful unless the first parameter in the list tells you what type the other parameters are (or unless you come up with some scheme to make them self-descriptive). In C#, you get an object array, so you could use reflection on each of the elements, but that would hardly be elegant and wouldn't let you distinguish between objects of the same type (is an int the x coordinate? y? width? height?).

Another idea would be to have the target object collect information, like this:

graphics.setX(100);
graphics.setY(100);
graphics.setWidth(100);
graphics.setHeight(100);
graphics.setBorder(true);

graphics.drawImage(image);
This is kind of like the manipulator usage on C++ I/O streams and it is pretty clunky. The alternative of setting all the drawing attributes on the image object instead is nearly equally clunky, since these are really attributes of the drawImage() action, not so much of either of the objects.

Is there an elegant solution for this problem in Java and C#, or is this just something we have to live with in statically-typed languages?


* To add to the clutter, many of these overloads had very long parameter lists, several having up to 10 parameters. Too many parameters is another egregious practice in my book, but I'll save that for another rant.

Talk Back!

Have an opinion? Readers have already posted 15 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Matt Gerrans adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Matt Gerrans is Artima.com's C# columnist. Matt began his professional life as an electronic engineer but quickly saw the light and switched to software development. He now has more than 12 years professional software development under his belt, including work in C++, Java, Python, and yes, even JavaScript.

This weblog entry is Copyright © 2003 Matt Gerrans. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use