8 ms·
I really don't see how enforcing {} syntax on all conditionals is going to make us so much safer. Yes, people make mistakes, but this is a pretty huge screw-up
by byuu 13y ago
I really don't see how enforcing {} syntax on all conditionals is going to make us so much safer.
Yes, people make mistakes, but this is a pretty huge screw-up. If you are modifying an unbraced if-statement and aren't paying attention to scoping, then you are being woefully negligent at your job. Especially when you are working on cryptographic code used by millions of people to protect their most valuable information.
So let's say we force more red tape to make sure this doesn't happen. Those of us who pay attention to scoping probably won't mind too much, it's good practice to do this anyway.
But what about the mediocre programmer? He may decide that now his if/else if/else three-liner, when adding new lines for {}, should really just turn into a switch/case. And now he neglects a fall-through case, or adds an unconditional break; before important code. And we're right back where we started.
It doesn't matter how much we safeguard and dumb down languages. We can load our languages full of red-tape: extra braces, no jumping or breaking, no fall-throughs, always requiring explicit conversions, no pointers, no null types ... all we'll end up with is code that is much harder to read (and possibly write), while the mediocre programmers will find new and inventive ways to screw things up. It's just as likely to make them even more lax, and attract even less disciplined programmers into important development roles. You know, since it's presumed to be so much safer now.
The real problem is the amount of poor programmers out there, and the lack of repercussions for these sorts of things. A doctor that leaves a scalpel in a patient is (rightly) ruined for negligence. Do you think the "goto fail;" writer even received a written warning? Why not?
I'm not saying people can't make mistakes, but I think your pay scale and the importance of what you do should come with some actual responsibility for your errors. Just like in every other profession out there.
Yes, sometimes you can blame the tool. But there are also times when you need to blame the user.
- tonysuper 13y agoIt should be noted that this might not have been a coder error, but a merge conflict. Nobody should be reprimanded in that case, since it's nobody's fault (except whoever decided to not test or lint this file, but he should have been punished for negligence even if it hadn't caused a bug.)
- jobu 13y agoThis is exactly what I thought when I first saw the Apple bug, and I was surprised that the author didn't mention this at all. He's blaming the programming language here, but I have yet to see a language where a single line accidentally duplicated or transposed by a merge tool couldn't cause the same problem.
- wpaprocki 13y agoWell, in Python, if you duplicate a return statement, then your code will recognize only the first statement. This, for example, will return 1: def func(): return 1 return 2 If the code from the goto fail example was written in Python so as to return an object when a condition was met, and it ended up with 2 return statements, then Python would have just returned the first one in the proper scope and moved on. Of course, this still depends on implementation in the code itself.
- eyeface 13y agoIf we're talking about returns, then C/C++ would behave the same way. The second return is unreachable. A duplicated line that isn't idempotent and that doesn't jump out of the current scope would be problematic.
- peterashford 13y agoJava (if it had gotos) would not have compiled this code because it doesn't allow unreachable code.
- jobu 13y agoIn the Apple SSL bug, a goto statement works much like a function call or a throw in Java. Here's a Java example that compiles without warning and has the same flaw: public static void foo() throws Exception { throw new Exception(); } public static int bar() throws Exception { int x = 0; if(x == 1) foo(); foo(); x++; return x; }
- nawitus 13y agoAre you making the claim that language design has no effect on the number of bugs? That JSLint (for example) doesn't really reduce the number of bugs? If you're not saying that, then presumably JSLint / language design does reduce bugs, which is probably the main claim the article. Nobody is saying that enforcing {} syntax etc. removes all, or even most bugs, but it removes a non-trivial amount of bugs while not making code particularly harder to read imo.
- byuu 13y agoNo, I'm more claiming that there's too much eagerness to blame ones tools. And that's very dangerous to me, because they blunt my tools in the name of safety. So you have these advocates coming in, saying we should stop using goto, stop using pointers, stop allowing implicit type conversion, not allow return statements anywhere but the end of the function, rely only on garbage collection, and so on. I end up needing to jump through hoops in order to safeguard an amateur that doesn't know what he's doing. This Apple bug was a failure on many levels. This was one of the most beginner-level bugs imaginable, on one of the most important libraries imaginable. Where was the programmer accountability? Where was the internal review process for this change? Where was the static code analysis to catch this block of unreachable code? Where was the security auditing suite to make sure the library was functioning as intended? Where was the corporate accountability? Blaming the tool for being sharp, to me, sounds like passing the blame entirely. The {} enforcement is, solely by itself, very benign. It doesn't remove any language functionality or expressiveness, and it's a good thing to do anyway. Aside from requiring us to go back and patch up decades of old code, it's in a very rare category of easy wins. From it, you could easily say the same about always explicitly casting everything, so that there are no surprises. And put all your literals on the left-hand side, in case someone forgets an extra =. if(!x) a = b * c + d; if(0u == x) { a = reinterpret_cast<int>(b) * c + reinterpret_cast<int>(d); } The code does exactly the same thing, yet the latter is going to have a real toll on code readability. My 1080p monitor is going to see a few less lines of code at once. I'm going to have to scroll a bit more. I'll have to filter out a few casts, flip a few compares in my head. But it adds up. Yet what I'm most afraid of, is that I'm very hard-pressed to think of safety changes to C that won't remove any functionality, aside from the aforementioned. In fact, I start seeing odd things creep up, like Clang warning when switching on a boolean value. It apparently catches some odd mistake some guy made at some point. It was thought that nobody would ever switch on a boolean. Except that I did. (see my post history here if you want details on that.) I'm getting a bit tired of being grouped in with programmers like the goto fail guy. Sure I'm not perfect, but I'm also not making these kinds of trivial mistakes. I am not eager to go through hundreds of thousands of lines of code to add these changes.
- ericHosick 13y agoProcess is not immune to entropy. It is very difficult to assure that even experts don't make mistakes: especially when they are running through the same process again and again. They will, at some point, always make a mistake. Even the worlds most competent doctor is at risk of leaving a scalpel in a patient. It is possible to lower the risk of such an event occurring which is why we push for best known practices (like enforcing {} syntax on all conditionals (I do), regression testing, etc.) and bodies of knowledge.
- deleted 13y ago[deleted]
- usefulcat 13y agoNo one's claiming that requiring braces on conditionals is any kind of silver bullet. The Apple bug is just a concrete example of how a different language design decision (requiring braces) could have avoided this particular bug. The fact that bugs can also be introduced via an erroneously designed switch statement is a red herring. And I also don't think anyone is claiming that the skill of the developers doesn't matter; of course it does. But the fact that no single change to any one part of the process (tools, developers, methodology, etc.) can prevent all bugs does not in any way negate the value of improving any one of those parts.
- brianberns 13y ago> The Apple bug is just a concrete example of how a different language design decision (requiring braces) could have avoided this particular bug. I don't see how requiring braces would have necessarily avoided the Apple bug. Whoever was responsible for creating the extra "goto fail" might still have left it outside the scope of an if-statement. if (error_of_first_kind) { goto fail; } if (error_of_second_kind) { goto fail; } if (error_of_third_kind) { goto fail; } if (error_of_fourth_kind) { goto fail; } if (error_of_fifth_kind) { goto fail; } { goto fail; } if (error_of_sixth_kind) { goto fail; } The_truly_important_code_handling_non_erroneous_case It all depends on how the extra line got there in the first place. Presumably there was a mistake made while editing the file. Braces don't necessarily eliminate those kinds of problems.
- DatBear 13y agoWho on earth would ever format code like that?
- SoftwareMaven 13y agoAssuming this is "C with required conditional braces", this would exhibit the same behavior as the original bug. Introducing a new scope with {} is valid (and regularly used) C. The problem here is that, visually, this class of error doesn't stand out, because, when you scan the code, it just looks ok (albeit, ever so slightly less right in your example). And that brings us back to language design. It's hard to have this type of bug and not bring up Python as an example, because Python behaves as your eye processes it. if error_of_fifth_kind: goto fail goto fail Those two gotos are in the same block, because they are indented the same. People continue to freak out over significant spacing, but there is a lot of value in it.
- stiff 13y agoThis is not an argument, just an attractive narrative for what boils down to a rejection of the possiblity of a better programming language reducing bug rates without negative side effects outweighing the benefits - I don't think you would find much agreement if you just stated your point explicitly, instead of painting a dystopian red tape programming language future... And you are obviously wrong, as proven by all the programmers today who don't even know what a buffer overflow is anymore, because a higher level language takes care of that for them once and for all.
- byuu 13y agoA dead code analyzer would be even more effective than making a non-backward-compatible change in a 40-year old language. I'm not convinced enforced {} is such a compelling advantage, just because of one company's screw up. I'm not convinced they wouldn't have screwed it up in a different way, like putting the second goto outside of the brace scope entirely. I'm not radically opposed to enforced {}, I am simply tired of developers blaming only their tools and never themselves. > And you are obviously wrong, as proven by all the programmers today who don't even know what a buffer overflow is anymore, because a higher level language takes care of that for them once and for all. Red tape decreases code readability to safeguard against basic due diligence. It is a burden to the developer on reading and working with the code. Forced array bounds checking and garbage collection sacrifice significant performance to protect even further. It is a burden on scalability and battery life to the user. It some cases, it has the potential to reduce code verbosity. And now we have new classes of bugs with dynamic type systems, with duck typing, with run-time errors, with not having to declare variables prior to use, with null pointer exceptions, with garbage collector stalls in real-time applications, and so forth. No language is ever going to be perfect. (Again, this is not me saying, "let's not try and make safer languages", that's not my point at all. My point is that you also have to encourage better diligence.) It certainly serves a place for rapid application development, for hiring lower-paid and less-skilled developers (which is not a bad thing), and for working on applications that don't demand performance. And yet performance still matters to many developers. For all of Java's professed safety, it's still below usage of C. And far below usage of the C family (C, C++, Obj-C.) It's still the #1 choice for operating system design, high-performance libraries, simulation, web servers, database engines, video codecs, and major studio games, among many other things.
- macspoofing 13y ago>If you are modifying an unbraced if-statement and aren't paying attention to scoping, then you are being woefully negligent at your job. No. Brains model the world based on sampled data from the senses. This internal model will frequently deviate from the real world so mistakes are inevitable. However, you can design programming languages and programming constructs in a way that makes brains either more or less susceptible to these kinds of mistakes. For example, if your programming language doesn't allow these types of compound statements, than the human brain will never make that kind of mistake. I'm primarily programming in Java and JavaScript and I've learned to just put braces around every statement that warrants one. I got burned once or twice and I prefer the peace of mind that comes with removing an entire class of bugs at the cost of two extra characters.
- konstruktor 13y agoRuined for negligence - medieval thinking combined with the US legal system. Like that's going to help the patient whose body the scalpel was forgotten in. But I like your example. Because in a well organised OR, the doctor cannot leave a scalpel inside the patient all by herself. The nurse would have to fail to properly count the instruments at the same time. BTW: all non-metallic objects have embedded pieces of metal that will show up on X-ray, so errors can at least be detected. Do they let plumbers operate on patients because it's now much safer? Not where I live, the laws are pretty strict with respect to who can practice medicine. If you want safety, stop thinking in terms of blame and vengeance and design systems that avoid errors, and reduce their impact if they occur. This includes culture, processes and tools to protect against errors by those who do the work, and some regulation to stop management from putting employees in situations where they are likely to cause harm. Those measures have made aviation safe, and medicine is catching up. Time for the software industry to mature.
- DatBear 13y ago>Do they let plumbers operate on patients because it's now much safer? Not where I live, the laws are pretty strict with respect to who can practice medicine. But there aren't laws that determine who can program... >If you want safety, stop thinking in terms of blame and vengeance and design systems that avoid errors, and reduce their impact if they occur. This includes culture, processes and tools to protect against errors by those who do the work, and some regulation to stop management from putting employees in situations where they are likely to cause harm. There obviously already are systems that are designed to avoid errors... Unit testing, static code analysis, automatic formatting, etc. The author of the article said to throw all those out and put all of the safeguards into the language spec. OP is just saying that they don't belong there.
- sanderjd 13y agoGreat comment! I agree with you, but a counterpoint is that punishment is one facet of the error-avoidance system design, based on the logic that people are more careful if they fear punishment. I think punishment is often overemphasized, but not completely worthless (as you seemed to, but perhaps didn't mean to, imply).
- 13y ago
- lutorm 13y agoThe NTSB got rid of this thinking a long time ago when it comes to aviation accidents. If you think someone is "woefully negligent at their job" for modifying an unbraced if statement, how about pilots who fly their airliner into the ground? Yet aviation accident investigations focus not on blaming people who erred, but on how to avoid them knowing that humans make mistakes. Instead of focusing on making ourselves feel better by talking about "a few bad apples" if we really want to avoiding things going bad in the future, we need to work with human behavior instead of against it.
- eldavido 13y agoSometimes it really is a few bad apples, though -- it's a delicate balance. Somewhere between "the pilot got onto the plane, intoxicated, and proceeded to fly it across the country" and "a major, unforeseeable control outage led to a midair collision between two aircraft following normal procedures", there exists a reasonably competent, responsible person, capable of performing their job duties as expected. The key is being reasonable in what we expect from people. We can't all be superheroes, but people aren't mechanical robots with the wits of children, either.
- lutorm 13y agoI never meant to say there's no such thing as negligence. Of course there is. But it's also true that the threat of punishment works poorly as a deterrent also in that case, because if you think you can get away with flying the plane intoxicated, you likely also think you won't get caught. And the same processes that catch honest mistakes also work to catch less innocent ones.
- groby_b 13y agoBut here's the thing - you don't weed out the bad apples by drastic punishment alone. You weed them out by designing your processes so they get tripped up, and then simply eject them from the profession. And it's not the bad apples that are the problem. You spot a drunk captain easily. It's the mistakes that are the problem. The worst aircraft accident in history? Caused by one of the most experienced and responsible pilots in the industry. As a result of a large chain of failures along the way. And these kind of problems are fixed by systematic change, not by punishment. Tenerife (the accident mentioned above) led to a whole slew of regulation changes. It led to an entirely new approach to leadership and decision making - crew resource management. And that's what's keeping the airline industry a fairly safe business, not just imposing penalties. It has nothing to do with "having the wits of children". It has everything to do with accepting that we all make mistakes. Sometimes silly ones. And that we need to put systems in place to prevent them before they happen.
- Dn_Ab 13y agoTo the contrary, your list smartens the languages up. Your list describes a typical functional programming language, and I certainly would not say most such users are mediocre: 'extra braces (or no braces in favor of white space), no jumping or breaking (since everything is an expression), no fall-throughs (pattern matching is much more powerful than clumsy switches), always requiring explicit conversions (type correctness is worth it), no pointers, no null types (Option types are better) ...' The resulting code is very easy to write and read, although you must approach learning them with an empty cup. Extra railings like contracts, contracts + prover, refinement types and dependent types enforce vigilance in ascending order of brutality. They do not leave room to be lax. Programming languages are meant to counter the limits or deficiencies of human working memory and focus. Better languages aren't profitless trades, the cost of learning and using them must be less than the attendant rewards + cost of not using them. Also, speaking of Doctors and attacking working memory constraints, checklists have been show to significantly reduce complications in surgeries. Type systems and good language design fall in the same category of aiding one in focusing on the bigger picture by alleviating WM of trivialities.
- danans 13y agoWhy not just eliminate the sources of common errors altogether (by enforcing {}, per your example), especially when it can be done with a style-checking tool that runs automatically at build time? The only reason to punish the programmer then would be if they blatantly ignore the style error. You could even do away with the punishment by making passing the style check a condition of code submission. Similarly, I'm sure there are many examples in medicine where a source of errors was eliminated completely by just using a better tool for the job, though I can't think of any at the moment. Edit: wording.
- icambron 13y agoI don't agree with almost any of this. To begin with, I think the reason you don't see this as a real language problem is because of status quo bias. Here's one way to think about it: your compiler (or interpreter or on-the-fly-IDE-underliner-thing) catches all sorts of syntax mistakes you make. You depend on that. But what if I pulled that all out from under you? Your compiler no longer checks that your function returns the type of thing it says it does in every case and your program just breaks horribly when it doesn't. What a terribly stupid thing for your language not to help you with! Well, as you'd say, you just need to be more vigilant, and it's a sign of mediocrity when a developer screws that up. We can extend that to literally every error-mitigation tool we have. In other words, just because you've steeled yourself against this class of error out of practical necessity doesn't mean it's a good idea to leave it around. From the other direction, look at Haskell. I'm not a Haskell programmer, but my understanding is that its type system and pure functions eliminate entire classes of errors and makes reasoning about the behavior of your program easier. That's not programmers being lazy or incompetent. They want their tools to do more thinking for them so they can tackle higher-level problems their tools can't, rather than spending their cycles ritualistically ensuring they haven't made basic screwups, which humans are intrinsically bad at anyway. People certainly aren't attracted to that safety net because they lack the discipline and rigor for the rough-and-ready world of C. Sheesh. There are all kinds of tradeoffs that go into language safety (and you mentioned one-- forcing {} for one-liners makes the code longer and potentially harder to read), but making your language less safe for the express purpose of making it less safe is just crazy. That's what you're doing when you keep around gotchas to keep out the noobs. Don't be the guy who thinks shaving with a straight razor makes him a real man. To push that further, if your measure of the quality of a programmer is how careful they are with syntax gotchas, I submit that you're doing it wrong. "Look at this beautifully designed, simple, elegant, fault-tolerant, highly maintainable module our new developer wrote! Oh, but she used an uncommented fallthrough. Fire her!" Being vigilant about little gotchas like this is, I suspect, uncorrelated with all the rest of the stuff you want in a programmer. That her module might be bad in spite of all that points exactly at the tools. If we fix the tools, now her code is awesome, but maybe you won't be able to lord your awesome never-mess-up-braces skills over her. It's especially interesting that you brought up doctors. Because doctors make mistakes all the time (they only get sued for negligence, which isn't just any mistake with nasty consequences). To help with that, they've been steadily improving their tools: EMRs, protocols, checklists, decision trees, standardized equipment layouts, and so on. And it's really changed medicine. So I don't believe the dichotomy you've set up is right. As applied to the "goto fail" bug, my guess is that the programmer who did it may well have been good, and just made the equivalent of a line-long typo. (Or maybe it was a merge error?) And next time you discover a baffling bug that, in the final analysis, should have been really obvious, I hope your peers cut you more slack then you cut this person.
- groby_b 13y agoThe answer is not "screw the safeguards, I know what I'm doing". The answer is language that a) doesn't have different ways to do the same thing. (I.e. if with either a single statement or a compound statements) b) Doesn't do things implicitly. I.e. if you want to fall through, you have to indicate that. If you want to break, you have to indicate that, too. The idea of saying "it's only mediocre people" is nice, because it implies we're not mediocre. It's also wrong, because everybody makes mistakes. You want to prevent mistakes from being made in the first place, independent of skill level. That's why doctors have adopted checklists, for example. They certainly know all the things on there. And 99.99% of the time, they do just what's on the checklist. But that one time when you're tired, and you forget one tiny step that can have catastrophic consequences, that checklist saves your bacon. Unambiguity in your language is nothing but a syntactically enforced checklist. After-the-fact punishment doesn't really help as much as you'd like to think. It merely leads to expending energy on cover-ups instead of making sure the mistake never happens again.