This is a post about letting go of something you think you need. It starts with an illustration from programming, but it’s not about programming.
Bob Martin published a dialog yesterday about the origin of structured programming, the idea that programs should not be written with goto
statements but should use less powerful, more specialized ways to transfer control. Edsgar Dijkstra championed this idea, most famously in his letter Go-to statement considered harmful. Since then there have been countless “considered harmful” articles that humorously allude to Dijkstra’s letter.
Toward the end of the dialog, Uncle Bob’s interlocutor says “Hurray for Dijkstra” for inventing the new technology of structured programming. Uncle Bob corrects him
New Technology? No, no, you misunderstand. … He didn’t invent anything. What he did was to identify something we shouldn’t do. That’s not a technology. That’s a discipline.
Huh? I thought Structured Programming made things better.
Oh, it did. But not by giving us some new tools or technologies. It made things better by taking away a damaging tool.
The money quote is the last line above: It made things better by taking away a damaging tool.
Creating new tools gets far more attention than removing old tools. How might we be better off by letting go of a tool? When our first impulse is that we need a new technology, might we need a new discipline instead?
Few people have ever been able to convince an entire profession to let go of a tool they assumed was essential. If we’re to have any impact, most of us will need to aim much, much lower. It’s enough to improve our personal productivity and possibly that of a few peers. Maybe you personally would be better off without something that is beneficial to most people.
What are some technologies you’ve found that you’re better off not using?
Actually I have to disagree about the whole goto notoriety, and this is why:
goto isn’t special. Just like braces are low-level structural operator of a language, goto is a low-level structural *statement* of a language.
Saying that goto is harmful is equal to saying that blocks are harmful.
Instead, just like blocks – goto should be used in moderation, and where it fits, to improve readability of the code.
One very good application of goto is initialization and release of resources. Done structurally through if-else statements, it creates an entangled mess that’s nearly impossible to easily follow, precisely because its hierarchical, not linear (“declarative”), however – if one sets up a label structure so that resources are released in reverse order than the one they’re created, and uses goto to jump to correct label if resource isn’t correctly initialized – this makes for very readable code.
This pattern is used often in kernel module coding, btw.
Donald Knuth’s 1974 “Structured Programming with go to Statements” is a classic. http://dl.acm.org/citation.cfm?doid=356635.356640
I presume Uncle Bob will follow up with discussion of this paper.
Please, no more comments about goto statements. That’s not the point of the post.
To be fair to the above posters, I interpreted the comments above not as pro-goto propaganda for the sake of being pro-goto, but rather as reminders that even damaging tools can still be useful tools in the right context. Like you, they simply used goto as a showcase example. Insofar as that is the case, I think their contributions are poignant.
If you watch some of Alan Kay’s talks (https://www.youtube.com/watch?v=FvmTSpJU-Xc is one that I watched recently, which ironically also uses the “considered harmful” meme), he talks a lot about this idea. One example from this talk is that tooling based on markup languages (as opposed to WYSIWYG tools) are harmful.
Letting go of MATLAB was a painful, but fantastically freeing event.
Jamie Zawinski famously wrote: “Some people, when confronted with a problem, think ‘I know, I’ll use regular expressions.’ Now they have two problems …”
It is true that I have worked with people who try regex as a near universal answer to problems only to discover they are creating new problems because they didn’t realize something – usually needing more semantic context than you can get with regex to decide when and how to handle the needed replacements.
One might argue that multiple regression is more often misused (to imply causality) than used correctly. I certainly have knowingly abused it in the name of expediency.
I’ve found that taking away debuggers helps, especially with more inexperienced programmers. It encourages reasoning about the code, instead “programming by co-incidence.” When you see something you don’t expect, looking in a debugger and changing things until it works impairs clear thinking about why something happened.
This isn’t to say that debuggers are always bad. There are times when you need one to examine a core dump, or figure out what typo caused the failure. However, those problems should be rare. The issue here is running code in a debugger as normal development practice.
I know programming (and goto) is not the point of the post. But I can’t resist, according to Alex Stepanov a harmful tool are “virtual functions in C++”.
I guess you are thinking about null hypothesis significance testing here …?
Relatedly: “C++ Core Guidelines will Help Writing Good Modern C++”
http://www.infoq.com/news/2015/09/cpp-guidelines-stroustrup-sutter
Getting rid of my oil company credit cards (no dough, no go) was my single best financial decision.
I completely agree with you – in modern day programming, especially web, I’m seeing too much opinion on new frameworks, languages and tech. Every day a new framework comes out and the mainstream forms their opinion on it too quickly, and fail to think about the discipline side.
Java and C# both deprecated killing threads by force. Seems plainly useful at first (operation hung? kill it!), but it’s very very hard to be sure your thread’s untimely death leaves nothing in an unclean state.
Style guides often spend a lot of space on what you rarely, or never, do: the Google C++ style guide, for instance, excludes operator overloading and (for Google-specific reasons) exceptions.
In JavaScript several constructs are deprecated: eval risks security problems, using the ‘arguments’ variable can hurt performance, etc.
You can look at much of Go’s design as a set of deliberate exclusions. You can’t have circular imports, overloading of any sort, a traditional exception-handling mechanism. It prohibits oddities that are legal (or warnings) in other environments, like unused imports or variables, or converting an int64 variable to a float64. Some clever things that aren’t excluded are strongly discouraged–memorably, the official memory model documentation has a para just reading “Don’t be clever.”
The regex example above was inspiring.
“…people who try [some powerful tool] as a near universal answer to problems only to discover they are creating new problems…”
I had an instructor on obstetrics (medical school). He told us the best way to use a forceps is NOT to use it at all. Avoid it as much as possible. Use it only after you have absolutely no other way. It is so “powerful” it’s literally harmful.
Personally, the most powerfully hyped tool I have is the Dremel rotary tool. I bought expecting to use it everywhere, but surprisingly, experience and mistakes have shown that, most the time, for everything you might find an use for a Dremel, it would be best to use some other, simpler, more specific tool (usually non-powered, as sandpaper or a metal file). What I have learned is: this powerful, flexible tool should be used when needed (that is, seldom), not just when possible (almost always, but with questionable results).
The “damaging tool” that I seem to be better off without is implementation inheritance. It’s a fundamentally unsound construct, and makes programs harder to reason about.
I’m not fully weaned off it, I must confess. I still use it every now and then, but before I’m allowed to do so, I must articulate a succinct reason why, and a one-sentence explanation why other solutions are worse. My main outstanding uses are places where it interacts with C++ templates (e.g. CRTP).
@Pseudonym I think that brings up a really good point, actually. Dropping a tool (even a damaging one) cold turkey could be more harmful than good at first. As soon as you stop using it, you’ll have to find something to take its place, and you may not always pick a better tool the first time around.
“Weaning” yourself off of it would give you more time to find a suitable replacement, and even then if the replacement isn’t any better then at least you didn’t over-use an even more damaging tool.