A group of developers on our team once sat down to discuss the parts of our codebase that were difficult to change. We reduced the discussion to two principles.
1. Minimize complexity
Complexity makes every future change harder. A useful abstraction removes more complexity than it introduces.
- DRY is helpful until sharing code creates a confusing abstraction.
- YAGNI and KISS matter most when a feature is new and likely to change.
- An abstraction that leaks everywhere is often worse than a little repeated code.
The goal is to reduce how much someone must understand before making a safe change.
2. Optimize for readability
Code is read more often than it is written. Make the next person’s job easier.
- Use explicit, descriptive names.
- Move complicated conditions into named variables.
- Keep methods focused on one job.
- Keep a method at one level of abstraction.
- Prefer familiar code over clever code.
These principles sometimes conflict. Removing repetition can hurt readability. Adding a small abstraction can make the code easier to understand.
When that happens, choose the version that leaves the next developer with less to hold in their head.