DEV Community

Cover image for Tale of Good Code
Adam Bright
Adam Bright

Posted on

Tale of Good Code

Introduction

People still argue about what "good" code is, as if it weren't an endless kaleidoscope of tastes and opinions, where every new trend seems revolutionary until it gives way to yet another "innovative" approach.

Good code isn't a set of oft-mentioned buzzwords like "maintainable," "scalable," or "intuitive." It's simply code that gets the job done: neatly feeding mocks into tests, swiftly and transparently solving the problems posed by business requirements, and managing not to unleash chaos on tech support.

So what are the criteria? Everything changes as soon as a new requirement, a new framework, or a fresh bug report from management appears. Readability? For a minute, forget that its assessment is nothing more than a subjective opinion, similar to the taste of those who, until the very end, argue over what’s better: tabs or spaces. Simplicity? As long as your code isn’t summoning your GPU to the basement, consider the task done. Maintainability? If a second-shift developer can at least guess what your code does and why within a week, you’re in the clear.

It’s no wonder that in this endless, disputable debate about quality standards, one might drown. Most people fail to notice that the main purpose of the code is to meet real-world requirements, not to delight the souls of those who spend their lives running endless lint marathons and code reviews. If your program works and the client is happy with
it—congratulations, you've already won the Olympic games of genius.

So, esteemed would-be code philosophers, perhaps it's time to stop arguing about trivialities? Let’s instead learn to understand: good code is not an aesthetically pleasing collection of rules, but, above all, a working tool that works miracles despite the peculiarities of the world and the whims of business. After all, in the end, it's not magic or art
that matters, but simply a job well done in a timely and quality manner.

Good Code

Examples of Describing Good Code

Debates about what constitutes good code have been raging for decades. Various developers have offered their definitions, and below are the most well-known approaches:

1. Clean Code — Robert Martin

In his book "Clean Code: A Handbook of Agile Software Craftsmanship" 1, Martin emphasizes that good code should be comprehensible, simple, and easily maintainable. He focuses on principles of readability, simplicity, and the avoidance of duplication.

2. SOLID Principles — Robert Martin

The five SOLID principles 2 (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion) help create flexible and maintainable code that can easily adapt to change.

3. Code That Solves the Problem — Kent Beck

Kent Beck, in the context of testing and software development, stresses that good code must efficiently address the tasks at hand, pass tests, and withstand the blows of reality.

4. Code That Is Easy to Read and Maintain — Martin Fowler

In his book "Refactoring: Improving the Design of Existing Code" 3, Fowler highlights the importance of regular refactoring and creating code that can be modified painlessly.

