Code Layout for Readability

Here's a simple rule to make your code more readable: When dependency flow is not restricted, put the dependent code over it's dependencies. Here's an example:

import math

def closest_points(points):
    if len(points) < 2:
        return None
    closest = points[0], points[1]
    for i in range(0, len(points)):
        for j in range(i+1, len(points)):
            dist = distance(points[i], points[j])
            if dist < distance(*closest):
                closest = points[i], points[j]
    return closest

def distance(a, b):
    return math.sqrt(length_squared(a.x-b.x, a.y-b.y))

def length_squared(x, y):
    return x*x + y*y

The code that depends least on other functions to run is the simplest and least interesting part of your program. You can see that in the example, the hardest, most interesting part of the program, the function that calculates closest points from a plot, is immediately after the intro which grabs imports and constant declarations. It is most likely the interfacing part of this module because nothing else in the module requires its presence.

This kind of dependency ordering allows the reader to skim large parts of the source file, because she discovers what the code is doing in the first half of the source. Even if she starts reading from middle of the code, she will know that the dependencies are either listed in the intro or under the function she's looking at. That's why it works so well.

Is it allowed?

Dynamic programming environments seem to propose downwards dependency flow. See the following code snippet:

x = 0
y = x * 2

def main():
    print(y)

main()

You have to define main before you can call it. Also you have to define x before you can use it in y. Obviously you can't relayout some of these things to make dependency flow in reverse from program flow. But consider following sample:

def foo():
    bar()

def bar():
    foo()

This code forms an infinite loop that is entered by calling either of the functions. To allow this, the function scope must allow dependency in reverse direction. It means that ordering of the dependency is not restricted within functions. We can exploit this property to improve the readability of our programs.

Does it make sense?

There is a reason to expect that dependency represented flowing upwards is the most logical and most readable way to represent complex dependencies. It's because people tend to do it everywhere else. Titles are represented before content. In recipes, the outcome tend to be described before ingredients.

It also adds information into the program. The upwards dependency flow is only possible when there is no strict downwards flow. Therefore it's clear when there is a strict dependency between some values, because the dependency flows downwards when it happens.

Obviously it makes sense in coding. So follow this rule: Put the dependency flow upwards whenever the data dependency does not restrict it.

Similar posts