Brian Slesinsky's Weblog

Wednesday, 24 Sep 2003

Functional Style in Java

Functional programming is (in part, to oversimplify) a way of writing programs using only immutable variables and objects. This eliminates certain kinds of bugs that happen when objects change unexpectedly. Normally, functional programming is done in specialized languages like ML and Haskell that aren't very popular. I believe this is because the programs tend to be rather mathematical and use special, hard-to-understand tricks to get work done despite the illusion that nothing actually changes. They also don't have the vast libraries and tools that mainstream programmers are used to.

However, it's possible to apply some of the lessons from functional programming to Java (and similar languages), and I believe it results in a pretty good coding style that can be easier to debug than your average JavaBean.

The first step is to use final instance variables whenever it makes sense. This is an overlooked Java language feature that even experienced Java programmers might be surprised to learn about. For a simple example, here's a record in a music database:

public class Album {
   private final int albumID;
   private final String albumName; 
   private final Artist artist;
   private final List tracks; 
   public Album(int albumID, String albumName, Artist artist, List tracks) {
      if(albumID<1 || albumName==null || artist==null || tracks==null) {
          throw new IllegalArgumentException("null arg");   // (simplified)
      this.albumID = albumID;
      this.albumName = albumName;
      this.artist = artist;
      this.tracks = Collections.unmodifiableList(new ArrayList(tracks));

If you're not familiar with final instance variables, this might look a little odd. Don't you have to set a constant when you declare it? It's a special rule: a final instance variable must be initialized exactly once, either when declared or in the constructor.

The nice thing about final instance variables is that if you've verified an invariant in the constructor, you can be certain it holds for the life of the object. No matter how complicated this class gets or what any other ill-considered method does, albumName, artist, and tracks can never be null. Anyone reading the class can easily verify this by looking at the constructor. It makes debugging much easier. You don't have to worry about synchronization and you don't have to do null checks. And (not that I'm recommending this), you could even make the instance variables public and get into surprisingly little trouble.

Of course, immutable objects are nothing new (see String), and you can write one without using final instance variables. But then bugs can break the invariant and you have to read the whole class to be sure it's really immutable. (For protected variables, it's even worse - you have to read all the subclasses.)

It's useful to make classes partially immutable, so this isn't an all-or-nothing strategy. The goal is to reduce the complexity of the system. (If you're retrofitting an existing system, a good start is to make id's immutable.)

A mechanical device might be advertised as having "only 3 moving parts" to emphasize its simplicity and reliability. A non-final instance variable is a moving part. How many moving parts do you need to write your class? Could you get away with fewer?