I can't really understand the equivocating tone a lot of folks are taking in response to this, and more importantly I can't wrap my head around how you could make such a statement in the first place: without correctness you've got nothing. Stating authoritatively that correctness comes after...anything is incomprehensible to me.
It's possible to have a correct solution that is neither simple nor fast, and it can be worth your while to speed up a correct solution while sacrificing simplicity. So there are trade-offs involved in the relationship between simplicity and speed, but correctness is not negotiable. Acknowledging that all software has bugs is not the same thing as throwing out correctness as your first and primary objective in implementing an algorithm, and accepting that your solution may only be partial or fail with certain inputs is fine if that is acceptably correct for the problem at hand, but ascertaining that still comes first. Preferring simplicity over complexity because it makes debugging, profiling, etc. easier is not a reason to insist that correctness can go out the window in service to simplicity--who cares if you've removed all the bloat from your code if it's wrong?
I am reminded of this classic snark from The Elements of Programming Style (1974)[0]:
"Some compilers allow a check during execution that subscripts do not exceed array dimensions. This is a help … many programmers do not use such compilers because “They’re not efficient.” (Presumably this means that it is vital to get the wrong answers quickly.)" (Page 85)
Usually the real reason is that such checks are pointless as they do not pinpoint the bugs. They are too late. You need a real stack trace to begin debugging such issues.
Languages like Ada Spark or Rust tend to rarely use or need such runtime checks. (they are available as an option to check unsafe code)
Others like Python and Java do check and give you traces. Not for free though.
And then you probably want something more powerful, such as a virtual machine like Valgrind; full sanitization of Address Sanitizer, etc.
Suppose my manager comes to me with some incredibly complicated problem. It's going to take six months to solve properly. Suppose in the first three weeks I implement a program that is 98% correct, and let's say it can detect the other 2% and kick it out for a human to solve. But it clearly does not fully and correctly eliminate the problem as brought to me by my manager. Have I solved the problem?
The correct answer is not "no, because your solution is incorrect and there is no such thing as an 'incorrect solution' because all solutions must be correct to even be solutions; you have no professional choice but to spend the next 5 months and a week implementing the correct solution". The correct answer is "the question is underspecified". I need to go to the manager and work with them on the question of what the benefit of just deploying this is, what the benefit of doing it "correctly" according to the original specification is versus the cost, and whether or not there are any other in-between choices. The business may require the full solution, sure. On the other hand, your manager may be inclined to thank you profusely for the 98% solution in a fraction of the time because it was far more than they dreamed possible and is way more than enough to make the remaining 2% nowhere near the largest problem we have now.
"Correctness" is only fully defined in a situation where the spec is completely immutable. Specifications are almost never completely immutable. So for the most part, everyone in this conversation using the word "correct" without being very careful about what they mean are not using a well-defined word.
It's all about costs and benefits, not correctness and incorrectness. For nearly two decades, Python's sort algorithm was technically incorrect: http://envisage-project.eu/proving-android-java-and-python-s... Does this mean that any program that used Python sort was worth "nothing", because it was not correct? Obviously this is absurd (in practice at least), so correctness must be understood in terms of costs & benefits to make any sense. And such an understanding must also be grounded in an understanding of the mutability of requirements as well, to make any sense of the real world.
From this perspective, it honestly isn't even 100% clear to me what prioritizing "correctness" over everything else would even mean. That we are slaves to the first iteration of the spec that comes out, no matter what? (Obviously not, but I can't come up with anything better that it might mean.) Correctness can't be prioritized everything else because it can only be understood holistically as part of the whole process. There is no way to isolate it and hold it up as the top priority over everything else. And there is no way for the correctness of a bit of software to exceed the scope of the specification itself, almost by definition, which in the real world tends to put a pretty tight cap on how correct your software can even be in theory, honestly.
This is the most important part, and people advocating “correctness first” are missing this point.
“Simplicity first” means having a minimal skeleton code with glaring weaknesses, unimplemented features, and bugs, but having a simple design that sets you up well to absorb the inevitable shitstorm of changing priorities, pivots, revised performance constraints, feature wishlists, budget, deadlines, etc., and to manage extensibility, integration, or abstraction needs as they arrive in random, ad hoc ways.
Usually project stakeholders don’t care about absolute functional correctness, meeting performance criteria, or completeness until far far later in a project lifecycle, after those requirements have been thrashed around and whimsically changed several times.
Early on, they care about a tangible demo apparatus and solid documentation about the design and tentative plan of implementation. They want to see steady progress towards correctness & performance, but generally don’t care if intermediate work-in-progress lacks these things (often even for early releases or verson 1 of something, they’ll prioritize what bugs or missing features are OK for the sake of delivery).
In terms of interacting successfully with the business people who actually pay you and determine if your project lives on or gets scrapped, “simplicity first” is a total lifesaver, and matters far more than any of the notions of correctness discussed here.
But this is what ddellacosta is saying. I imagine his interpretation of this argument (and I agree) is that 98% correct IS prioritizing correctness. A very fast, simple solution that is 2% correct is an unacceptable balance.
"A very fast, simple solution that is 2% correct is an unacceptable balance."
That begs the question (in the original sense) of "unacceptable". If I banged out that 2% solution in an hour, and it lacked other costs that outweighed the benefits, it may still be something we ship! It is unlikely that we'd stop there, just because the numbers as you've given are unlikely to favor it because something else substantial would have to overcome the small amount of the problem we've solved, but to be firmly confident it's "unacceptable" you'd have to define "acceptable" a lot more carefully.
I understand the deep temptation to turn to discussions of the virtues of letting bugs through or something, but the costs/benefits framework completely handles that already. If you ship a buggy piece of "incorrect" shit, well, you've incurred a ton of costs with no benefits. That's wrong, by whatever standards you are measuring costs and benefits by. There isn't a "what if your 98% solution actually has a massive bug in it because you were unconcerned about 'correctness'?" argument to be made, because if it does have a massive bug, it's not a 98% solution.
But I would put $10 down that if I asked you to assert that all medical software in current use that has never killed a patient because of its software issues is therefore "correct", you'd walk back hard. You'd have to be crazy to assert that all such software is "correct".
Unless you are willing to make that assertion, you don't really mean that as a definition.
This is also an example of what I mean in my cousin message about the temptation to turn this into a discussion about attention-grabbing bugs. But my framework already encompasses that. Software that kills patients is software very high on the costs side. There's a complicated discussion to be had about how to exactly quantify probabilities of failure vs. cost, but you can't have that discussion if you're stuck in a "correct or not correct" mindset.
>But I would put $10 down that if I asked you to assert that all medical software in current use that has never killed a patient because of its software issues is therefore "correct", you'd walk back hard. You'd have to be crazy to assert that all such software is "correct".
I made no such assertion. That's a straw man.
But I think I can safely assume that if the patient dies as a result of the software's functioning, that software is not "correct".
You may disagree, but I think it's preferable to have a patient kept alive by an overly-complex system than killed by a simple, elegant, incorrectly functioning one.
Not to be intentionally blunt or snarky, but I think Drew DeVault's post was a bunch of rambling, hand-waving nonsense. Until today, I wouldn't have expected anyone to seriously argue that simplicity is more important than correctness. But he comes along and makes that very argument, with a self-assured, authoritative tone, but very little in the way of concrete reasoning, and to my surprise, the number of people on HN who apparently agree with him is non-zero.
There's a sweet spot in the neighbourhood of well-defined problems and low complexity, that sings phrases like Before even trying to implement it I know it can be done right, or Even though it can't be done 100% right, that's just the nature of the problem domain. Give the users a good enough solution that they can understand, so they can use it in the way _they_ need.
It's possible to have a correct solution that is neither simple nor fast, and it can be worth your while to speed up a correct solution while sacrificing simplicity. So there are trade-offs involved in the relationship between simplicity and speed, but correctness is not negotiable. Acknowledging that all software has bugs is not the same thing as throwing out correctness as your first and primary objective in implementing an algorithm, and accepting that your solution may only be partial or fail with certain inputs is fine if that is acceptably correct for the problem at hand, but ascertaining that still comes first. Preferring simplicity over complexity because it makes debugging, profiling, etc. easier is not a reason to insist that correctness can go out the window in service to simplicity--who cares if you've removed all the bloat from your code if it's wrong?