The Wayback Machine - https://webcf.waybackmachine.org/web/20240730221542/https://blog.thepete.net/blog/2021/06/24/explaining-variable/

Pete Hodgson

Software Delivery Consultant

Explaining Variable

June 24, 2021

An Explaining Variable is a code-level pattern which reduces the need for code comments, making your software a little more self-documenting.

Here we have a function with some non-obvious business logic, with a comment to explain what’s going on:

before.js
function determineShippingSpeed(shippingRoute, shippingMethod) {

    // if the shipping route is very short, or it’s by air
    if( shippingRoute.distance < 20 || [BY_AIR,BY_AIR_EXPRESS].includes(shippingMethod) ){
        return SAME_DAY;
    }

    // ...
}

And here’s how we can replace that code comment with a couple of explaining variables:

after.js
function determineShippingSpeed(shippingRoute, shippingMethod) {

    const routeIsVeryShort = shippingRoute.distance < 20;
    const isByAir = [BY_AIR,BY_AIR_EXPRESS].includes(shippingMethod);
    if( routeIsVeryShort || isByAir ){
        return SAME_DAY;
    }

    // ...
}

We no longer need that code comment; we’ve replaced the explanation in the comment with two explaining variables.

The benefits of explaining variables

Why might we prefer explaining variables over code comments? Because with code comments we end up with two parallel sources of truth - what the code is doing, and what the comment says. Over time these two sources of truth have a tendency to diverge.

To illustrate how this can happen, we’ll explore a scenario where we need to update the logic in this function later on. Let’s say we can no longer assume that shipping by air implies same day delivery. To reflect these updated business rules, we simply remove the second part of the conditional in that if statement:

function determineShippingSpeed(shippingRoute, shippingMethod) {

    // if the shipping route is very short, or it’s by air
    if( shippingRoute.distance < 20 ){
        return SAME_DAY;
    }

    // ...
}

Looks good, right? The implementation is correct. But we forgot to update the comment and it is now out of sync with the implementation. Oops.

This phenomenon of comments and implementation diverging occurs a LOT. It’s really easy for a developer to skim over comments when making a code change and forget to update them. There’s even a saying for this - “code comments are lies waiting to happen”.

In contrast, when working with the version of our implementation which uses explaining variables, the code remains accurately self-documenting:

function determineShippingSpeed(shippingRoute, shippingMethod) {

    const routeIsVeryShort = shippingRoute.distance < 20;
    if( routeIsVeryShort ){
        return SAME_DAY;
    }

    // ...
}

Explaining Method/Function

We can apply this same self-documenting approach with methods or functions - rather than commenting a block of code to describe what it does, we can create a method or function with an explanatory name.

Here’s a function which is performing a few different steps, described using comments:

function placeOrder(orderSpec) {
    // create order
    const order = Orders.createOrder(orderSpec);
    order.validate();
    order.save();

    // submit order for fulfillment
    const manifest = FulfillmentAnalyzer.manifestForOrder(order);
    Warehouse.submitManifest(manifest);

    // track order analytics
    Analytics.orderCreated(order);
    Analytics.fullfillmentRequested(manifest);
}

We can replace those comments with explaining functions:

function placeOrder(orderSpec) {
    const order = createOrder(orderSpec);
    const manifest = submitOrderForFulfillment(order);
    trackOrderAnalytics({order,manifest});
}

function createOrder(orderSpec){
    const order = Orders.createOrder(orderSpec);
    order.validate();
    order.save();
    return order;
}

function submitOrderForFulfillment(order){
    const manifest = FulfillmentAnalyzer.manifestForOrder(order);
    Warehouse.submitManifest(manifest);
    return manifest;
}

function trackOrderAnalytics({order, manifest}){
    Analytics.orderCreated(order);
    Analytics.fullfillmentRequested(manifest);
}

These explaining functions (or methods) have the same benefits as explaining variables - they reduce the need for explanatory comments.

References

Martin Fowler introduced the concept of explaining variable in his Refactoring book - it’s covered briefly in his Refactoring.com catalog. I find myself recommending this refactoring a lot and wanted a more detailed discussion of the pattern to point to, hence this post.