Tag Archives: fast-fail Java tip

Writing Fail-Fast Code

With projects as complex as they are now, it can be hard to modify all of the code needed when a change is made.  First is to identify all the places needed for modification. The next step is to write code that handles the new requirement. The former is typically harder than the latter. Inspect the following code.

static void processIfQuiet(Data d) {

if (d.getType() == DataType.XML) {

System.out.println(“XML Data”);

}

else if (d.getType() == DataType.LEGACY) {

System.out.println(“Legacy Data”);

}

}

This code is fine if no more data types are added.  When a new DataType is created, this code could be skipped and no one would know.  The code could be pushed to production incomplete and there will be errors that the customer will find or not depending where this snippet is located.  If this is for a data loader, the new data type could be falling through and not be stored at all.  Three months down the road when the customer is generating a report relying on the new data type, the report code blows up and it takes awhile to find the error.  Here is an implementation trick that I had to learn the hard way.

static void processIfLoud(Data d) {

if (d.getType() == DataType.XML) {

System.out.println(“XML Data”);

}

else if (d.getType() == DataType.LEGACY) {

System.out.println(“Legacy Data”);

}

else { // new part

assert false: “Unknown Data Type”;

throw new RuntimeException(“Unknown Data Type”);

}

}

The else clause will catch any unknown type either throw an AssertionError or a RuntimeException depending whether or not assertions are enabled. This message could be logged and not have an ugly Error or Exception popping up. However, I would call this a “Developer’s error” meaning that it should not have got past the developer in the first place. Making it ugly will make sure it will not be missed and can be fixed before the customer gets to see it. This can be used for select statements too. See the loud version of a select statement:

import static blog.mathison.example1.DataType.XML;

import static blog.mathison.example1.DataType.LEGACY;

static void processCaseLoud(Data d) {

DataType dt = d.getType();

switch(dt) {

case XML:

System.out.println(“XML Data”);

break;

case LEGACY:

System.out.println(“Legacy Data”);

break;

default:

assert false: “Unknown Data Type”;

throw new RuntimeException(“Unknown Data Type”);

}

}

Just adding a default will make it fail where the problem is rather than three months down the road.  Do you think this not a good idea?  Are there better ways?  Leave me a comment.

Advertisement