Architecture,  Test,  Unit test

DOES UNIT TESTS IMPROVE THE ARCHITECTURE OF MY CODE?

This might sound like a silly question, but what do you use unit-test for? It is not as obvious as it sounds, given that the word “test” is in the name. It makes us believe that they are used only for testing, doesn’t it? And to some extent, that’s true. But that is not the full story. They are giving you so much more value than just that. For instance, it changes the way you write code, it changes the architecture.

Writing unit tests forces you to write testable code. That makes it easier to read and understand, it tells you what it does instead of hiding things in gigantic code blocks. But the biggest change is that if code is hard to test, you will not test it enough. And that means you don’t know if it works or not. Your clients will get buggy code.

Architecture

Uncle Bob (Bob Martin) has a lot of talks on Youtube. And in one of them he said (and I paraphrase, because I don’t remember exactly, or even in which of them I saw it):

– Something that is hard to test is badly designed.
– Hmmm. I’m not sure…
– Look. Suppose you ask me to write an app to control your grandmother’s pacemaker. I agree, and a week later I hand you a thumb-drive and tell you to load it into her controller. Before you do you ask me: “Did you test it?” And my response is: “No, I chose a design that was hard to test.”
– Hmmm. Yeah. OK. I guess I see…

– Do you? Are you sure? Let me drive that home even more.
– Any design that is hard to test is crap. Pure crap. Why? Because if it’s hard to test, you aren’t going to test it well enough. And if you don’t test it well enough, it’s not going to work when you need it to work. And if it doesn’t work when you need it to work the design is crap.

Good architecture

The conclusion Bob Martin does is, if it’s testable it has a lot better architecture than if it is not testable. Or put the other way around, if you have a good architecture, the code is testable. And I totally agree!

The reason is that if you just churn out code, you don’t care about anything else than finishing the functionality. You don’t care about things like if it’ testable, if anybody else can understand what it does, if it is easy to find bugs or if you can change it or add things in the future. You don’t care about what the code looks like.

But if you now say that you also have to test it, you add a new concern. And now you write code that both delivers what it should AND is testable. I.e., readable. I.e., easy to debug. I.e., easy to change.

To make code easy to test, you have to separate the functionalities from each other. You just can’t do ten things at the same time, because the tests will be horrendously large and complex. Just the setup to reach the point you want to test will take so much energy from you that you just don’t want to do it.

So, we add a bit of architecture to the process. Like the SOLID principle. The S will take you far. S stands for the Single Responsibility Principle. And in short it means that a function should only have one reason for its existence. So instead of having one big blob that does ten things, you now have ten small functions, each doing just one thing. And doing them well. Why is this good?

Why is finding a needle in a haystack hard?

Let me give you an example. There is a bug in the code. Can you spot it?

public int Add(int a, int b)
{
     return a – b;
}

How long did it take for you to find the error?

Now consider a function that is 50 lines long, just finding the line where we do the subtraction… er… addition is a bit of work. And if the functionality is a bit more complex and the bug is a little bit more subtle… Well, then you really have a problem.

Unit tests makes the code shorter

Now, how much code do you need to write a test for this addition-function? You’re right. Not much. Not only do you get a function that is easier to read, but you also have to write less code to test it.

Good architecture, like Single Responsibility Principle, makes the code easier to read and understand, and thus easier to debug. And let’s face it, writing tests is writing code to debug code.

And it also makes it faster to write. Add a little effort up front, and the ride will be downhill the rest of the way.

— Cheers!

Like it? Share it!

Leave a Reply

Your email address will not be published. Required fields are marked *