It’s OK if your code is just good enough
I’ve heard a story about a student who had to write an essay to pass the exam. He had a three-month deadline. During those months, he struggled a lot, rewriting pages again and again. Now and then, the professor checked on him, and he would always respond with, “I’m not done yet; it’s simply not good enough.”
Finally, the professor suggested: “Write the essay as if it would be graded good enough.” As much as this approach was strange to him, he took the advice. Surprisingly, he finished the essay in a whip, earning a higher grade than expected.
Where I come from, good enough would be a “three,” simply an average grade on a 1 to 5 scale. Solid, acceptable, good.
The five shades of code quality
We, as software developers, not only write essays but dissertations to bring our pile of zeros and ones to life. Most of us would want our code to be 5 out of 5. But is this something worth pursuing? Let’s explore five shades of code quality:
1 – Shit
2 – Proof of concept
3 – Good enough
4 – Very good
5 – Perfection
Grade 1: Shit
This is the type of code that makes you sweat. Your heart sinks when you hear about a new requirement. You know it will take ages to implement it. The best thing you can do is to throw everything away and rewrite it. Such code shouldn’t be acceptable; we shouldn’t ship shit.
Grade 2: PoC
Typical PoC code. You know this code is not good, but you can live with it for a while.
- doesn’t have clear architecture, clear boundaries
- many things are tightly coupled
- many edge cases are not covered
- missing validations
- inadequate domain object modeling
- too complex or too tiny test suite
- code is not clean
While this may not sound ideal, it can serve to determine the direction you want to go quickly. You can move really fast and iterate as you go. This code quality is particularly suitable for PoC initiatives.
Grade 3: Good enough
Good enough code is a nice middle ground between implementing a feature fast and maintaining the code quality.
It addresses many of the issues typically found in grade 2 code, with some exceptions:
- some unnecessary levels of abstraction
- some unclear naming
- few larger functions or classes (nothing too big)
- misuse of exceptions here and there
- some code duplications
- redundant commenting
- readability issues in tests
This code is suited for most applications. It’s probably the best for those dealing with CRUD operations. You can also achieve good results using this approach on components involved in traffic flow.
Grade 4: Very good
Grade 4 is a highly maintainable clean code paradise. Doesn’t have any problems that good enough has.
Take a look at the infobip-spring-data-querydsl library. Although it sounds perfect, it’s not. Everything is by the book, yet you may not like it or dislike some parts of it. For example, you may find interfaces too generic, or you might be bothered with using primitives instead of objects or something else. There will always be something to dislike, and that is ok. :D.
The problem with this grade is that it is difficult to achieve. We have different backgrounds and views about how a really good code should look like.
I’ve worked with a freelancing company whose code was on this level. They enforced highly strict static code analysis and challenging code reviews to achieve this. Static code analysis was the cornerstone to stop most of the common problems from good enough entering the codebase. You can view them here – under principles. Code review consisted of two reviewers, one developer and an architect, plus a QA person who would check the quality of the review.
If you want to tackle grade 4, you need to build infrastructure for it and have everyone onboard. Aiming for this grade will slow you down, so it should be taken into consideration when doing estimations with PD. Clear benefits will be seen in the long run.
This grade might be suited for building libraries used by multiple projects/teams or when building critical system parts.
Grade 5: Perfection
Good enough is the way to go
Daily, we face different requirements, deadlines, scopes, and so on. They are, of course, not always quick and simple to solve, but most of the time, the good enough approach is the way to go.
To me, the code with a clear architecture, understandable names of services, and good tests tick all the boxes. And I like it! It doesn’t have to be a clean-code candy. If you prefer candies, then you have to convince PD and your team that this extra sugar will benefit the project.
What would you say? What would be your preferred coding approach?