I love programming, but even if I didn’t, I couldn’t give it up because I would feel like I had failed at my life’s quest, which is to figure out how to write perfect software. Perhaps my quest is as futile as Ponce de León’s search for the Fountain of Youth, but I press on.
“Perfect” entails beautiful, and we love beautiful software, but I would be happy if my team and I could just avoid making mistakes! To that end, I present this little series of posts.
Some current ideas for reducing defects include
- Use test-driven development (TDD).
- Use a functional-programming paradigm.
- Use “reactive” programming.
We have emphasized TDD for some time, but before I upended my team’s paradigms by switching to functional or reactive styles, I thought I’d take a look at all the defects my team fixed in a recent release. Why did these defects happen, and how could we prevent each type from happening again? Were the new paradigms the answer, or were we missing something else?
Here are the results. Expand each category to see some details (except on IE/Edge they are permanently expanded), but the upcoming posts in this series will explain a lot more.
30% – Developer not thinking about obvious UI concerns
Bugs in this category range from the trivial (controls not being visually aligned, capitalization conventions not being followed) to failing to think about the requirements from an end-user’s point of view.
8% – Earlier code did not cover all cases
Here, the developer did not consider all edge cases, all contexts in which a module is used, etc.
6% – WET code
WET code (We Enjoy Typing or Write Everything Twice) is the opposite of DRY (Don’t Repeat Yourself). These bugs occurred when one instance of copy-and-pasted code was updated for new requirements but another was not. Also when a pattern such as error-handling should have been encapsulated, but was implemented WETly, and correctly in some places but incorrectly in others.
6% – Missing abstraction
6% – Insufficient understanding of third-party software
Using third-party libraries is an effective way to reduce defects, but sometimes those libraries are so complicated or quirky that mistakes in their usage are almost inevitable. (I’m looking at you, Entity Framework.)
5% – Insufficient requirements
Sometimes developers code the wrong thing because management (that would be me) have failed to provide requirements in sufficient detail.
5% – Not considering performance
What happens when you code an HTML
select element with a few
options in development and then, in the real world, it gets loaded up with thousands of
options? A performance defect, that’s what.
4% – Faulty promise-handling
3% – Weak error-handling
Failure to check parameters, non-helpful error messages, and other things that make support staff’s lives miserable.
3% – TDD not used
TDD fanatics might claim that the technique eliminates nearly all bugs, but this category is reserved for especially egregious cases such as non-TDD code that generates (generates, mind you!) regular expressions where those regexes turned out to have bugs.
3% – Caching
We optimize the performance of our web application by caching various data from the server. This extra layer of complication gives rise to the occasional defect, such as when data are cached in more than one place. Oops.
21% – Other
Failure to be backward-compatible, developer not remembering to update the installer, race conditions, changes in third-party software, etc., etc., etc., each less than 3% of the total.
Coming posts in this series will describe how my team and I decided to address each category of defects. Stay tuned!