What about bugs that arise not from a fundamental misunderstanding of the sort you’re referring to, but from some sort of typo or language-specific error that you’d never think of as correct if only you’d noticed? These are more frequent, more annoying because they can come up even in simple tasks, and take just about as long to debug.
I realize that this sort of bug isn’t interesting to write about, but you ignore this case completely when stating your ‘fundamental law of software’.
I think it’s covered: the programmer has a mental model of the what the code does (say, drawing a triangle on the screen) that does not match what the code actually does (completely fail to start up due to a syntax error). I agree that this isn’t really all that great a way of describing those sorts of bugs or how to fix them, but it is at least included in the law.
Misunderstanding doesn’t need to be “fundamental”, the Nature is still the law, even if the law is stupid. Annoying detail that failed to be noticed is still a flaw in your map.
When the law needs interpretation like this to be valid, it is not more interesting, insightful, or useful than saying:
The lack of have a program that flawlessly achieves objective X, is the result of the programmer’s map not accurately representing the fact in the territory that typing a certain sequence of characters and compiling would produce such a program.
A more interesting, less fundamental law, would be that:
A large class of “bugs” or defects in software is the result of a mismatch between a person’s assumptions, beliefs or mental model of the problem domain (a.k.a. “the map”), and the reality of the corresponding situation (a.k.a. “the territory”).
The map-territory metaphor applies to the actual program (or even a specific test case) and your understanding of the actual program (test case), not hypothetical program that would solve the informally-specified problem if it was available.
Note that the change I recommend as an improvement does narrow down which territory the law refers to. The problem with the original is that it doesn’t actually specify anything like what you said.
It doesn’t feel very fundamental. How commonly they crop up, and how easy they are to debug have much to do with your editor, coding style and interpreter/compiler.
the use of long’ish descriptive identifiers makes it less likely that single typos collide with other valid names, while text-completion largely eliminates single-character typos as a class of error.
syntax highlighting provides a useful form of spell-checking
consistent formatting makes it difficult to accidentally hide ‘structural typos’, especially given editor support (mainly brace matching).
These sorts of concerns are very amenable to technical solutions, which are commonly implemented to various degrees. But even if they were completely eliminated, programming wouldn’t be that much easier. My boss would still be making fun of me for staring off into space for long stretches while I’m thinking through a problem.
This is exactly analogous to typos vs defects of argument in prose. Yes, spell-checking will miss typos that collide with valid words, but it feels off to claim this as a deep insight into the nature of writing.
A typo is when you think you have written down X, but actually you have written down Y. Are we not squarely in a map-territory discrepancy?
And, speaking from personal experience, those can be very painful to debug, because right until the very moment of realization you are prepared to swear that the problem must be something very subtle, since quite obviously you wrote down what you meant to write down.
If you’re lucky, and work in a statically typed language, the compiler will catch typos for you. Lucky because the typo has to be a) in an identifier (the compiler doesn’t check strings or integer values), b) such that it results in an undefined identifier (you could have a typo which turns one defined identifier into another defined identifier) or c) in an identifier of the wrong type.
I don’t know what you mean by a language-specific error, what I can come up with is also a map-territory discrepancy: you think that the array accessing convention is 1-based when in fact it is 0-based.
The more down-to-earth formulation is “every bug is in fact a programmer mistake”.
It’s almost not worth mentioning… but my experience in a different domain says otherwise. Namely the game of Go: one of the first, most basic rules you learn in Go is “players alternate play”. Or, to say it another way, “you ain’t going to get to play two moves in a row”. Every player is supposed to know this… and yet I have seen one strong player totally humiliate others by pointing out that they played exactly as if they hoped to get two moves in succession.
Every bug is in fact a programmer mistake, and everyone knows this… but why does everyone behave as if they thought different?
If we’re thinking about programming as a way of deeply understanding a problem—or at least as a process which leads to understanding a problem as a necessary step—then we have these errors that don’t reflect a misunderstanding of the problem. They may reflect a misunderstanding of the language, or a typo, which I realize are still map-territory discrepancies (isn’t any mistake?) but have nothing to do with the problem you’re trying to solve.
In a way, I suppose I’m nitpicking. But it also needs to be said because when debugging, you need to be aware of two levels of differences: differences between what the correct solution is and what you think it is, and differences between what the program does and what you think it does.
This comes up a lot when I’m grading mathematical proofs. Sometimes the mistake is a faulty step: for instance, an assumption of something that shouldn’t be assumed, or maybe only a partial solution is found. Sometimes, the mistake is in the presentation: the idea of the proof matches the correct idea, but a key step is unexplained, or a final answer is wrong due to an error in arithmetic. I think it definitely matters which kind of error the students are making.
The big difference between a typo in writing and a typo in code is that in the first case the hardware that does the interpretation transparently covers up the mistake (which is why editing is a hard job, btw). In the second case the consequences can be more severe, are likely to crop up later and inconvenience more people. Code is unforgiving.
As a case study we could consider the latest “bug” to have a noticeable effect on LW. Someone released this code into production believing that it worked, which turned out to be very different from the reality.
What about bugs that arise not from a fundamental misunderstanding of the sort you’re referring to, but from some sort of typo or language-specific error that you’d never think of as correct if only you’d noticed? These are more frequent, more annoying because they can come up even in simple tasks, and take just about as long to debug.
I realize that this sort of bug isn’t interesting to write about, but you ignore this case completely when stating your ‘fundamental law of software’.
I think it’s covered: the programmer has a mental model of the what the code does (say, drawing a triangle on the screen) that does not match what the code actually does (completely fail to start up due to a syntax error). I agree that this isn’t really all that great a way of describing those sorts of bugs or how to fix them, but it is at least included in the law.
Misunderstanding doesn’t need to be “fundamental”, the Nature is still the law, even if the law is stupid. Annoying detail that failed to be noticed is still a flaw in your map.
When the law needs interpretation like this to be valid, it is not more interesting, insightful, or useful than saying:
A more interesting, less fundamental law, would be that:
The map-territory metaphor applies to the actual program (or even a specific test case) and your understanding of the actual program (test case), not hypothetical program that would solve the informally-specified problem if it was available.
Note that the change I recommend as an improvement does narrow down which territory the law refers to. The problem with the original is that it doesn’t actually specify anything like what you said.
It doesn’t feel very fundamental. How commonly they crop up, and how easy they are to debug have much to do with your editor, coding style and interpreter/compiler.
the use of long’ish descriptive identifiers makes it less likely that single typos collide with other valid names, while text-completion largely eliminates single-character typos as a class of error.
syntax highlighting provides a useful form of spell-checking
consistent formatting makes it difficult to accidentally hide ‘structural typos’, especially given editor support (mainly brace matching).
These sorts of concerns are very amenable to technical solutions, which are commonly implemented to various degrees. But even if they were completely eliminated, programming wouldn’t be that much easier. My boss would still be making fun of me for staring off into space for long stretches while I’m thinking through a problem.
This is exactly analogous to typos vs defects of argument in prose. Yes, spell-checking will miss typos that collide with valid words, but it feels off to claim this as a deep insight into the nature of writing.
A typo is when you think you have written down X, but actually you have written down Y. Are we not squarely in a map-territory discrepancy?
And, speaking from personal experience, those can be very painful to debug, because right until the very moment of realization you are prepared to swear that the problem must be something very subtle, since quite obviously you wrote down what you meant to write down.
If you’re lucky, and work in a statically typed language, the compiler will catch typos for you. Lucky because the typo has to be a) in an identifier (the compiler doesn’t check strings or integer values), b) such that it results in an undefined identifier (you could have a typo which turns one defined identifier into another defined identifier) or c) in an identifier of the wrong type.
I don’t know what you mean by a language-specific error, what I can come up with is also a map-territory discrepancy: you think that the array accessing convention is 1-based when in fact it is 0-based.
The more down-to-earth formulation is “every bug is in fact a programmer mistake”.
It’s almost not worth mentioning… but my experience in a different domain says otherwise. Namely the game of Go: one of the first, most basic rules you learn in Go is “players alternate play”. Or, to say it another way, “you ain’t going to get to play two moves in a row”. Every player is supposed to know this… and yet I have seen one strong player totally humiliate others by pointing out that they played exactly as if they hoped to get two moves in succession.
Every bug is in fact a programmer mistake, and everyone knows this… but why does everyone behave as if they thought different?
If we’re thinking about programming as a way of deeply understanding a problem—or at least as a process which leads to understanding a problem as a necessary step—then we have these errors that don’t reflect a misunderstanding of the problem. They may reflect a misunderstanding of the language, or a typo, which I realize are still map-territory discrepancies (isn’t any mistake?) but have nothing to do with the problem you’re trying to solve.
In a way, I suppose I’m nitpicking. But it also needs to be said because when debugging, you need to be aware of two levels of differences: differences between what the correct solution is and what you think it is, and differences between what the program does and what you think it does.
This comes up a lot when I’m grading mathematical proofs. Sometimes the mistake is a faulty step: for instance, an assumption of something that shouldn’t be assumed, or maybe only a partial solution is found. Sometimes, the mistake is in the presentation: the idea of the proof matches the correct idea, but a key step is unexplained, or a final answer is wrong due to an error in arithmetic. I think it definitely matters which kind of error the students are making.
The big difference between a typo in writing and a typo in code is that in the first case the hardware that does the interpretation transparently covers up the mistake (which is why editing is a hard job, btw). In the second case the consequences can be more severe, are likely to crop up later and inconvenience more people. Code is unforgiving.
As a case study we could consider the latest “bug” to have a noticeable effect on LW. Someone released this code into production believing that it worked, which turned out to be very different from the reality.