|
When Static Methods and Code Collide
Resist the urge to overuse static methods. Promote greater application flexibility through libraries and interfaces
by Daniel F. Savarese
August 6, 2004
The release of a final version of J2SE 1.5 is just around the corner, and Sun is up to its old tricks again. One day I visited java.sun.com only to find J2SE 1.5 was no more. It is now J2SE 5. Furthermore, the J2SE 1.5 SDK is now the J2SE 5 JDK with internal version number 1.5.0. Just when we were getting used to accepting that Solaris 2.7 is Solaris 7, SunOS 5.8 is Solaris 8, and JDK 1.2 is J2SE SDK 1.2, now we've got J2SE 5 and are back to a JDK instead of an SDK, but with some internal version numbering business tacked on. These numbering games aren't worthy of note other than to put you on alert that documentation will surely be inconsistent and cause some short-term confusion.
A J2SE news item meriting attention is that Sun has started making available snapshot releases of JDK 1.5 (or is it 5?). This move is extremely important because it gives developers access to new features and bug fixes that are in the development tree but have yet to make it into a formal release. Also, it gives Sun the benefit of more user testing, with the anticipated result that more bugs will be detected sooner. A note on either java.sun.com or www.java.net from one of the J2SE team members called the new practice an experiment, but my guess is they will not discontinue the practice after they reap its benefits. The release of J2SE 5 may be the most important event for Java developers since the transition from JDK 1.1 to J2SE 1.2. Therefore, Sun's effort to involve developers more in the release cycle is laudable.
Having dispensed with the commentary, it's time to talk about code. What I perceive of as an overuse of static methods in Java programs has long concerned me. Time after time I find my hands tied by static methods that cannot be overridden or adapted in an object-oriented vein. I don't mean to say that static methods should be avoided altogether. It just seems to me that they are often used when inappropriate. I'll concede that it's hard to lay down clear guidelines about when they are appropriate and when they are not; so keep in mind I am expressing my personal opinion based on my experience, which may not agree with yours.
Go to the Library
Despite the variety of programming work I've done over the years, I have a bent toward library and API design. Reusability, flexibility, genericity, maintainability, portability, usability, and testability are some of the factors I emphasize in design. Also, my experience as an application programmer influences how I approach the design of class libraries. I don't believe class libraries should force constraints upon an application that should best be left in the hands of the application.
For example, I don't believe class libraries should have dependencies on environment variables or system properties unless absolutely necessary. These dependencies are instances of global behavior that influence how a library behaves to all aspects of an application. If part of an application requires a library to behave in one manner at the same time another part of the application requires it to behave in another manner, global configuration throws a wrench into the works. It is less restrictive to allow the application to instantiate library artifacts and configure them through an API, thereby allowing the application to implement its own environment variable, system property, or other configuration system.
Similarly, static methods preclude the ability for a program to customize behavior or implement generic algorithms using polymorphism. It can be tempting to lock up stateless algorithms into static methods instead of creating interfaces and class implementations. If you resist the temptation, you can make a class library more flexible and make the job of an application developer easier.
To illustrate the point, let's look at sorting. If you implement sorting in a static method, you cannot interchange sorting algorithms without changing the method call in application code. Instead of using a static method you can define an interface such as:
public interface Sort {
public void sort(
Object[] array, Comparator
comparator);
public void sort(
Object[] array, Comparator
comparator, int start,
int end);
}
Back to top
|