The Rule of Thrice: Know When to Build Generic Solutions in Code
Knowing when to build generic solutions is a long-standing problem in software, as this XKCD comic illustrates:
Striking the right balance between "ya-ain't-gonna-need-it" premature generalization and "copy-paste" code re-use comes with experience. It's part art and part science. Over time, I've developed a rule of thumb that helps me make these decisions.
I call it, "The Rule of Thrice."
The Rule of Thrice
The Rule of Thrice goes like this,
Once is a fluke. Twice is a coincidence. Thrice is a pattern.
To follow the Rule of Thrice, you don't spend any time generalizing a solution until the problem has appeared at least three times.
Benefits
- Avoids premature generalization
- Better defines the pattern
- Reduces technical debt
Avoids Premature Generalization
The left side of the comic above makes this point better than I can:
Developer: It took some extra time to build, but now we can use it for all our future projects.
Narrator: How to ensure your code is never reused.
I've been that developer more times than I care to admit...
Better Defines the Pattern
When you write a procedure based on a single instance of a problem, you end up making a lot of assumptions about:
- Which values will remain constant
- Which values will change
- What behavior needs to be dynamic
- What conditions dictate branching in your code's logic
Waiting for multiple instances of the problem allows you to make fewer assumptions. This results in cleaner code than if you were to slap on branching logic over time as the true nature of the problem revealed itself to you.
Reduces Technical Debt
I'm a backward-compatibility zealot.
One of the big benefits of maintaining a code library is being able to import updates of the library into existing projects. If you are constantly introducing breaking changes into your code library, then you will learn to avoid importing updates into your projects. That's why backward compatibility is so important within your code library.
The big downside to maintaining backward compatibility is that early design decisions are very difficult to undo. By waiting until you have at least three examples of a pattern, you can avoid making obvious design blunders that you will come to regret later.