by ex3ndr on 1/23/25, 7:31 PM with 87 comments
by jp57 on 1/23/25, 9:25 PM
1. Correctness of a program is distinct from its performance.
2. Program correctness can be proven.
3. Optimizing for performance often makes it harder to prove correctness.
I do not actually use formal methods in my work as a developer, but the class helped improve my program quality nonetheless. Now I generally think in terms of a program being correct rather than having no bugs. Technically these are the same thing, but the change of language brings a change of focus. I generally try to use the term "error" instead of "bug", for an incorrect program.
My strategy is to write the simplest correct version of the program first, convince myself that it is correct, and then optimize, if necessary without regressing on correctness. I generally use tests, rather than formal proofs, though, so of course there is still the possibility of uncaught errors, but this strategy works well overall.
Thinking this way also gives me guidance as to how to break down a program into modules and subprograms: anything that is too big or complex for me to be able to reason about its correctness must be subdivided into pieces with well-defined correctness.
It also has clarified for me what premature optimization means: it is optimizing a program before you know it's correct.
(EDIT: fixed "reason about its complexity" to say "reason about its correctness" in the penultimate paragraph.)
by codeulike on 1/23/25, 8:26 PM
by teddyh on 1/23/25, 9:47 PM
However, with more experience comes a better understanding of the general metastructure of code, and therefore an ability to hold more code in your head at a time. (Compare for instance the well-known increased ability of chess masters to memorize chess boards, compared to non-chess players.)
When you’re an inexperienced programmer, you need to write the code down (and run it to test if it works) before you know if the code and algorithm solves the problem. This makes the inexperienced programmer take shortcuts while writing down the code, in order to get the code written down as fast as possible, while it is still clear in their mind.
The experienced programmer, on the other hand, can easily envision the entire algorithm in their head beforehand, and can therefore spare some extra attention for adding error checking and handling of outlier cases, while writing the code for the first time.
Also, as the article states, when you make a conscious habit of always writing code which checks for all errors and accounts for all outliers, it becomes easier with time; practice makes perfect, as it were. This is essentially a way to speed up the natural process described above.
by jordansmithnz on 1/23/25, 9:05 PM
Assume that your code will have bugs no matter how good you are. Correct for that by making careful architecture decisions and extensively test the product yourself.
There’s no silver bullet. If you put in enough time and make some good decisions, you can earn a reputation for writing relatively few bugs.
by skulk on 1/23/25, 8:12 PM
by lizard on 1/23/25, 10:32 PM
A one of my CS cohorts happened to be in the same class so we teamed up for the first lab project. It was pretty straightforward, we collected whatever information, and started working on our report. We didn't bother spending much time on it because we already knew we'd lose points for something or another.
When we got it back, there was a big, red "100" on top. We checked around and it did look like we were the only ones that got a perfect score, so we went to the instructor and, mostly jokingly, said, "What's up with this?" to which he stayed on beat and replied, "Do you want me to take another look?"
It's not hard to do good work, but you do have to make a habit of it. Re-read what you write, preferably out loud, to make sure it actually makes sense.
You'll still make errors and mistakes and you won't catch them all, but no one's going to care about a typo or two unless you draw attention to it with more glaring problems. And I think this is where metrics, especially things like code coverage, can actually be detrimental, because they bring attention to the wrong things.
Specifically, in places I've seen code coverage enforced, tests (written by consultants making x5-10 more than I do) tend to look like, `assert read_csv("foo,bar") == [["foo", "bar"]]` that execute enough of the function to satisfy the coverage requirements, but everyone is surprised when things break using a real CSV document.
The corollary of the author's trick is that if you keep making excuses to produce poor work, you may subconsciously decline instead.
by TypingOutBugs on 1/23/25, 8:30 PM
by lcnPylGDnU4H9OF on 1/23/25, 8:08 PM
Practice makes permanent. Perfect practice makes perfect.
by chowells on 1/23/25, 9:21 PM
If you want to really get code that can be adapted whenever requirements change, you need to be thoughtful. Understand the code you write. Understand the code you choose not to write. Understand the code that was there before you got there. Think about the edge cases and handle them in a way that makes sense.
I'd call it "practicing writing code without bugs" rather than "writing code without bugs", though. In the end it's a practice. Is it going to be what you work towards every day, or is just an afterthought?
by ChrisMarshallNY on 1/23/25, 9:56 PM
Getting there, though, I have lots of bugs. It's just that I want them gone, before I pat my app on the butt, and send it out into the field.
I often see people use Voltaire's phrase "Perfect is the enemy of the good," to justify writing bug farms. I'm not sure that this is what he meant.
by csours on 1/23/25, 8:47 PM
https://www.destroyallsoftware.com/screencasts/catalog/funct...
by taeric on 1/23/25, 8:23 PM
This reads to me like the idea that a rich person walking down the road wouldn't pick up a $20 they happen to see at their feet. Of course they will. Why not?
What they don't do, is waste time walking around looking for spare money that has been dropped. Because that would almost certainly be a waste of time.
Similarly, use your tools to write as efficient and bug free code as you can. Make it as flexible and allow for any future changes you can accommodate along the way. But "along the way" should be "along the way of delivering things in a timely manner." If you stray from that, course correct.
by eternityforest on 1/24/25, 11:06 PM
Then mention subconscious skill, and I think some people improve with practice more than others, and there may be individual differences in the "Noise floor" of trivial mistakes, like swapping plus and minus for no reason you could explain, they're just in the same category and you vaguely pattern matched that an operator goes there, and didn't think about it because people don't analyze every single token like a robot.
I can ship code that is more or less bug free, and I always aim to do so, but I don't really consider the idea of directly writing good code.
I try to remove opportunities to fail, designing an architecture that I think wouldn't take a lot of skill to implement, and then write the code, and then assume I have still failed in every imaginable way, and check for those failures, even if I have looked over the code ten times and am sure that I didn't make some particular mistake.
This is generally how I think about life in general too, I'm always thinking "Use a protective case" instead of "Just don't drop it".
by 3vidence on 1/23/25, 8:24 PM
It feels close to just saying, make your code better and you will see less bugs.
I don't disagree but the product environment has a lot to do with how features get deployed and how closely a developer can match the real life deployment to their development setup.
World class experts make mistakes all the time, I think learning how to address bugs is probably a more valuable skill.
by epolanski on 1/23/25, 8:24 PM
Lately I've been victim of letting too much pressure from clients build and I ended up spending 5 days on a major feature (built on legacy messy code) and in the process of making it better and adding a new features I ended up breaking few things here and there, which didn't play nicely with my refactor. Which costed me another few days of work.
I guess I should've had an approach closer to what he describes, written few tests more before hand and taken more time to nail it without the delay.
I learned from that experience, but the mindset he talks about would've been more beneficial.
by switch007 on 1/24/25, 7:44 AM
Oh, you've met my CEO and CTO. And all those at previous companies!
by smileysteve on 1/23/25, 8:22 PM
Airbrake, Rollbar, Datadog, New Relic mean nothing if you ignore bugs because you don't take the time to replicate them.
You also can't fix what you don't know, so you need some telemetry or reporting of not your happy path. You can't have a goal of bug free code if you don't measure bugs (that's not SMART goal because it's not measurable).
Unit Tests, Typing, Linting, a collaborative code review process are key to big free code.
by noodlesUK on 1/23/25, 9:11 PM
In order to really prevent bugs, you need actual engineering.
This means understanding the constraints on a system, where bugs are likely to occur (perhaps not even in code your company writes - your OS can have bugs too!).
Shipping stuff that you subjectively feel is high quality is a good start, and it’s enough for a lot of industries, but it doesn’t mean “bug free”.
by presentation on 1/24/25, 11:16 AM
by karaterobot on 1/23/25, 9:41 PM
I'm very skeptical of this. You can't really have it both ways. I believe someone when they tell me they can ship code without bugs, but only by taking a lot of time, including the time necessary to test and debug the relatively fewer bugs they produce. But, I find it hard to believe someone who says that through pure self-discipline and force of will, they can just not write bugs without sacrificing speed.
And, generously, if there is someone who can do this, I find it hard to believe it's a generalizable methodology. "Just decide not to write any bugs... why didn't I think of that?"
I guess the third possibility is that you can ship code quickly without bugs, but only if it's trivial code. I would believe that, but I don't think that's what he's saying. This seems like an extraordinary claim.
by cess11 on 1/23/25, 9:33 PM
Some of the most successful softwares are horribly bugridden.
by JTyQZSnP3cQGa8B on 1/23/25, 8:49 PM
by affinepplan on 1/23/25, 9:48 PM
applies to nearly everything.
by JohnMakin on 1/23/25, 10:12 PM
I don't really approach code this way, but I do prefer to fully think through a problem before I begin banging it out. This has upsides and downsides. Honestly though, I am very wary of anyone in tech that says something "absolutely" has to be done a certain way. An example - I have a convention with executable convenience scripts where I will label them per environment, in the naming of the file, and separate them by directory that way. It often gets pointed or yelled at me about "DRY" being violated, and now I have to maintain 3 separate sources of these, etc., when I could simply have a parameter I pass in to do the same thing. That would make it "productionalized", why all this repeat code everywhere???
Well, yea, I could. But, knowing me and how long I've done certain things, it's stupid easy to forget in the moment when you're tired or distracted what you are doing and where and do the wrong thing in the wrong place - which can be a total disaster that far outweighs whatever I am gaining from DRY principles. I find the better engineers I work with aren't so strictly rigid with their thinking and tend to do the same types of cost/benefit/risk analysis to whatever approach they choose.
by lieks on 1/23/25, 8:47 PM
A lot of them have this bizarre idea that since bugs will happen anyway, there's nothing we can do to avoid them. Then they come up with some bad architecture, or poorly-thought-out convention, or use a problematic library, which makes it easier for logic bugs to happen later, when someone else changes a convention elsewhere that interacted with it.
There often is a way (usually multiple ways) to architect software to avoid bugs. What Rust does to memory bugs and Haskell does to state bugs, can often be done manually in other languages, for whole categories of logic bugs, by being careful with your conventions and making sure they are easy to follow correctly.
I.e. software can be designed to avoid bugs. That requires some thought many people don't care to put in.
by groby_b on 1/23/25, 8:23 PM
You can write code without bugs all you want, you won't sidestep those two.
I mean, yes, of course. Don't write obvious garbage code. Don't take obvious shortcuts. Value your craft.
But you'll still have bugs. (So did Telegram, btw: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=telegram)
by NooneAtAll3 on 1/23/25, 8:18 PM
by withants on 1/23/25, 9:28 PM
by tonyhart7 on 1/24/25, 12:09 PM
I mean when we talk about money and company can potentially bankrupt within few minutes because how easy today to move money, things can get south pretty quick