You can do all the testing in the world, but if your code is poorly architected, your software will be of low quality, especially in the long run.

I used to think I was pretty good at software architecture. I had clearly named modules, functions, and variables. I thought you could read my code and understand what it was supposed to do.

Then I learned and practiced TDD on a project, and I learned that I was pretty bad at software architecture.

Loose coupling and high cohesion are software design principles that are probably familiar to experienced programmers. I thought I understood them.

Practicing TDD made it crystal-clear to me that many of my code modules were highly-coupled, and responsible for too many things.

Writing proper unit tests for a code module means exercising every aspect of the interface to that module.

If the interface is large and complex, writing comprehensive unit tests for it is going to be incredibly difficult. So difficult, that you’ll start to realize that maybe the interface should be smaller and simpler.

You start to realize that it’s awkward to unit-test private helper functions, because they are by definition not part of the interface of the module. But they’re complex! They should be tested! You’re right. Put those complex helper functions into separate modules, so they can be unit tested too. You may have to do substantial refactoring along the way. That’s ok!

It’s easier to test a bunch of small code modules, each doing one thing and doing it well, than a large code module that does a lot of different things.

As it turns out, it’s easier to understand a bunch of small code modules, each doing one thing and doing it well, than a large code module that does a lot of different things.

If code is easier to understand:

  • it’s easier to debug
  • it’s easier to maintain
  • it’s easier to modify
  • it’s easier to verify

These are the hallmarks of high-quality software.

I’ve said it before: Writing unit tests is the fastest way to reveal flaws in your code architecture, and force you to fix them.

Practicing TDD is the best way to force yourself to write those unit tests, and realize all the benefits that entails. Wait to write them after the fact, and you’ll regret it.

Be safe out there, and happy developing.