27 Jan 2022
Everyone seems to be striving for ‘clean’ code at the moment. You can’t read a blog post without the author telling you how clean their approach is. Engineering teams get together and discuss which of the possible solutions is the cleanest. Other developers assure you that they practice ‘clean code’.
I’ve come to a realisation though. There’s no such thing as clean code.
‘Clean’ isn’t a measure of anything useful. Code can’t be clean simply because ‘clean’ doesn’t describe anything about code.
What a hypocrite!
I'm not innocent myself, I've used the term 'clean' plenty of times in the past. I also want to make it clear that I'm not trying to disparage anyone who uses this term.
As a marketing term, or a description of a vision or ethos, 'clean' is great! As a technical term, though, it's got some issues...
When people describe code as clean they usually mean that the code is good in some way.
The thing is, code can be good for a variety of reasons. It could be:
But these traits are in some ways at odds with each other. The most simple code is probably not the most testable. All those interfaces and injected dependencies make for convenient testing, but have a cost in terms of simplicity.
Your heavy reliance on singletons may make things easy to understand, but it might not lead to a maintainable application.
It could be argued that some of these things are fundamentally opposing forces that can’t all be satisfied simultaneously. Engineering is about trade-offs, so we’ve got be aware of the trade-offs we’re proposing, and be able to discuss them as a team.
When someone says a solution is ‘clean’, they’re often touting it as the superior option without being able to rationalise why.
If we want to have constructive discussion around technical solutions then we’ve got to be able to articulate to each other why one solution is better than another. It’s no good arguing over which solution is the ‘cleanest’, as if we should get our clean-o-meter out any weigh up each solution according to this mysterious metric.
It’s actually quite difficult to express sometimes why one approach is better or worse than another, but it’s a skill that is worth honing.
Would you rather have discussion like this?
“I like solution X, it feels much cleaner.”
“I like solution X. It decouples the error message presentation from the core logic. It’s easier to understand, because you don’t have to consider both at the same time. This separation also unlocks some testability, as we can mock either object whilst testing the other. It does come at the expense of requiring the parent object to inject the dependencies, but that’s a worthwhile tradeoff for the testability.”
The second statement actually conveys something tangible about the pros and cons of the solution we’re discussing. Terms like ‘clean’ allow us to cop-out, rather than working to improve our ability to articulate our ideas.
Coding is generally a team sport. If you’re hacking away on your own then you can do what you want, but when we’re working with a team then we’ve got to discuss our ideas. Being able to have discussion about technical solutions using language that is specific and has common understanding throughout the team is invaluable in understanding one another.
‘Clean code’ means a different thing to everyone.
To some developers, code is clean because it has a well defined architecture. To other developers, code is clean simply because it uses a consistent formatting style.
Words like ‘encapsulated’, ‘testable’, ‘mockable’, ‘reusable’ have meanings that we can all agree on. When we use more specific words that describe the various code traits that affect our project then we can be sure that we’re all on the same page.
‘Clean’ has the same level of precision as ‘good’. You can say that code is good, just as you can say that it’s clean, but that doesn’t absolve you from having to justify that with more concrete rationale.
I’ve come to the conclusion that often when we describe code as ‘clean’ when we think it’s good but we’re not entirely sure why. It just feels like the right solution.
Or sometimes we do know why the code is good, but we can’t find the words to articulate it, and somehow the conclusion of our blog post just reads “See! Look how much cleaner that it is!”.
It’s good to build that intuition, but we can’t just stop there. We need to dig deeper beyond those feelings to understand and articulate why we think the code is good. What characteristics does this code have that other solutions don’t? Are those the characteristics that make the most sense for our project? Perhaps it’s actually not the right solution after all.
Hopefully I can convince you that you don’t really need clean code, you need _____ code. It’s up to you to fill in that blank with words that describe what your project requires.