a reply-to-all on the rationale of the COMP1511 style guide, following the release of assessment style marks
written 2017-10-24
Fair enough for penalising multiple returns as it’s been chosen as good style, but I really think that should be changed for next year. It was quite acceptable where I worked and seems to be accepted industry practice to use multiple returns when it makes things clearer to read/write (c.f. stackoverflow:36707).
The main philosophy that guides both the style guide and our approach to teaching is that this course isn’t about C or syntax, but about skills in problem solving and abstraction, which you can apply in any language.
To that end, we deliberately and explicitly restrict the subset of the language you’re allowed to use, to make it faster and easier to learn, and easier to debug and reason about. As a general rule, a function’s control flow should be easy to trace from top to bottom, and shouldn’t simply disappear in the middle; with short, clear functions that capture one idea, this becomes really straightforward, and usually obviates the need for multiple returns.
Mechanisms like assert(3)
and err(3)
give us a way to handle
invariant violations (things we know to be true under all circumstances)
or exceptional circumstances (things we know might go wrong) without
adding complexity to control flow.
I have strong objections to many of the top-voted answers on that StackOverflow post, beyond those raised by observing our style guide. Stripping away the words, the core points that come out are design decisions and error handling:
-
“error handling is a mess if we restrict code paths”: yes, it is, which is why we’ve subtly tweaked the original CSE C style guide to allow early return or early exit in the case of failure;
-
“our code looks awful anyway; multiple returns make it clearer”: that suggests your code has a deeper problem, one that can only superficially be solved by throwing multiple returns at it.
The third answer, in particular, is a mess, which has deliberately been written that way “for clarity” because of language misfeatures. You could easily structure your logic to circumvent that mess.
By choosing to structure your code intelligently and deliberately, you can easily minimise concerns about poor design.
One concern that was only raised several answers down is that C, unlike the other languages shown, requires explicit resource management: all languages illustrated in that post, which looked to be C++, C#, and PHP, have mechanisms for implicit resource management (in C# and PHP, run-time memory management via reference counting or garbage collection; in C++, the RAII pattern). You can simply drop heap-allocated objects on the floor, and count on their cleanup.
In a typical C code-base, that’s terrible practice. Often, there’s even an explicit requirement to not leak resources. In our operating systems course, for example, you work in C in an environment where a slow leak of memory will kill your assignments (and your marks); that isn’t an unusual circumstance for a C code-base. Many of our students will take these skills into embedded systems development, where an early return bypassing some resource management could crash your car, aircraft, or pacemaker.