-2

How many times have you encountered a function with a return statement deep within the code? Or failed to notice a break or a continue in a loop? While I have not been blindsided by return recently, I have still been caught off guard by continue and break.

Shortly after undergrad, I suggested changes to C’s break statement to Dennis Ritchie. While I no longer desire the changes, Dennis’s response holds wisdom that applies more broadly:

Your suggestion that the ‘break’ statement should be augmented with a number to indicate the number of levels to escape from, has arisen before. It is an idea that both I and the X3J11 committee thought about carefully, and it is attractive in several ways. Nevertheless, the committee standardizing the language decided to reject it. One of the inherent problems with the idea is that it exacerbates a difficulty already present with ‘break’, namely making it hard to determine where control goes. Very small changes in the source program result in dramatic changes in the control flow, and the confusion increases with the number of break levels. [emphasis mine]

I believe the issue is not with break and other control flow statements. The issue is how we indent those statements. The indentation should not be from the level where the control goes from. Instead, indentation should be to the level the control goes to. So, instead of

func(....) {
    …
    for (...) {
        …
        if (...) {
            break;
        }
       …
    }
    …
}

I propose that we indent as follows

func(....) {
    …
    for (...) {
        …
        if (...) {
    break;
        }
       …
    }
    …
}

The above code looks ugly, and that is precisely the point.

By indenting as usual, we potentially mask unexpected behavior. By indenting as proposed, we make the unexpected expected. This will result in a better understanding of the code, and better night sleep for all.

I do not know what Dennis would have thought of this. Sadly I never got to run it by him. However, if you like the idea, as a tribute to Dennis, I would like to have it named after him. K&R style of indentation is already attributed to him. Calling this Ritchie indentation will be confusing. So, I propose we call this Ritchie flow-apparent (RFA) option. There are many indentation standards, and this would apply to most. Code editors, repository code viewers could toggle the indentation on click of the RFA button. And if folks like, this option could be added to code formatters too.

Please let me know what you think about this?

I wrote this article originally on medium. It has a scanned copy of the original letter from Dennis Ritchie.

Would love to hear what folks think of this? Also, if folks like it and support it, are they in position to help create tooling around it?

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • Dear Álvaro-gonzález, this is not specific to `C`. It is generic proposal applicable to a wide spectrum of programming languages including `Java`, `JavaScript`, `C#`, `Golang` and more. Is it OK if I remove `C` and add back `readability`? – user2150648 Mar 29 '23 at 08:09
  • 1
    It's an interesting idea, but it does make it harder to see that the break is conditioned on the if statement. I think I'd prefer to use the current indentation, with an editor that draws a line or something to show you what the break breaks. [Something like this](https://i.imgur.com/GEY8FB1.png) – Verpous Mar 29 '23 at 08:31
  • This is likely going to get closed here because SE hates program design/programs with a design and there's no suitable site on the network to discuss such. I'd recommend posting at https://software.codidact.com/ which allows design questions and at some extent also questions about best practices, as long as "best" is defined (safest/most readable in this case). – Lundin Mar 29 '23 at 09:32
  • Attempting to pretend your idea is somehow related to someone famous is a massive red flag that makes it look like you're a con artist. – Brendan Mar 29 '23 at 09:37
  • Hi Verpous, anything that makes the flow control apparent is wonderful! Your idea is great! – user2150648 Mar 29 '23 at 16:02

1 Answers1

5

Lots of things have happened since the first standardization of C and we now have a better understanding of what designs that are good and which ones that are "spaghetti programming". Back in the days when K&R 1st edition was written, they really didn't have a clue about such (although "goto considered harmful" pre-dates the C language). And even during C90 standardization, the concept of good C programming practice was still under construction. Similarly, the concept of computer security didn't really exist back in 1990.

Mid 1990s Les Hatton performed population studies on all manner of C code to determine the most common sources of bugs. His results were published in the book Safer C, which is more of a science paper than a book. The conclusion was that C contained numerous dangerous pitfalls that should be avoided by adopting a safe subset of the language. Many of these pitfalls were already known from before through Andrew Koenig - C Traps and Pitfalls.

Hatton and Koenig were in turn major influences when the automotive industry rolled out the first professional safe subset of C in 1998, called MISRA C. This coding standard has since then been refined and revised multiple times and among many things, it contains advise about what constructs to avoid in terms of "spaghetti programming".

MISRA C summarizes most conclusions about which things to avoid:

  • goto should be avoided but can be safely used if only for jumping downwards, for the sole purpose of an "on error goto" error handler/cleanup at the end of the function.

  • Multiple return should be avoided just because having them from deeply nested loops etc is unreadable and easy to miss.

    Personally I don't think it is a problem to have multiple returns as long as they aren't done from inside deeply nested compound statements - in fact multiple returns can be used to avoid such.

  • There should only be a single break statement inside loops.

  • MISRA makes no mentioning of continue.

    My very personal opinion is that it should always be avoided just like goto, since continue is almost always an indication of a loop which could be written in a better and more readable way.

If adhering to the above advise, the most severe forms of spaghetti programming is prevented.

Even better, generally well-recognized advise:

  • Always keep functions small.
  • Avoid deeply nested compound statements, for example by splitting a function in several or by removing an inner compound statement/loop with a function call.

So should we indent break as you suggest? If following all the above best practices, then this trick becomes quite useless. The only reason why you'd need to make break stand out is when you've made a mess of your whole program, creating needlessly complex compound statements or far too big functions. The solution then is not to indent break differently, but to rewrite the code into something more readable/maintainable.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    `continue` has its uses. For example, when processing a text file like a properties file `continue` is very useful when a comment or empty line is encountered. That's a significant improvement over having to carry an extra level of indentation over the entirety of the rest of the loop where all the real work is done. – Andrew Henle Mar 29 '23 at 12:06
  • 2
    @AndrewHenle As always when this comes up, I challenge you to post the code and I bet that I can find a more readable way to write the loop without continue. – Lundin Mar 29 '23 at 12:58