You should almost always use the equivalent of “break” to exit a loop. Actually you should almost always exit via the loop condition, and if that’s sufficiently inconvenient then use break. Goto is for “break glass in case of emergency” use only. It isn’t never. But you should take a moment to consider it. Multiply nested loops? Sure, go for it… but think about whether those loops were a good idea in the first place.
I find goto aesthetically unpleasing, but I can see a few instances where it could be the simplest approach. Like, if a looped process fails in mid run, you can jump past the trailing code to the fault handler. Being able to use named targets would allow you to reduce your comment load, e.g., goto itFaulted. But mostly I prefer code that expresses its structure with { scopings } , not because it is better or more readable but just because I like it.
One common use is when you have a series of statements to initialize some process, but there are a bunch of failure points and you want some common path to clean things up. Sometimes exception handling is appropriate–throw an exception on failure and perform the cleanup in the exception handler. But that’s not always available (like in C, or certain environments that don’t support it), plus the exception has a different scope block than the rest and doesn’t have everything available to it. Just doing a goto to some cleanup code is relatively clean and readable.
Perl actually supports labels on its “last” (break) keyword. So you can jump out of deeply nested loops. But as you say, the targets are still limited. You can’t jump just anywhere as with goto. It has to be one of the loops you’re inside.
Except that the schoolmarm-type dictum against “GO TO” goes way, way back before newfangled languages that supported “break” type statements ever existed. If certain purists had had their way, it would have been removed from FORTRAN IV!
I’m not arguing that “break” isn’t superior, when available. My major argument is that the minutiae of code structure within a module is far, far less significant than the structured organization of thousands of such modules within a large software system where maintainability and reliability are crucial. I’ve always looked down on “structured programming” as technological pedantry.
Well, Dijkstra’s “Go to statement considered harmful” is certainly the grandfather of all anti-goto sentiment. The fact that not all languages support the required constructs to eliminate goto use was part of his point.
In fact he mentioned “abortion clauses” (i.e., the break/continue we’ve been talking about) as an example of just that sort of thing:
Eh, I’m sure Dijkstra was a fine fellow and made important contributions to the art of programming. I once attended a small seminar to hear him speak. I wasn’t particularly impressed although one of my colleagues at the time went up to have him autograph whatever his latest book was.
Structured programming is obviously a Good Thing™. Readability and code review matters a lot in assuring reliability in special cases like spacecraft and avionics. But in the general case, the reliability and maintainability of large software systems has much more to do with a coherent overall architecture defining the structure of thousands of software modules than with the elegance of the code within any one of them. I’m more impressed by people like Glenford Myers, author of Software Reliability: Principles and Practices than I am by advocates of how to write really spiffy code.
A fantastic design can be rendered both unreliable and unmaintainable by a shitty cadre of devs led by clueless managers.
You’re certainly right that moronic architecture or stupid design can make everything else at a lower level almost irrelevant as to quality, performance, or maintainability.
But great design shoddily implemented is … simply a shoddy outcome.
Sure, that’s like arguing that the best car design in the world is no good if the brakes fall off as soon as you leave the lot. There have to be certain baseline assumptions.
The job of software architect and project manager are closely intertwined and are often the same person (i.e.- me). What I’m saying is that I never much cared what anyone’s code looked like* as long as the product was successfully unit tested seven ways to Sunday, then integration tested a hundred ways to Sunday, then tested again two hundred ways to Sunday, and never failed. If it turned out to be shitty code that happened to work well but wasn’t easily maintainable, it could just be thrown out later and rewritten – which is one of the major strengths of a coherent architecture with well-defined interfaces.
* I was especially amused by Elon Musk demanding that IT staff send him samples of their code so he could assess how valuable they were to the company and whether or not they should be fired. This was more or less the point where I was convinced the man was an idiot, before he went ahead and proved it beyond any shadow of a doubt.
The trap was being so allergic to the use of gotos that you wrote yourself into knots avoiding them. Having taught students to implement loop exits with branches in assembler, this wasn’t a problem for me.
Some of the professors were suspicious of structured programming (which was still new) and wanted to catch the fanatics.
In HS, I learned on HP2000 BASIC, which was an awful language that used numbering for every line (which I guess would be helpful if you accidentally dumped your card stack on the floor, since all the lines are entered by number) and branches had to use line numbers as there were no labels. It was trivially easy to create a while loop using an if/then statement (the only loop construct was for/next) but it was also way too easy to cook up the spaghetti.
So, my profound dislike of branching statements arises to aversion to my early learning tool, rather like an ex-addict can form a strong aversion to the object of their adkiction.
Yes, and it’ll be just as shitty the next time if your programmers are incompetent and care nothing for craftsmanship.
Anyone that’s actually programmed for any length of time can detect shitty code. It has a scent. People that care about writing good code also care about good architecture.
And it’s not just the code as such. It’s the comments, and the way it’s organized into functions and files, and the naming conventions, and a bunch of other subtle factors that are hard to articulate. But you can see it immediately if you look at well-regarded open source like Quake 3 or the Linux kernel. You don’t have to understand the whole architecture to be confident that whoever wrote it cared about craftsmanship.
It’s no different than normal architecture. It just doesn’t happen that the doors are poorly fitted and there are supports in bizarre places and everything is kinda falling apart, while at the same time the fundamental architecture is good. People that care about the architecture also care about the details.
FWIW, I’ve been programming professionally for 20+ years (so soundly post-goto-considered-harmful) and I have yet to encounter a situation where having a goto would help, nor have I seen a peer encounter such a situation. It seems to be well below the “not ideal but sometimes useful” level to “never necessary ever”. No one is tying themselves in knots to avoid a GOTO these days.
The “not ideal but sometimes useful” statements are “break” and “continue”. Most of the time when you’re using those, you could factor the loop or the body of the loop into its own function and use “return” instead (and then it can be property unit tested).
The “break” and “continue” statements are for those rare cases where the loop body logic is complicated enough to finish early conditionally, but not so complicated that you’d want to give it its own name/unit tests.
There is no reason to use a GOTO directly in code. If you don’t have a BREAK statement make one with a macro or your own preprocessor. Do that in assembler too. There’s no need to code a JMP instruction to a direct address. Make your assembler or compiler do that dirty job. You have no excuse for hardcoding direct branches. Period.
Well, this was in 1976 or so. In my 36 year career I never used one, because I was using languages with some sort of loop exit statement. The microprogramming language I designed for my dissertation was Pascal-based but had a loop exit statement added.
I’d like to know WTF else software engineers are supposed to do. What is Google doing, paying software engineers to make chopped liver? I’m sure the author’s gonna pull a swerve and try to say software engineers at Google are designing and implementing something that is not a large-scale computing system even though every single thing Google does or has is a part of a large-scale computing system.