How to Write Good Code
As developers, we’re taught to polish craftsmanship — write code that doesn’t only work but is also well-structured, error-resistant, and follows best practices. Countless resources discuss “clean code” — elegant algorithms, perfectly structured classes, and clever abstractions.
However, one crucial aspect is often overlooked in these discussions: code must deliver business value. “Good code” isn’t just about following best practices or seeking technical perfection. At its core, good code effectively solves the primary problem.
In this article, we will focus not on craftsmanship alone but also on the broader picture of how code impacts businesses. Let’s explore what good code means in that context.
The Definition of “Good Code”
“Good code” is a subjective term — its definition might differ depending on who and when defines it, based on their personal experience and preferences. A functional programmer might mention the lack of side effects and referential transparency, while a junior developer prefers code they can easily understand and extend.
On the other hand, if you ask non-technical business people what type of code they find good, their answers are likely to mention cost efficiency or competitive advantage. Rarely would they say anything about polymorphism, single-responsibility principles, or dependency inversion. And it’s understandable; they hire us, developers, to write code for them, so they don’t have to think about it.
The problem arises when developers focus only on technical aspects, disregarding business needs. The priorities of both groups begin to diverge. Software engineers want to write clean, loosely coupled code, while business people expect quick results. These conflicts might lead to either solutions that fail to address the real problem or are too costly to implement.
Solving the Right Problem
The most crucial criterion for “good code” is achieving the right outcome. Too often, I’ve seen perfect implementations of multiple design patterns, following best practices, with a single flaw — they solved the wrong problem.
Imagine a scenario where a development team is asked to create an onboarding feature for a web application to help new customers. The team decided to build an onboarding system connected to a CMS, with fancy animations and a clever way of highlighting elements on the page and transitioning between steps — all crafted with SOLID principles using TDD philosophy. After weeks of effort, the technologically perfect system is done and presented to stakeholders. Everyone is happy, and the release is a huge success. At least until the development team learns that the business cared only about creating a simple text and image-based intro for clients to briefly describe core features, as that was required to get started.
The problem? The team solved the issue of a customizable onboarding solution instead of making a simple onboarding experience for clients. Although the development team could blame the product people for not providing detailed explanations, these types of misunderstandings happen daily in every company. How could they be avoided?
Understanding the ‘Why’
A good developer always seeks to understand the business context of a task. This might seem pointless to some, as having proper feature requirements and task descriptions in place is sufficient to start writing code. This is indeed enough to finish the task, but asking “why” helps uncover deeper needs and prevents over-engineering.
Teams can deliver faster by prioritizing current requirements and avoiding speculative features. Techniques like the “5 Whys” or user story mapping can help uncover the true purpose of a feature request, ensuring alignment with business goals. In the onboarding example, a simple approach might have better met immediate needs. Even if a generic solution eventually becomes a requirement, teams would likely better understand the final feature by then, and the initial customizable implementation might become obsolete anyway.
Understanding Product and Market
To write good code, developers must go beyond technical considerations and immerse themselves in the product and market landscape. This doesn’t mean becoming product managers or marketing experts, but it does involve understanding the broader purpose of the software. Who is the end user? What problem are they trying to solve? How does the product fit into the competitive market? These questions help developers align their technical efforts with the organization’s strategic goals.
Take, for instance, a company building software for small businesses to manage their finances. A developer who understands that small business owners value simplicity and reliability over cutting-edge technology might prioritize straightforward interfaces and robust error handling over implementing the latest AI-driven features. This doesn’t mean compromising code quality but making design and implementation choices that fulfill user needs and business priorities.
Enhancing communication
The flaw of every process is human error, period. Things get even worse when people need to communicate with each other to reach a common goal. That is why emphasizing effective communication greatly increases the likelihood of solving the right problems.
Get Rafał Ileczko’s stories in your inbox
Join Medium for free to get updates from this writer.
Bi-Directional Communication
In the onboarding example, the issue was the transfer of information from business people to developers. However, it is equally important for communication to flow the other way. Sometimes there is a need to implement something superficially simple, but for which the codebase was never prepared. Implementing the feature will be painful, and the resulting code will either be messy or take much time to write. In such cases, the development team must raise the issue with the business team, suggesting a simpler approach.
Ubiquitous Language
Business stakeholders and developers often speak different languages. That might cause inconsistencies in communication flow, leading to incorrect implementations. For that reason in Domain-Driven Design the term “Ubiquitous Language” was placed — a shared, precise language used by both technical teams (developers) and domain experts (business stakeholders), and in code, documentation, and communications. It ensures everyone involved in a project communicates effectively, avoiding misunderstandings. This alignment bridges the gap between business needs and technical implementation, making software reflect the real-world domain accurately and intuitively.
Understanding the business and effective communication differentiates an average developer from a great one. But those are not the only important aspects of writing good code.
Balancing Craftsmanship and Business Value
Aligning Expectations
One’s perfect code might be poor for another. The business context plays a significant role in defining what “good code” means. Startups, for example, are typically constrained by tight budgets and a need for rapid results. This means achieving quick outcomes is often preferred over stability. In such cases, a scrappy, “ugly but working” approach is not just acceptable — it’s frequently necessary. However, if the company expands significantly, the software error cost increases, which might result in changing expectations from “poor but working” to a stable, well-defined codebase.
On the other hand, big corporations, especially those in regulated industries such as finance or healthcare, have different priorities. Stability and risk mitigation are often more important than rapid iterations. Complex abstractions and architecture are acceptable or encouraged if they ensure long-term reliability and adherence to strict standards.
The key is to adapt the approach to match the business’s stage and context. The development team must evaluate whether the current focus is short-term agility or long-term sustainability. This doesn’t mean abandoning best practices but tailoring their application to the business’s needs, whether that’s speed, scalability, or compliance.
Avoiding Over-Engineering
Perfect code has its downsides. Over-engineering occurs when developers create overly complex solutions for a problem. While these solutions may look impressive and align with every “clean code” principle, future developers (including the original author) may struggle to understand or adapt the code, slowing progress.
The tendency to make every feature generic and reusable — a practice sometimes called “gold plating” — is a common trap and a type of over-engineering. While preparing for all possible future scenarios might be tempting, it often results in a bloated, harder-to-read codebase. Developers can spend time building features or abstractions that may never be used, increasing maintenance costs without delivering value.
The YAGNI principle (“You Aren’t Gonna Need It”) is very useful. It reminds developers to focus on current requirements and avoid unnecessary complexity. Solutions should be as simple as possible while still fulfilling the business need.
“Good code” balance between avoiding unnecessary complexity and ensuring the solution is robust enough to meet current and foreseeable needs.
Handling Technical Debt
So following the rules above, the development team writes not-so-perfect code, leading to a technical debt. It is an inevitable part of software development. While it often carries a negative connotation, not all technical debt is harmful. When managed deliberately, prioritizing speed or functionality over perfection can be a strategic decision. For example, accepting a certain level of technical debt can save time and resources, if a feature is unlikely to be revisited or modified soon. The problem arises when technical debt accumulates without proper control, affecting the maintainability and scalability of the entire system.
A pragmatic approach to managing technical debt involves constant supervision and refactoring. The development team should maintain a backlog of known debt and prioritize addressing it based on its potential impact on the business.
Conclusions
Good code isn’t just about craftsmanship — it’s about delivering value. Code represents a cost until a product is released and starts generating impact. While clean, maintainable code is important, it must always be placed within the broader goals of the business.
Developers who understand and balance technical excellence with business priorities set themselves apart. By aligning their work with the organization’s needs, they help ensure the product’s success—not just in terms of functionality but also in delivering value, meeting user expectations, and achieving long-term sustainability.
What about open-source library and framework development you ask? I’d say the same principles apply. There isn’t any business around it, but the core problem exists that contributors want to solve, and focusing on it, while keeping the codebase and project scope small is a good choice.
In the end, software engineering isn’t just about writing “perfect” code — it is about solving real-life problems, with or without code, and this should be the main focus.
Thanks for reading! Let us know your thoughts about writing a good code in the comments. :)










