You should aim to write/design/structure your code/language/framework so that bugs are obvious.
Bugs can be spotted at various points, a slight over-simplification would be to characterise these stages as:
- Defect is seen by looking at the code
- Defect gives rise to a compiler error
- Defect gives rise to a compiler warning
- Program falls over at run-time at (or immediately after) the erroneous code.
- Erroneous behaviour caught by automated testing
- Erroneous behaviour caught later (or perhaps never)
I was reminded of this issue by considering how best to guard against resource leaks in Java. There are any number of suggestions online for how to do this, and most of the solutions make your code rather complex (so errors are easy to introduce, but hard to spot) while at the same time errors would all fall in to the "detect at runtime (hopefully by us rather than our customers)" category.
In my first set of posts I'm going to consider this issue, always keeping this fundamental rule in mind.