Testable Code vs Clean Code






4.89/5 (10 votes)
Testable code versus clean code
I wrote my first blog article 1.5 years ago, and it was about how TDD made me a happy developer. In that article, I talked about how TDD helps me write clean code, refactor code without breaking it, decrease debugging time and improve my career.
I’m still a Test Driven Developer, but when I wrote the first post, I thought that clean code is testable code, and vice versa. However, I don’t think anymore that these two are the same thing. In my first days of TDD, my goal was to test everything so I could have a high test coverage, now I know this is wrong, but back then, I was really happy to see that my code coverage was over 95%. The problem is that in order to reach a high coverage like this, you have to make sure everything is testable, so I ended up creating interfaces for almost every class that I used, in order to be able to test the code.
Let me give you a better example of what I’m trying to say. If you remember, I made a few articles about doing TDD with Windows Phone, and I said that in the test project I can’t reference any Windows Phone libraries in order to be able to test it, because my test project was a simple class library, not a Windows Phone Test Project. If you have a method that calls a phone number, you would normally do something like this:
public void CallUser(User user)
{
PhoneCallTask phoneCallTask = new PhoneCallTask();
phoneCallTask.PhoneNumber = user.PhoneNumber;
phoneCallTask.DisplayName = user.FullName;
phoneCallTask.Show();
}
But I couldn’t do it because I can’t test the method, so I have to create a wrapper for PhoneCallTask
and add it in my ViewModel
through constructor injection.
private readonly IPhoneDialer _phoneDialer;
class MyViewModel
{
private readonly IPhoneDialer _phoneDialer;
public MyViewModel(IPhoneDialer phoneDialer)
{
_phoneDialer = phoneDialer;
}
public void CallUser(User user)
{
_phoneDialer.Call(user.PhoneNumber, user.FullName);
}
}
The code is shorter, but it’s a lot of extra work that doesn’t add any real benefit. In my example, creating a wrapper for PhoneCallTask
could be useful in the future, because I’m not dependent on the Windows Phone SDK anymore. If they decide to change the way of calling someone, I just have to change the implementation, not the interface, but the chances for this to happen are very slim, so if you’re not going to need it now, don’t do it.
Clean code has its benefits, it will make your code easier to understand for someone else, and it will make it easier to change and refactor. But testable code will make your product more reliable, so you shouldn’t chose between these two, but find a balance between them. If you want only clean code, I say you should write the tests around the code, and if the tests are more important for you, then you should focus on making it testable. If there’s one thing that I learned as a programmer is that there’s no “42” in software development. Stop thinking that all the code should be clean or that all the code should be testable, there’s no such thing.