5. The DRY Principle (Don't Repeat Yourself) — Martin Fowler

The DRY principle 4 urges us to avoid code duplication, thereby reducing the likelihood of errors and easing maintenance.

6. The KISS Principle (Keep It Simple, Stupid) — Various Authors

The KISS principle 5 dictates that systems should be as simple as possible, and any additional complexity should only be introduced when absolutely necessary.

Common Characteristics of Good Code

After analyzing various claims about good code, the following general characteristics can be identified:

  1. Readability

    • Clarity: The code should be comprehensible and "talkative."
    • Consistency: Use of uniform styles and naming conventions.
    • Commenting: Presence of comments to explain the trickiest parts.
    • Structure: Logical organization of code (e.g., through functions and classes).
  2. Simplicity

    • Minimalism: Avoiding unnecessary complexity and superfluous functions.
    • KISS: Keeping solutions and architecture simple.
    • DRY: Eliminating duplicated code, because repetition is the mother of all errors.
  3. Maintainability

    • Modularity: Code is divided into independent, easily replaceable modules.
    • Testability: The ability to easily write tests (e.g., unit tests).
    • Refactoring: The potential to improve the structure of code without changing its functionality.
  4. Efficiency

    • Performance: Code optimization for fast execution.
    • Resource Usage: Effective use of memory and other resources, without overdoing it.
  5. Security

    • Error Handling: Proper management of exceptions and errors so bugs don’t turn into catastrophes.
    • Data Protection: Preventing leaks and unauthorized access to information.
  6. Documentation

    • Technical Documentation: Detailed descriptions of the code’s architecture and usage.
    • Automated Documentation: Tools for generating documentation (e.g., godoc).
  7. Standards Compliance

    • Coding Standards: Adherence to widely accepted recommendations (e.g., effective Go 6).
    • Static Analysis: Using linters to check code quality to make sure bugs don’t get a chance to hide.

A Detailed Look at Key Characteristics and Why It's All a Bunch of Nonsense

1. Readability

Code readability is a subjective concept; what one programmer finds clear, another might find utterly confusing.
Consider our examples:

          global    _start

          section   .text
_start:   mov       rax, 1
          mov       rdi, 1
          mov       rsi, message
          mov       rdx, 13
          syscall
          mov       rax, 60
          xor       rdi, rdi
          syscall

          section   .data
message:  db        "Hello, World", 10
Enter fullscreen mode Exit fullscreen mode

Assembly code often appears "grainy" and demands deep knowledge of the processor architecture and assembly instructions.
For a specialist used to high-level languages, such code might seem completely unreadable—even if the structure is quite simple: system calls, register usage, and jumps. Yet for a programmer who regularly works with low-level code, this style might be entirely familiar.

Now let’s compare it with a Python example:

def f(n):
    return (
        1 if n < 2
        else n * f(n - 1)
        if (lambda x: x % 2 == 0)(n)
        else (lambda x: x * f(x - 1))(n - 1)
    )


def g(x):
    return (
        (lambda y: y + 1)(x)
        if x < 5
        else (lambda y: y - 1)(x)
    )


def h(a):
    return [g(i) for i in range(a)]


print(h(f(5)))
Enter fullscreen mode Exit fullscreen mode
def factorial(n):
    if n < 2:
        return 1
    return n * factorial(n - 1)


def adjust_value(x):
    if x < 5:
        return x + 1
    return x - 1


def generate_adjusted_list(a):
    return [adjust_value(i) for i in range(a)]


result = generate_adjusted_list(factorial(5))
print(result)
Enter fullscreen mode Exit fullscreen mode

In the first example, the same operations (such as calculating a factorial or adjusting a value) are expressed through nested ternary operators and lambda functions. This style might appeal to those who value brevity and functional programming. However, for most developers, such code can be hard to grasp, as the convoluted logic and nested calls make it difficult to understand the author's intent.

The second example is structured much more clearly: functions have meaningful names (factorial, adjust_value, generate_adjusted_list), and the logic is expressed with usual if/else conditionals. For most programmers, this style appears more "readable" because it follows the common logic without unnecessary nesting or abstraction.

The main point: Readability isn’t so much about following a rigid set of rules (e.g., the AirBnB guidelines for JS) as it is about how familiar a developer is with the semantic and style of the code. If you're used to reading functionally compact code with lambdas and ternaries, you might not have any issue with the first example. But if you prefer the traditional imperative style, where functions and variables have self-explanatory names, the second example will be much clearer.

Experience and habit. What is readable to one programmer might be challenging for another. The context and domain matter. In some cases, brevity and compactness are key, while in others, clarity and explicit logic division are more important. Ultimately, the sensible approach is to choose a style not only matching personal preferences but also
meeting the expectations of the people who will maintain and develop the code later. Blindly following guidelines might lead to code that adheres to some “canon,” but if the team is used to another style, the effect will be the opposite.
There is no universal solution. Readability is a delicate balance between widely accepted practices and the specific features of a project and team.

2. Simplicity

Simplicity in code is judged not by its appearance but by its clarity. People often confuse a sleek look with internal complexity. Consider two examples:

const user = db.collection('users').find({
    id: new UUID('507f1f77bcf86cd799439011')
});
Enter fullscreen mode Exit fullscreen mode
const user = getUsersService().getUserById('507f1f77bcf86cd799439011');
Enter fullscreen mode Exit fullscreen mode

What might be hiding behind a “simple” wrapper?

  1. Hidden logic and infrastructure.

    The function getUserById might look like a simple wrapper, but inside it could be handling extremely complex
    processes:

    • Deduplication of requests. If several data requests come in simultaneously, the service may group them to avoid unnecessary database calls.
    • Caching. Before querying the database, the function might check if the needed user is already stored in a fast cache, significantly boosting performance.
    • Permission checks and authorization logic. The wrapper may automatically verify that the user has permission to access the requested data.
    • Query building and input validation. Builders and validators that ensure the query is correct might be employed here, and their code can be quite voluminous.
  2. Simplicity is a myth.

    In the first example, the code directly accesses the users collection in the database. At first glance, it seems "
    low-level," simple, and transparent, but it requires the developer to understand the intricacies of database
    interactions, the correct data format (for instance, how exactly a UUID should be passed), and manual control of
    all query aspects.

  3. Services and abstractions don’t magically simplify code.

    Using a service layer (as in the second example) can hide all the complex logic behind a straightforward and brief
    interface. However, that doesn’t mean the logic itself has become simpler—it’s just encapsulated elsewhere and may
    perform a host of hidden operations critical to the application’s correct functioning.

  4. Comparison and conclusion.

    • Simple syntax does not guarantee simple logic. The getUserById wrapper looks much easier to read than a direct database call, but behind that "pretty wrapper" there might be a host of mechanisms aimed at improving performance, security, testing convenience, and code maintenance.
    • Only the surface appears simple—not the depth. Think of it like mythical creatures: unicorns only exist in your damp dreamy fantasies. What the developer sees on the surface doesn’t always reveal the full complexity of the underlying processes.
    • Unicorns? If you’re still hung up on unicorns, I suggest you take a three-minute or so break from this article and clear your cluttered mind of distracting notions.

Ultimately, you must understand that simple code is a myth. There is always another level of abstraction. And, as the saying goes, any problem can be solved through abstraction—except the abstraction problem itself.

3. Maintainability

Maintainability is, essentially, how much time and nerve it takes to implement changes, adapt the code to new requirements, fix bugs, or add new features. But let’s break down why the idea of “maintainability” often turns out to be a myth—a myth cooked up by old, sweaty C++ programmers in their garages, clinging to the idea that code can be easily changed in the future, even if requirements suddenly do a 180 and hit those morons right in the nuts.

Why Maintainability Is a Legend
  1. Constant changes and deadlines

    In a world where AGILE processes, meetings, and urgent client requests dictate the rules, developers can spend entire
    days “juggling” new features without even having a chance to ensure the code is architecturally and aesthetically
    perfect.

    • The code changes so quickly that the perfect design conceived at the start becomes obsolete after a couple of sprints.
  2. Old architecture versus new requirements

    What was considered a convenient solution yesterday may become completely incompatible with the new business needs
    today.

    • Old architectural choices start “falling apart” when new functions are added, and investing in refactoring often deals a heavy blow to the schedule.
  3. Quality degradation over time

    Rapid changes, often bypassing proper checks, lead to code that was once pristine turning into a developer’s
    nightmare, where fixing one bug triggers a cascade of unforeseen consequences.

    • “Maintainability” becomes a comforting word frequently used when a system, over years of operation, ends up laden with half-baked fixes, crutches, and “kludges” (code that no one wants to touch).
  4. Financial losses and legal risks

    Neglected code can become a source of vulnerabilities, leading to data leaks, performance drops, and even lawsuits if
    something goes wrong.

    • Neglecting quality for the sake of a quick release can spell disaster for the business.
What Really Matters in Practice

Experience shows that instead of striving for the chimera of “maintainability,” it's crucial to have true professionals
who can sift through what others call "horse manure" (a.k.a. code), and even more importantly, know how to say “no” when a feature or change threatens to destroy everything you’ve been overtime-ing for across the last ten epics. Hail SCRUM and its creator (no, really)!

  • Programmer skills:

    The best asset is the person behind the code—someone who can quickly assess its state and figure out how best to
    improve or modify it. An experienced developer knows that behind “clean” code might hide a bunch of adaptations,
    compromises, and clever tricks, and knows how to work with that. This is far more practical than clinging to
    theoretical maintainability.

  • The role of business analysts and managers:

    They often demand changes based on short-term business needs, ignoring the depth and interconnectedness of different
    parts of the system. Here, it’s critical for developers to be able to stand up for technical boundaries and
    convincingly argue why everything shouldn’t be changed “on the fly.” Although sometimes, saving your ass from getting
    fired is the top priority.

Maintainability isn’t a magic button that makes the whole development process easy and painless. It’s a constant balancing act among business requirements, time, resources, and technical debt. Code, like any complex system, requires constant attention: refactoring, testing, optimization, and a clear understanding that sometimes you simply must say “no” to avoid gluing yet another layer onto an already entangled system.

So if you still believe in mythical maintainability, remember: real development strength is the ability to navigate complexities, see the labyrinth of processes behind the pretty interface, and, when needed, resist the onslaught of business demands. That is true competence in the programming world.

4. Efficiency

Efficiency and speed of code are important, but often overdoing optimizations is a road to nowhere—especially in interpreted languages. Let’s go over several points.

Micro-Optimizations

If you're writing in JavaScript or, heaven forbid, Python, trying to save a few microseconds on a particular piece of code is absurd. These languages already have inherent overheads far more significant than your attempts to swap a for loop for a list comprehension. Remember that most of the web request processing time is consumed by database queries.

Even when using compiled and fast languages, such as Go, Rust, or Zig, attempts to speed up the "hot spots" might either yield negligible gains or, on the contrary, render the code unrecognizable by adding some inexplicable "esotericism" that ultimately slows down the entire system and future development.

Less Code - Less Time

If the goal is for the code to run faster, just write less code! Every extra line, especially if it adds its own abstractions or overhead, can negatively impact performance. For a more resource-efficient solution, consider choosing low-level languages where you directly control resources and can achieve maximum optimization for the specific hardware.

No matter what ultra-cool algorithm you use in your project, it will never be faster than its absence. If you can remove something and still get the same result, you’ve found the optimal efficiency solution.

Measure Seven Times, then Go for a Walk Once

Claiming one approach is faster than another without conducting before/after measurements is completely pointless.
Optimization should start with profiling: measure where resources are being spent, and only then decide what and how to change it.

Everything must be measured in the context of real conditions: specific hardware, an actual dataset, and defined business requirements. Without that, any claims of optimality remain speculative.

Testing Against Reality

Writing two million lines of Python code and expecting your application to run like "a perfect stallion" is nonsense.

Optimization only makes sense where it’s truly needed. If the system runs fast enough and its throughput meets expectations, over-optimizing is just wasted effort—time spent on "optimizations" could be better invested in developing new features or improving code quality in other areas.

5. Security

Do you really need an explanation? Seriously? Go read OWASP 7 or something...

Security shouldn’t be a selling point of good code. It just needs to be there. Period. If you believe you can achieve 90% secure code and enjoy that, please step into this chamber. Something smells fishy? Don’t worry, we haven’t received a single negative review yet.

6. Documentation

Documentation is undoubtedly important, but it doesn’t compensate for the lack of good code. You can document every nuance. But let a new developer read the most detailed documentation—even if each method or function has a comprehensive description—if upon opening the first file they see raccoons rummaging through a trash can, no amount of comments or instructions can fix that.

Perfect but outdated documentation is an even bigger nightmare than having none at all.

Key Points:
  1. Code Comes First.

    Documentation is like a navigational map. But if the terrain (the code) looks like ruins, even the most detailed map
    won’t help you figure out how to get to your destination.

    • If the code is well-structured, readable, and logically divided into modules, the documentation becomes merely a pleasant bonus.
    • If the code itself is a jumbled mess of hacks and chaos, the documentation can only highlight that contrast.
  2. Documentation Relevance.

    You need to document everything, but if the documentation isn’t updated alongside code changes, it loses its value.

    • Constantly updating documentation is as vital as maintaining the code itself.
    • Perfect documentation isn’t a static artifact—it’s a living entity that evolves with the product.
  3. Code is the Project’s Face.

    When a new developer starts exploring a project, the first thing they look at is the code.

    If they find strangeness there, their trust in the project will wane, even if every method or function is accompanied
    by a detailed explanation.

    • Good code should "speak for itself."
    • Documentation should serve as a helpful tool, not a way to cover up architectural or implementation shortcomings.
Conclusion:

Documentation is an important component that helps you understand how the system works, but it by itself does not make code good. Ideal comments and detailed descriptions cannot mask chaos in the source code.

In the end, if you ensure that documentation reflects the state of the program and that the code is clear and logical, you are creating a truly quality product. But if your code looks like a tangle of unorganized text and hacks, no amount of detailed commentary will change the bitter truth.

7. Standards

Standards indeed play an important role—they help minimize internal team disputes, ensure a basic level of uniformity, and simplify the integration of various components. However, standards on their own are far from perfect:

  1. Standards Are Never Ideal.

    Just look at how many data exchange protocols, cable connectors, and various JavaScript libraries exist today. Every
    standard, be it an established practice or a modern trend, has its limitations and can’t satisfy absolutely every
    need of different teams and projects.

  2. Rigid Adherence to Standards.

    By following any given standard, you can significantly reduce debates, even if not everyone loves it unconditionally.
    But in doing so, you deprive yourself of the opportunity to express a creative approach or implement something new if
    the standard doesn’t consider your realities.

  3. A Compromise-Based Approach.

    The ideal is not blind adherence to a standard, but a conscious choice: use it to reduce conflicts, yet remember that
    sometimes you can and should suggest improvements. No one is saying you must be dogmatic or reject everything new.
    The key is to maintain a balance between the compromises necessary for teamwork and the critical thinking needed to
    improve processes.

  4. Emphasis on Constructive Change.

    In reality, adhering to standards isn’t the ultimate goal—it’s a way to simplify communication. If a standard doesn’t
    meet your needs, think about adapting it. Yes, this might lead to further debates, but through constructive disputes
    and experiments, innovative approaches are born.

Follow standards if they help your team work together, but don’t expect them to magically make your code perfect.
Standards are merely tools to ease communication and maintain a unified style. They cannot replace common sense, professionalism, and the desire to constantly improve your solutions. Remember: when a standard begins to hinder development, it might be high time to give a little "kick" to those who set it—in spite of the fact that you might have been its initiator.

Not a Post, Not a Scriptum

This article was written and translated with the support of the ChatGPT o3-mini neural network.


  1. Clean Code  

  2. SOLID Principles  

  3. Refactoring  

  4. Don't Repeat Yourself  

  5. KISS Principle  

  6. Effective Go  

  7. OWASP 

Top comments (0)