Skip to content
Contact

Reflections on code qualityConfession of a CTO

The software is often the foundation of your online business. Foundation on which that business is based. On top of which it will be evolving over the next years or decades.

Early stages of development should be thought through carefully like with a multi-store building. The first floor needs to be quite stable for the whole building's safety.

The most important on that stage is to maintain the best code quality possible.
But, what does it mean? How to do it?

After 11 years of experience as a software engineer and then as a CTO of a software company Untitled Kingdom, I want to share with you my thoughts about:

  1. Is it always necessary to fight for good code quality?
  2. What does the temptation come from to overengineer stuff?
  3. How to maintain good code quality and who is responsible for it?
  4. How processes and culture affect code quality?

GOOD QUALITY OF CODE. IS IT ALWAYS NECESSARY?

Some companies acknowledge that it is good to strive for good code quality but say that sometimes code quality must give way to the quick deliverance of outcomes to the customer.

We’ve been working on over 60 different products. Some of them we built from scratch and some were legacy from different software houses, freelancers, and founders.

I would say there are three types of codebases we dealt with in our history.

  1. There are (usually) quite current codebases with all the good latest tech and trends in code.
  2. Some codebases have pitfalls, quirks, or older tech but they’re still good to work with.
  3. Legacy code hell. A nightmare for every developer. Messy, huge, buggy code that shouldn’t exist.

I had a chance to work on all of those types of projects where and the conclusion is very simple:

Code quality is not an abstract concept that has a value only in the developers’ world, it is a very real thing, which translates directly to money, namely if you are missing it, it translates into great financial losses over the time.
Jakub Holý, a quotation from his blogpost Code quality matters to the customers. A lot.

Don’t get me wrong. No ones’ code is perfect. If you as a developer look back on your code and wouldn’t want to change or improve something after a year or so it means you are standing still where the technology and trends are probably already way ahead of you.

 

OVERENGINEERING STUFF

All another problem is overengineering stuff and trying to be too perfect, spending unreasonable amounts of time designing it to be more robust, extra featured than is deemed necessary for its primary application to be completed successfully. This might mean either an inexperienced developer or perfectionist without supervision and a lack of business perspective.

You can say a developer is senior if he can find the proper level of sufficient quality, especially in legacy code. It might not be wise to rewrite the whole feature just because its code quality is poor. If it doesn’t affect overall application extensibility and readability, it might be better to leave it as it is, and maybe come back to it when the time is right.

However, when speaking about software, which will live or 5, 10, 20 years, code quality is not anything that can be sacrificed! It’s a bit like with planning or security. Creating a technical debt by expanding already poor quality code or applying some hacks to make it work for now can save some time in a short distance, but over its long lifespan and future development, you eventually will pay ten times more.

Trust me, I’ve been there, I’ve seen it, I’ve paid the price and cursed the authors of the hack.
Jakub Holý, a quotation from his blogpost Code quality matters to the customers. A lot.

HOW TO MAINTAIN A GOOD CODE QUALITY?

Structuring the system

The first and the most crucial aspect of the code is its architecture and proper structuring. Developers should know universal design patterns that are commonly known, and thus are better understandable by others in the team. That also makes the code extendable in the future if correct principles are applied.

Developers also need a vision for the whole system working to be able to create its draft and blueprints. Again, like with buildings, you don’t build a couple of first floors to realize then that it won’t support the next 100. You also want to divide all functionalities into modules so that one feature is precisely in one place, it’s natural to find, and if needs changing or fixing you only need to do it in one place. It’s called separation of concerns.

Mixing different things all over the code is super messy and very hard to understand by someone else if not even by the developer that wrote this in the first place. Each module and component should be easy to exchange without creating too many dependencies. For example, if at some point we will need to change our database to something faster.

Naming

Even small things like naming conventions, file structure, variable names all contribute to making the codebase more readable and easier to understand by others. At some point, a developer will come and go, and if project onboarding takes a couple of weeks or months, it might destroy the business. It’s also recommended to use the same terminology for modules and classes as we use in other documents and everyday discussions to avoid confusion and misunderstandings.

Test coverage

Last but not least is the test coverage — again quality, not quantity. With 90 or even a 100% test coverage we still might not cover all possible cases and errors.

