Source Code as Poetic

source code,
like poetry,
is more than its words and symbols
(or the bytes they represent)

it has shapes that communicate
its intentions

While we might share Mr. Jourdain’s1 delight, we should not ignore the shape of our code as well as its syntax. In deciphering code, others (or ourselves after a few weeks) can use the shape and flavour of code not merely as artistic or affected expressions, but as guides to its meaning. While rhyming, alliteration, and meter are usually not practical for source code itself, patterns, rhythms, and flow are

Patterns and rhythm are how the logical parts of code (e.g. functions) resemble each other, how they appear when arranged or nested (e.g. methods in a class), and how variations from these patterns are intentional and recognizable. Top-level code, often the public-interface functions2 that begin the orchestration of all the specialized procedures (e.g. the Service pattern3) can look like verse because it calls [makes reference to] other functions, which, just by their names4, evoke what the author intended

function EventValidator.execute(person_id, destination_address, event_id)
    total_pending = get_total_pending(event_id)
    if total_pending < EVENT_MINIMUM
        return null, EventMinimumRequired("...")

    address_problems = validate_address(destination_address)
    if address_problems != []
        return null, BadAddress(destination_address, address_problems)

    fitness_problems = validate_coordinator(person_id, event_id)
    if  fitness_problems != []
        return null, NotQualified(person_id, event_id, fitness_problems)

    return event_assignment, null

Note the rhythmic pattern of the call, check, and compose-the-error triplets. Note also that the “return” has whitespace to give it finality

Compare a function call to a literary allusion or metaphor. Both represent something not described in the text (i.e. in-line) and have an understandable meaning in context. For example, “a stentorian voice” evokes a voice with specific attributes.

display_message(bold("a voice"))

does as well. We don’t know the specific of exactly “stentorian” or bold() is going to do, but we know what they mean

Couplets and triplets are common in complex processes. Whether it’s Go’s error-checking5 or if-else cascading trees, these repetitious stanzas can communicate a series of related events, a progression through a workflow, or a gathering of information and permissions needed to achieve a goal6.

At the very least, vertical whitespace allows a few lines of code to form a stanza. They are connected to each other they are a discrete step. They stand apart from the stanzas above and below, although they are connected to them. If they were completely unconnected, they would be in their own function with its own, well-considered function name

In truth, naming and whitespace are the main things we can control as far as the look and feel of source code; programming languages (even Ruby) do not allow us to break the rules of language as poetry sometimes does. But those tools are enough to see our code as more than tokens embedded in a syntax

See Also #

My thanks and endless admiration to Brian Kernighan, Robert C. Martin, and Kevlin Henney for their inspiration


  1. Bourgeois Gentleman or The Middle-Class Aristocrat or The Would-Be Noble, Molière, 1670 

  2. Also known as kingpin functions 

  3. I remain unconvinced that the Service Pattern needs to create an instance with parameters, save those parameters to the instance’s fields, then call “execute”, which takes those saved parameters and does something. A class method (with a specific name) could take those same parameters and go on its merry way, no instance required 

  4. A good function name describes what it does cleanly and without cleverness, as Nomenclature Is the Best DocumentationRichard Haven 

  5. if (result, error := subroutine(foo, bar); error != 0) { return nil, error } 

  6. Rhythmic code can also hide copy-and-paste errors because the reader will fill in the correct rhyme while the compiler will just do what it’s told 

 
0
Kudos
 
0
Kudos

Now read this

You Don’t Know Why I’ve Called You

An advantage of functions (or methods or subroutines) is boxing up a part of a process so it does not clutter up the code that calls it. Like telling one’s spouse to “take out the trash”, it reduces all an operation’s steps into a single... Continue →