Friday, February 27, 2015

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

Identify the ultimate pre-condition.

Part one in this mini-series is found here.

Here is a simplified extract of a program I am working on right now.

A principal method:
public void process(Dto dto, PresumptiveOrder presumptiveOrderOrNull) {
    // some code
    commonExecute(dto, appointmentOrderOrNull);
    // some code
}

commonExecute:
protected void commonExecute(Dto dto, PresumptiveOrder presumptiveOrderOrNull) {
    dto.to(appointmentOrderOrNull);
}

to:
public void to(PresumptiveOrder presumptiveOrder) {
    presumptiveOrder.setProperty(getProperty());
    // set more properties
}

Now, this becomes interesting. The method process states that it is ok for it to get null as an order parameter. Then, it forwards this to  commonExecute, which also find that to be fine, and forwards it on to the to method in the dto, which is neutral as to what kind of parameter it will welcome. And that's where things start to get exciting.

For what happens if the order parameter is actually null, as allowed by the caller chain? Well, the statement presumptiveOrder.setProperty(getProperty()); will of course crash with a NullPointerException. So we have a problem to tacle. But how?

I will not discuss here the option of checking the parameter for null and then attempt some hopefully correcting or compensating actions. I frequently meet that attitude, sometimes under the name of Defensive Programming. I don't believe in that approach, but that's the subject for a different post. Instead, I promote an offensive style, based on the assumption that should this situation ever occur. it must be the result of a programming error (or a design error). Then, it becomes important to identify and correct that error in the code as soon as possible.

Two pieces are needed for this kind of errors to be avoided. Firstly, the caller of the method must know that a null parameter is illegal. Secondly, the method itself must detect and signal when it nevertheless does occur.

The first piece is solved by including this restriction in the name of the formal argument. So, I start by renaming presumptiveOrder to presumptiveOrderNotNull. Now, this important, semantic information is signalled to the caller from whereever he is calling this method, eg. through a tooltip like this:

The second piece is solved by including a precondition verification, as discussed in part one of this mini-series. The implementation of the method now becomes


public void to(PresumptiveOrder presumptiveOrderNotNull) {
    DbC.precondition(presumptiveOrderNotNull != null, "The order should not be null");
    presumptiveOrderNotNull.setProperty(getProperty());
    // set more properties
}

So far, so good.

Now, what about commonExecute calling to? With input argument presumptiveOrderOrNull, allowing an input value of null, there is no guarantee that the precondition for to is satisfied. So what is gained? Of course, what is gained is that it now becomes obvious that the input condition ...OrNull will not do, so it must be corrected. This will then push the stronger condition ...NotNull backwards through the caller chain, from the leave method, setting the ultimate pre-condition, to the principal method. The resulting calling chain then becomes

A principal method:
public void process(Dto dto, PresumptiveOrder presumptiveOrderNotNull) {
    DbC.precondition(presumptiveOrderNotNull != null, "The order should not be null");
    // some code
    commonExecute(dto, appointmentOrderNotNull);
    // some code
}

commonExecute:
protected void commonExecute(Dto dto, PresumptiveOrder presumptiveOrderNotNull) {
    DbC.precondition(presumptiveOrderNotNull != null, "The order should not be null");
    dto.to(appointmentOrderNotNull);
}

to:


public void to(PresumptiveOrder presumptiveOrderNotNull) {
    DbC.precondition(presumptiveOrderNotNull != null, "The order should not be null");
    presumptiveOrderNotNull.setProperty(getProperty());
    // set more properties
}

Now, the principal method process clearly signals that somewhere along the chain, there is a requirement for the order parameter not to be null. This allows this condition to be verified already at the outset, eliminating the risk for potentially tricky problems later on. And by requiring and verifying this input condition, each caller along the chain can confidently call the next method, knowing that ist pre-condition is satisfied.

In the next, and last, post in this mini-series, I will discuss the case of a polymorphic situation where some of the implementations have a stronger pre-condition than others.

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.