Moreover, because the software is continuously evolving whenever we are changing something we don’t want to break something else at the same time, it’s called regression bugs.

Requiring high code coverage just because that number seems correct and it’s a KPI in another company will usually result in a bunch of useless scenarios not testing the units they are supposed to. Of course, writing them will take a lot of precious time and developer's frustration.

First, you need to understand the value of creating them in the first place. Excellent communication, education, and trust is the key to every good product development process. Of course, I’m talking here about cooperation with more experienced developers.

HOW PROCESSES AND CULTURE AFFECT CODE QUALITY?

Code quality can be considered a reflection of the process and culture that create it. Without the right kind of attitude and support — technical, managerial, social — the code base is likely to decay over time. One approach to postponing the onset of such entropy is to avoid getting into big problems in the first place by continually attending to the smaller ones. If big problems grow from medium-sized problems, which in turn grow from small problems, catching them at source makes sense.
Kevlin Henney, a quotation from his blogpost Why code quality matters

Things like refactoring, which is the process of restructuring existing computer code without changing its external behavior, might sound stupid and unnecessary at first. Why would you change something if it’s already working fine, and why didn’t you code it correctly in the first place, you may ask. Those are indeed valid questions, but the truth is that creating software is a tough game.

You need to integrate many things, care about security, performance, future features, and code extensibility. Of course all of that under time pressure. Moreover, sometimes we merely inherit some legacy code that we have to deal with. In IT everything is changing very rapidly. You have to know that some of the code needs to be simply updated over time. There might be new system features to use or newer versions of libraries that could do a better job.

WHO IS RESPONSIBLE FOR CODE QUALITY?

Is it that just developers are responsible for code quality? Well, that’s not the only case.
Of course, they will try to find an excuse for every wrong decision and error created in the code. However, let me show you how initial pressure in the early stage can affect the future of project development. I’m not even talking here about things that might change in the future or bad architectural decisions because after another pivot might be impossible for any good architecture to hold on.

I want to talk about a sloppy code cycle that is hard to break because the sloppy code is self-reinforcing. Often it starts with pressure. There might be different needs, different critical priorities, like an important client deal, event, or something else that might require a significant amount of functionalities by the time it comes. That initial pressure leads to sloppy code. Because of the short deadline, they had to cut corners, consciously using bad practices and not applying the same amount of rigor and when developing at a normal pace. Of course, their intentions are right here. They are trying to meet critical business objectives, that they were left with.

Unfortunately, sloppy code can make it harder to work with the codebase. It means you can no longer deliver features as quickly as you were before. That, of course, means a project not being ready for the time. Moreover, if you are going to communicate that problem to the team, it will create even more pressure on developers to work harder and faster. The loop is completed, and it can go on for a long time like this until devs will give up.

Code quality is a curiously slippery quality. It is often talked about in theory and ignored in practice. It is considered to be important in the long term but optional when a deadline is looming. It has no direct presence in a schedule, but it affects the schedule. There are syntax-centered, runtime robustness, and broader design-related definitions of it.
Kevlin Henney, a quotation from his blogpost Why code quality matters

It’s easy to forget about everyday challenges and chasing deadlines, but it’s hard to argue that software with fewer defects will get higher customer satisfaction and higher confidence for business partners than one with a dozen features that often fail to work as intended.

SUMMARY:

We must strive for good code quality so that the code will be able to live on without rotting over the time. The quality will never be perfect, but it must be good enough (…).
Jakub Holý, a quotation from his blogpost Code quality matters to the customers. A lot.

That means that you shouldn’t hesitate to make small-scale improvements when you see an opportunity for them. The result will be that the overall quality of the code will improve over time instead of decaying, as is usually the case. That will bring much value to the product, the team, and your budget.

__________________

If you share my ideas and want to talk more about code quality, please leave a comment.

If you have a project to discuss, contact us.

By Bartek Hugo Trzciński

Head of Technology by day and software engineer by night. Recently solving more problems in business and mangement than in code - hard to tell which one is more fun. Local dev groups activist. Automotive enthusiast. Boosted Board shredding champ. The best companion to dance and to give you a ride.