Thursday, February 26, 2015

Using parameter names to write self-documenting and self-diagnosing code, part 1

Since some time, I have taken on the habit of letting variable names be their own comments. That turns out to be an outstanding quality and documentation aid, that I would like to share with you. By far the most common is naming method parameters following the patterns parameterOrNull and parameterNotNull.

Assume you have a method for validating order details before processing:
public Validation validationResult(PresumptiveOrder presumptiveOrder)

Of course, you expect presumptiveOrder to be non-null. To document that, I then rename it to presumptiveOrderNotNull.

As soon as I see a name like that in the formal argument list, I know that there is a precondition to verify. Now, Design by Contract is not implemented in the common languages, with a reservation for C#'s Code Contract, that I have merely looked at superficially. For me, it seems too heavy-weight. but I may give it another try if prompted to. So instead, I am using my own, light-weight, 80/20 solution, which is as follows.

  • Make a class DbC (short for Design by Contract). I am normally against abbreviating class names, but this on is an exception. This class is not part of the functionality of the system, it is a quality assurance measure. I make an effort for the precondition verification to be as discrete as possible, and the abbreviation DbC is part of that.
  • Make a static method
public static void precondition(boolean condition, String message){
    if (!condition){
        throw new PreconditionViolationException(message);
    }
}
  • Make an exception (this is for Java. For C#, just inherit from Exception)
public class PreconditionViolationException extends RuntimeException {
    public PreconditionViolationException(String message){
        super(message);
    }
}

Voilà. You have made yourself a low-profile design by contract framework that will do in the vast majority of cases. This is what I use myself, and it serves me well. So how is it used?

Back to the example, I want to verify that the parameter presumptive order is not null:
DbC.precondition(presumptiveOrderNotNull != null, "The presumptive order should not be null");

Do I hear you screeming at me? presumptiveOrderNotNull != null looks very much redundant. The variable states that it is not null, and then I verify that it is not null. That should be quite evident, shouldn't it?

Well, not quite. You see, the point is this. The variable name states a requirement on the parameter, not a fact. This requirement is called a pre-condition. What this call to DbC.precondition does is to verify that the pre-condition holds, so that the code in the rest of the method can safely rely on it.

Oh, by the way. It is of utter importance that the calculation of the actual condition parameter, in this case presumptiveOrderNotNull != null, does not have any side effects (or at least not any side effects observable from the outside, but that is a risky statement to make). That is obviously the case here.

The next post in this mini-series discusses how to identify and implement the ultimate pre-condition.

2 comments:

Kristofer Pettersson said...

I've vowed to start using more static code analysis tools (like fortify) this year. My conclusion is that humans suck as programmers. We need better tools which automatically correct our mistakes.

Eivind Nordby said...

Sounds like a good idea. I think both code analysis and human aids are needed and complement each other. It would be interesting if you could report some of your experiences with it here.