← Back

Programming for Testability and Maintainability

Good software is designed to be easy to test and maintain. These qualities reflect structural decisions that make it possible to fix bugs and evolve a product.

Clean CodeTesting

I’ve sometimes wondered how to tell good software from software that isn’t so good. There are surely subjective aspects involved. However, if we try to arrive at some kind of principle like those Max Kanat presents in his book Code Simplicity, there are in fact several ways to evaluate the quality of good software.

I don’t even like raising the concept of quality, since most of the time software developers do the best they can in the work environment they have to deal with. I’ve rarely seen things done badly out of sheer intellectual laziness. I have often seen them done badly out of naivety, or because there was no mentor to provide guidance and pass on their experience.

So how can we tell a well-made library or piece of software from one that isn’t as good?

A very common mistake many software developers make is writing code in a way that makes it difficult to create enough tests around it to ensure that the software works now and will continue to work in the future.

This is a mantra I repeat often: the structure of a solution that can be tested is nothing like the structure of one for which it is impossible to create a suite of tests. So here’s one factor that can give us some indication of a piece of code’s quality: how easy or difficult it is to test.

But what about maintenance? Don’t we want to write software that lives for many years and can be sold and deployed to as many customers as possible? How can we do that if the solution we write is impossible to maintain? Here we return to the metaphor of a car that can’t be repaired…

Similarly, good software written to be easy to maintain is entirely different in form and structure from software that is impossible or very difficult to maintain (a rigid design). By maintenance, I mean being able to detect small bugs easily and improve the product with new features or enhancements to existing ones.

Indeed, over time we realize that the design, structure, and form of software that can be tested easily and maintained simply have nothing in common with those of software that we cannot test well and in which making any change is very difficult.

This is an unbreakable principle of software development that we eventually learn over several years, after going through a few periods of failure and mistakes.

When we reach these conclusions, we realize that programming well isn’t achieved simply by reading a good C#, Ruby on Rails, or other technology manual; knowing the fundamentals of any technology isn’t enough. There are principles, laws, designs, and so on that truly show us how to arrive at a solution of sufficient quality.