Line of Sight Coding

I read an article the other day where Mat Ryer talked about a concept called “Line of Sight Coding” which he discussed as part of a talk he gave at a Golang conference a few years ago.

The general concept is simple. Make your functions easy to read and understand by limiting how many times you indent. Keep all of the happy stuff in the same line and keep your logic as simple as possible. This will save other engineers (and future you!) headaches when they need to work with that code.

If you’re interested in hearing what Mat has to say about it, here ya go:

Golang UK Conference 2016 – Mat Ryer – Idiomatic Go Tips

Line of Sight Coding tips from Mat:

  • Align the happy path* to the left; you should quickly be able to scan down one column to see the expected execution flow
    • * The route that execution will take if all goes well
  • Don’t hide happy path logic inside a nest of indented braces
  • Exit early from your function
  • Avoid else returns; consider flipping the if statement
  • Put the happy return statement as the very last line
  • Extract functions and methods to keep bodies small and readable
  • If you need big indented bodies, consider giving them their own function

To make it simple, anyone looking at your code should be able to quickly understand what a function returns if everything goes well (the happy path) and also quickly understand what it returns if things go wrong.

Take the following example. toReturn can represent an error or success depending on which parts of the logic it goes through. To understand what actually gets returned I need to understand the entire method. While this example is extremely simple, its important to think of what it would be like if there were lots of other logic:

public static String doWork() {

    String toReturn = '';

    if(successCondition) {

        if(anotherSuccessCondition) {
            toReturn = 'success';
        } else {
            toReturn = 'error';
        }

    } else {

        if(successCondition) {

            toReturn = 'success';

        } else {

            toReturn = 'error';

        }

    }
    
    // LOTS OF OTHER LOGIC
    
    return toReturn;

}

I’d have to trace the data through each conditional block. The process could take a really long time, lead to mistakes, and the code could be misinterpreted.

What if we took this example, removed the else statement and only returned the happy path value at the end of the method. Now all of the sudden we know what happens immediately when there is an error and can easily track success.

public static String doWork() {
    if(errorCondition) {

        return 'error';

    }
    if(otherErrorCondition) {
        return 'error';
    }
    
    // LOTS OF OTHER LOGIC 


    return 'success';

}

The concept of line of sight coding makes sense to me but I’ll be honest; it’s not something I’ve practice on purpose. Now that I’ve seen it, however, I’ll definitely think about how my code fits into this paradigm in the future.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.