Previous Page
Next Page

6.19. Linear Coding

Reject as many iterations as possible, as early as possible.

Chapter 2 recommends the practice of "coding in paragraphs" as a way to chunk code and improve its comprehensibility. Taking this idea one step further, it is also good practice to "process in paragraphs". That is, don't wait until you have all your data assembled before you start checking it. It's more efficient, and often more comprehensible, to verify as you go.

Checking data as soon as it's available means that you can short-circuit sooner if the data is unacceptable. More importantly, the resulting "paragraphs" of code are then specific to each piece of data, rather than to one phase of the processing. That means your code chunks are better focused on the distinct elements of the problem domain, rather than on the more complex interactions between those elements.

For example, instead of:

    for my $client (@clients) {
        # Compute current and future client value...
        my $value     = $client->{volume} * $client->{rate};
        my $projected = $client->{activity} * $value;

        # Verify client is active, worth watching, and worth keeping...
        if ($client->{activity}
            && $value >= $WATCH_LEVEL
            && $projected >= $KEEP_LEVEL
        ) {
            # If so, add in the client's expected contribution...
            $total += $projected * $client->{volatility};

you can generate-and-test each datum sequentially, like so:

    for my $client (@clients) {
# Verify active client...
next CLIENT if !$client->{activity};
# Compute current client value and verify client is worth watching...
my $value = $client->{volume} * $client->{rate}; next CLIENT if $value < $WATCH_LEVEL;
# Compute likely client future value and verify client is worth keeping...
my $projected = $client->{activity}* $value; next CLIENT if $projected < $KEEP_LEVEL;
# Add in client's expected contribution...
$total += $projected * $client->{volatility}; }

Note that this second version deals with each part of the decision separately, instead of lumping them together in one bloated, multiline conditional test. This sequential approach makes it easier to see the different criteria that are being tested, as you can focus on one criterionand its associated dataat a time. Linear coding also typically reduces the number of nested blocks that are required, which can further improve readability.

Better still, the second version is potentially much more efficient. The first version computes $value and $projected for every single client, whether or not the loop eventually uses that data. The second version does no work at all on inactive clients, because its first next statement terminates each iteration as soon as torpor is detected. Similarly, the loop block does only half as much work on the clients who are active but not worth watching.

    Previous Page
    Next Page