Understandable Code
December 12, 2004
Dave Hoover : Home

Any fool can write code that a computer can understand. Good programmers write code that humans can understand. --Refactoring: Improving the Design of Existing Code, Martin Fowler

I want to write code that is easy to read. When people read my code, I want to make it as easy as possible for them to understand what I was trying to accomplish. This is hard. Developing easily understood software requires more than just writing understandable code. There are higher level concepts to consider. That said, today I'm focusing on writing understandable code.

I grabbed this code snippet from an excellent paper from some of my colleagues at ThoughtWorks. I'll pick on their code because they can all code circles around me.

1    public Object lookup(Object key) {
2        Object value = cachedValues.get(key);
3        if (value == null) {
4            value = objectLoader.load(key);
5            cachedValues.put(key, value);
6        }
7        return value;
8    }
I want each line of source code to pull its weight. Each expression should not only instruct the compiler to do something of value, but (ideally) it should communicate my intention to the reader as well. In my opinion, line 3 does not communicate my intention to the reader. While there are likely situations where it is necessary to check for null, this is not one of them. java.util.Map has a handy-dandy containsKey(Object key) method that allows me to refactor like this:
1    public Object lookup(Object key) {
2        if (cachedValues.containsKey(key))
3            return cachedValues.get(key);
4        Object o = objectLoader.load(key);
5        cachedValues.put(key, o);
6        return o;
7    }
The following is my interpretation of what this Java code is communicating to (you) the human reader. I'll start with the first version...
1    public Object lookup(Object key) {
2        I'm getting an Object from a Map.
3        Was the Object returned from the Map null? {
4            I'm getting an Object from an ObjectLoader, because the Map returned null.
5            I'll cache this Object for later.
6        }
7        Return the Object that was either loaded or previously cached.
8    }
And now, the refactored version...
1    public Object lookup(Object key) {
2        Have we already cached the Object we need?
3            Return the cached Object.
4        Load the object from the ObjectLoader.
5        I'll cache this Object for later.
6        Return the Object that was loaded.
7    }
To me, the second version is more understandable. Your mileage may vary.

The purpose of the design of the system is, first, to communicate the intent of the programmers and, second, to provide a place for the logic of the system to live. --Extreme Programming Explained, Kent Beck


Home : Dave Hoover Copyright © 2001-2017 Red Squirrel Design, Inc. All Rights Reserved.