Saturday, 7 July 2012

Item 40: Design method signatures carefully

Choose method names carefully. Names should always obey the standard naming conventions (Item 56). Your primary goal should be to choose names that are understandable and consistent with other names in the same package. Your secondary goal should be to choose names consistent with the broader consensus, where it exists. When in doubt, look to the Java library APIs for guidance.

Don’t go overboard in providing convenience methods. Every method should “pull its weight.” Too many methods make a class difficult to learn, use, document, test, and maintain. This is doubly true for interfaces, where too many methods complicate life for implementors as well as users. For each action supported by your class or interface, provide a fully functional method. Consider providing a “shorthand” only if it will be used often. When in doubt, leave it out.

Avoid long parameter lists. Aim for four parameters or fewer. Most programmers can’t remember longer parameter lists. If many of your methods exceed this limit, your API won’t be usable without constant reference to its documentation. Modern IDEs help, but you’re still much better off with short parameter lists. Long sequences of identically typed parameters are especially harmful.

There are three techniques for shortening overly long parameter lists.

One is to break the method up into multiple methods, each of which requires only a subset of the parameters.

A second technique for shortening long parameter lists is to create helper classes to hold groups of parameters. Typically these helper classes are static member classes (Item 22). This technique is recommended if a frequently occurring sequence of parameters is seen to represent some distinct entity.

A third technique that combines aspects of the first two is to adapt the Builder pattern (Item 2) from object construction to method invocation.

For parameter types, favor interfaces over classes (Item 52). If there is an appropriate interface to define a parameter, use it in favor of a class that implements the interface. For example, there is no reason ever to write a method that takes HashMap on input—use Map instead. This lets you pass in a Hashtable, a HashMap, a TreeMap, a submap of a TreeMap, or any Map implementation yet to be written.

Prefer two-element enum types to boolean parameters. It makes your code easier to read and to write, especially if you’re using an IDE that supports autocompletion. Also, it makes it easy to add more options later. For example, you might ave a Thermometer type with a static factory that takes a value of this enum:

public enum TemperatureScale { FAHRENHEIT, CELSIUS }

Not only does Thermometer.newInstance(TemperatureScale.CELSIUS) make a lot more sense than Thermometer.newInstance(true), but you can add KELVIN to TemperatureScale in a future release without having to add a new static factory to Thermometer.

Reference: Effective Java 2nd Edition by Joshua Bloch