.NET Developer with interests in React and DevOps, who tries to challenge the status quo. Passionate about microservices, cloud and all other ways to improve the development process. After work a fan of cinema, gym enthusiast, philosophy amateur and fantasy bookworm.
Why do we emphasise crafting clear, readable and elegant code? Why do we rely on acronyms like DRY, SOLID, YAGNI, KISS to elevate engineering quality? Why do we produce documents such as Agile or Software Craftsmanship manifestos to steer our software development principles?
In this blog post, I will explore what constitutes a “good code” and argue that this may be a matter of perspective, the phase of the project and the company you’re working at. I’ll look at different approaches to aligning our technical standpoint with the business needs of the project.
Almost every change can have a comment in the code review process. Does it mean that every code has something to be improved? No, not necessarily, we just usually have different preferences as to how the code is structured and which way is better. You can name a variable in five different ways and it will convey very similar meaning, but your colleague may prefer a specific naming due to her personal inclinations. Even if you have the most comprehensive code guidelines, there will always be something to argue about. Writing code is a creative process, like in writing a book, an article, (or a blog post :)), there is no single way to write it. Therefore, it’s important that we understand other people’s styles, preferences and conventions as long as they are in line with general guidelines in your company.
Did you ever try to follow a few software principles at once? How did it go? Did you find a path to a perfect code? I would guess that you rather had a strange cognitive dissonance – something did not add up together. Looking at your code from different angles may result in conflicting approaches, and it's usually a matter of common sense to determine which one to use for a particular change. Let’s examine a few examples.
Scenario: Refactoring a legacy system
1. DRY (Don't Repeat Yourself) vs. YAGNI (You Aren't Gonna Need It):
2. KISS (Keep It Simple, Stupid) vs. SOLID:
Scenario: Designing a new cloud-based project architecture
1. DRY vs. KISS:
2. SOLID vs. YAGNI:
Do you already see where I am going with this? There is just no way to combine these every time. You will always bump into some conflicts along the way. These principles are a way of guiding us towards a better understanding of what we should aim for. The goal isn't to rigidly choose one principle over another but to find a harmonious balance that best serves the project's needs. The principles that we prioritise may change over time. It is best to consider an iterative approach, where you can change your choice later if a specific approach doesn’t serve your needs in the end.
However, the hybrid approach had its limitations, mainly concerning memory usage and user interactivity. Because the app was essentially a web page displayed in a native wrapper, it didn't perform as well as a native app, and the user experience was less fluid and intuitive than what competitors could offer with their native applications.
In 2012, LinkedIn chose to transition away from the hybrid architecture to a completely native application, specifically for iOS and Android. This move was a nod towards the principles of SOLID design, the utilisation of clean, maintainable, and scalable software architecture. Leaving behind the quick-and-easy hybrid solution, they settled on a more robust, even though complex, development approach that ultimately put them in a better position for long-term success . Facebook made a similar move for iOS in 2012 .
Let’s consider another step in the software improvement process: code reviews. Have you ever engaged in an extended discussion about a small section of code that your colleague disliked? What impact did the proposed change have? Was it related to a significant bug discovered by your colleague? I would assume not.
The longest code review discussions are probably the least significant ones, where two different “religions” meet. You think you’re in the right, that someone completely misunderstands software development, and you’re angry that you have to explain it multiple times. This results in extended ping-pong-style code reviews that usually don’t significantly benefit the code. It’s important to realise that there isn’t a single way to implement a feature, and as long as the change does improve the existing code, minor differences can be let go.
I think the perfect summary of the code review process comes from Google Engineering Practices:
“Developers must be able to make progress on their tasks. If you never submit an improvement to the codebase, then the codebase never improves. [...] On the other hand, it is the duty of the reviewer to make sure that each PR is of such a quality that the overall code health of their codebase is not decreasing as time goes on”.
If we fail to balance these two conflicting principles, we will fail to improve the project codebase. Either by preventing improvements that never go through code review or by letting in changes that decrease the quality of the code.
When looking at your code and the must-haves you want to include, even before creating a pull request, it’s important to consider the stage your project and company are at. Is it a greenfield project for a startup with a vaguely defined business logic and domain model?
Or is it a 30-year-old monolith for a big corporation with millions of lines of code? You may be somewhere in between, but it is important to notice that different projects will have very different definitions of “good code”.
Let’s examine these two examples in a little more detail. We will consider a few different “good code” categories.
I highlighted categories that demonstrate the differences, but both projects could share common practices rooted in overarching software engineering principles. These could be security concerns, prioritising code readability, adhering to robust coding standards, or emphasis on the extensibility of the code.
The company and the project you’re in do matter. You can’t use the same approach in vastly different development dynamics. Understanding your project needs at a particular stage can be challenging, but it will make you much more flexible and valuable to your company. Even for two companies at the same stages, with similar projects, development practices can be markedly different. It’s important to understand whether you fit into the company culture and to sometimes consider another job without blaming yourself for a perceived failure.
Soo, we’re finally through it, 2600 words, I’m glad that you’re still reading (you didn’t just skim through to the summary, did you?). Writing “good code” will always be challenging, because, in the words of Google Standard of Code Review: “there is no such thing as "perfect" code – there is only better code”. Even the code generated by LLMs won’t be perfect and will require engineers' attention – I’m sure you wouldn’t just straight-paste LLMs’ code into your payment processing module. However, shipping your code to production is as important as making it technically excellent.
Aligning different software principles together may give you a headache sometimes, cause arguments with your colleagues or even make you reconsider your career in software development :D. It’s useful to have them in the back of your head because all in all, they do help a lot if you sift through them. Even the design of your product may be inspected from the standpoint of the software principles.
Code reviews are aimed at improving code quality. They’re an essential part of the process for the vast majority of modern software companies. It’s important to remember that code is only code, it doesn’t present the entirety of a person. Keeping empathy in mind will help you make code reviews more productive and efficient. A code left in the phase of PR is always a wasted effort.
Your company certainly has its own philosophy of programming. Whether it’s aligned with your view of “good code” may depend on what you value as a software engineer. Being more flexible with your views will allow you to thrive in a variety of software teams. Understanding the dynamics and culture of your company will lead you to deliver software aligned with your company’s goals.
Did you think about the philosophy of programming at your company? Perhaps you can see some of the previous examples in your everyday work? Or maybe, if you’re early in your career, you think you know the right way, because there must be a right way, right?