Living With Complicated Code
It can be tough to make changes in large, complicated codebases. When we make changes, we must know that we are making them one at a time. Too often, we think we are changing only one thing, but instead, we change other things unintentionally: introducing bugs. If we can write tests against old code, we can figure out when its behavior changes. This helps us know that we’ve added new code properly and supports us when we refactor. Unfortunately, getting tests in place in complicated code is often challenging. You have to refactor to get tests in place to refactor.
When you do this often enough, you start to see code that doesn’t have tests as legacy code. The differences between code bases that have difficulties and those that don’t are so significant in most cases that they swamp most other criteria for good design. When you have tests, you can improve things; when you don’t, you often don’t know whether you are or not.
Michael Feathers