Skip to Content

Software correctness is a lot like flossing

My work brings me though a lot of software correctness techniques, things like type theory, test-driven development (TDD), and formal methods. The surrounding communities all have the same problem: they can’t get people using these techniques. They all ask “Don’t people care about correct software?” To which the insiders usually answer “programmers don’t care about correctness, they just care about shoveling out garbage to make money!”

I’ve heard this from every single community I’ve explored, many of which are in direct conflict with each other. Bertrand Meyer, the main popularizer of Design by Contract,1 wrote an essay attacking functional programming, while many TDD advocates reject formal methods entirely. Every single one of these communities can point at the other ones and say “they don’t care about correctness, they just want to shovel crap out”, and those communities can say the same things right back at them. A very nice symmetry, isn’t it?

Which means that they’re not seeing the bigger picture. An explanation of why programmers “don’t care about correctness” shouldn’t just be post-hoc rationalizations. Here’s my main argument for why most programmers don’t seem to care about software correctness:

  1. Which is worse: buggy software or a root canal?
  2. How often do you floss?

Whenever I pose this in a discussion, I get the same answer: everyone thinks root canals are worse, and at most half of the group flosses daily. That’s ridiculous! Flossing takes like three minutes a day. But people don’t do it because it’s fiddly, annoying, and inconvenient. If people are unwilling to do something simple to keep their teeth from rotting, why should we expect people to use annoying inconvenient tools to improve software?

Some purely anecdotal evidence I have in favor of this is that I vastly prefer to use TDD with Ruby than with other languages, entirely because of rspec. Rspec is the most pleasant unit testing library I’ve ever used. It was easy to set up, easy to tweak, and easy to read and write. To add to this, there’s a huge array of Ruby libraries, like factorybot and capybara, to handle the inconveniences of TDD. I don’t have hard numbers, but I’d speculate that a far greater percentage of Rails projects use TDD vs projects in other web frameworks. Part of this is culture, sure, but the affordances in rspec certainly help.

I’ve also seen a lot of my friends get more excited about type systems because they started using Elm or Typescript. If you are Too Online you’ve probably seen essays attacking these two for either being unsound (in the case of Typescript) or for lacking typeclasses (in the case of Elm). On the other hand, these languages are much more UI/UX oriented and provide significant tooling affordances. Elm is famous for its compiler error messages and Typescript has great IDE integration. Both of these play a significant role in user adoption. Many people then migrate from these two languages to more “hardcore” type systems, like PureScript or Haskell. Experienced people are willing to tolerate more inconvenience for more power.

That tolerance might be why insiders don’t see inconvenience as a serious issue and prefer “easier” explanations, like developer laziness. But inconvenience is a serious barrier to beginners and interested outsiders. And when inconvenience isn’t addressed- or even acknowledged- in the community then it’s a signal that the community doesn’t care about growth. So it’s not just that user-friendliness makes it easier for people to use these techniques, it also makes it easier for them to commit. They are more likely to believe that the community has the user’s best interests in mind.

One reason I don’t like the “developers don’t care” excuse is that it’s too nihilistic. If that’s the case, there is nothing that we can do to encourage people to use better correctness techniques. Changing “developers don’t care” would mean changing the fundamental culture of our society, which is way above our pay grades. On the other hand, if adoption is a “flossing problem”, then it’s within our power to change. We can improve our UI/UX, we can improve our teaching methods, and we can improve our auxiliary tooling. I’ve seen this work in my own life. I’ve done a lot of educational outreach for formal methods and have seen spectacular results. A lot of those “apathetic” developers started using formal methods once learning it was easier.

Barriers

I suspect there are three major reasons why people avoid “convenience” explanations for tool adoption:2

  1. Once you’re an expert in something, it’s really easy to work around the inconveniences, so people may not even realize that things are inconvenient.3 This is sometimes called expert blindness.
  2. Convenience sounds like “polish”, a nice-to-have that gets pushed to the wayside when budgets are limited. Performance and security are thrown out under time crunch, so why should usability be any different?

    Similarly, in academia, UI/UX is low prestige work. Academics can’t publish papers about how they made a tool easier to use, even if improving usability would dramatically improve industry adoption. The incentive structures are all messed up.

  3. UI/UX is really hard and requires a skill set completely distinct from the skills required to technically address software correctness. This means a lot of the core contributors and early adopters of a tool aren’t equipped to make it more convenient.

Fortunately, there are low hanging fruit that can be provided by the communities without needing fundamental changes to tools. I contribute through writing documentation. There’s also providing snippets and cookbooks. Higher level UI abstractions help, too: we could probably increase property-based testing adoption by providing input generators more sophisticated than the core primitives, or by developing test generators like ghostwriter and QuickSpec. These don’t make the tools easy, but it makes them easier. Some people who were “just barely” put off will take the plunge, growing the community and bringing in people who can help shift the usability window more in the future.

Ultimately adoption is a optimization problem: where do you best invest resources for the good of the community? Some communities aren’t interested in growth at all and that’s fine. Some may decide that improving things for existing users is more important than finding new ones, and that’s also fine. But for communities who want to go mainstream, it’s a mistake to blame outsiders for not seeing the light. Maybe you just have a grimy window.

I shared the first draft of this essay on my newsletter. If you like my writing, why not subscribe?


  1. Tee Em. [return]
  2. These don’t apply as much for the adoption of practices, like TDD or code review, but the tools used to do them suffer from similar issues. [return]
  3. This is different from the aforementioned “experts acknowledge there’s inconvenience but don’t think it matters to adoption”. [return]