Skip to content
All posts

Does “Clean Code” Exist?

April 16, 2026·Read on Medium·

I have read the book. I have followed the rules. I have also inherited systems that followed the rules and were impossible to work with.

A client handed me a Laravel codebase two years ago. The previous developer was proud of it. Every function was under 20 lines. Every class had a single responsibility. Comments were almost nonexistent because “the code explains itself.” Variable names were long and descriptive. It was, by every metric the book defines, clean.

I spent four days trying to understand how a payment status update worked.

The logic was spread across eleven classes. Each class did exactly one thing. Each function called another function which called another function. To trace a single operation I had to open seven files, hold the call stack in my head and pray I did not lose the thread. The code was not readable. It was a treasure hunt with good variable names.

That was the moment I stopped treating Clean Code as doctrine.

What the Book Actually Says

Robert C. Martin published Clean Code: A Handbook of Agile Software Craftsmanship in 2008. It is a real contribution to the field. I am not here to dismiss it.

The core rules are these. Functions should be small, ideally under 20 lines, with some interpretations pushing for 2 to 6 lines. Functions should do one thing. The ideal number of arguments is zero, then one, then two. Three is already pushing it. Comments are a failure to express intent in the code itself. Classes should have a single responsibility. Duplication is the enemy.

These are not bad ideas. In isolation, most of them are correct.

The problem is not the rules. The problem is what happens when developers treat them as a checklist without asking what problem each rule was trying to solve.

“Clean” Is Not a Property of Code

When someone says code is clean, they mean something. But they rarely mean the same thing as the person next to them.

To a junior developer, clean code is code they can read without getting lost. Short functions help here. Descriptive names help. Comments sometimes help more than the book admits.

To a senior developer maintaining a system under load, clean code might mean code where the data flow is traceable. Where you can understand what happens at the database level without reading six layers of abstraction. Where a query is a query, not a method that returns a builder that calls a scope that joins through a repository.

To a performance-sensitive system, clean code might mean code that does not pay the cost of dozens of function calls for work that could be done in one loop. Abstraction has overhead. Every additional layer of indirection is a cache miss waiting to happen. This is not hypothetical. It shows up in profiler output on systems under real load. The book was written primarily for enterprise Java in the late 2000s. That context matters.

To the developer who inherits your system in three years, clean code is code where the business logic is findable. Not distributed. Not abstracted into oblivion. Findable.

These are not the same definition. They produce different code. All of them are valid depending on what the system needs.

The Abstraction Trap

The rule that causes the most damage in practice is the function length rule taken to its extreme.

The logic sounds right: small functions are easier to understand, test and reuse. If a function does one thing, you know exactly what it does. Compose them and you build complex behaviour from simple parts.

The problem is that beyond a certain point, decomposition does not reduce complexity. It redistributes it.

When you split a 40-line function into eight 5-line functions, you have not made the code simpler. You have made each individual piece simpler while making the overall system harder to follow. The complexity lives in the relationships between the pieces now, not inside any one of them. And relationships are harder to read than sequential code.

The codebase I inherited had a processPayment method that called validatePaymentContext, which called assertPaymentEligibility, which called checkAccountStatus, which called resolveAccountState. Each function did one thing. Together, they made it impossible to understand what "process a payment" actually meant without reading all five and mentally assembling the steps.

A 35-line function with clear inline comments would have been faster to read, easier to modify and far less likely to introduce a bug when one of those seven levels needed to change.

Where the Rules Do Apply

I am not saying throw the book away.

The naming advice is genuinely good. Meaningful names at the right level of abstraction save hours of confusion. $u is not acceptable. $user is fine. $authenticatedUserWithActiveSubscription is probably overcorrecting.

The duplication rule is correct. Code that exists in two places will diverge. That is not philosophy, it is statistics.

The comment advice, qualified, is useful. Comments that restate what the code does are noise. Comments that explain why a decision was made, especially a non-obvious one, are gold. There is a difference between:

// increment counter
$count++;

and

// payment gateway requires fixed-length order reference, pad to meet spec
$reference = str_pad($orderId, 12, '0', STR_PAD_LEFT);

The second comment is not a failure. It is the only way a future developer will know not to remove that padding.

The single responsibility principle is correct at the right scale. A class that handles authentication, sends emails and generates PDFs is a problem. But a function that validates input, applies business logic and returns a result is not necessarily violating anything meaningful.

The Real Question Nobody Asks

When someone says your code is not clean, the useful response is not to defend your line count. It is to ask: clean for whom?

Clean for you, six months from now, to debug at 11pm when something breaks in production?

Clean for a junior developer joining the project next quarter?
Clean for the next contractor who will maintain this after you?
Clean for the database engine that will execute your queries?

These are different answers. A codebase optimised for readability to an expert might be hostile to a junior. A codebase optimised for performance might be unreadable to both. A codebase that follows every rule in the book might be a nightmare to extend when requirements change, which they always do.

The book does not tell you which one matters. It assumes they are all the same problem. They are not.

What I Actually Do

I have stopped asking whether my code is clean. I ask three questions instead.

Can someone unfamiliar with this system understand what this code does in under five minutes? Not the whole system. This function, this class, this service. If the answer is no, something is wrong regardless of what the style guide says.

If I need to change one business rule, how many files do I touch? More than three is a signal. More than five is a problem. Not because of any principle, but because every file you touch is a file that can break.

Does this code reflect how the business actually works? The most unreadable code I have ever seen was technically correct, well-structured and followed every naming convention. It was also written to reflect a class hierarchy that had nothing to do with how the business thought about its own data. The abstraction was clean. The model was wrong.

The Book Was a Starting Point

Clean Code gave the industry a shared vocabulary. Before it, “this code is bad” was an argument. After it, you could point to specific patterns, name them and discuss them. That is valuable.

But shared vocabulary became dogma. Developers started failing code reviews not because the code was hard to understand, but because a function exceeded 20 lines. Teams adopted the rules without understanding the reasoning. Juniors learned to split functions not because it made the code better but because the book said small is good.

The irony is that the book’s own examples have been criticised on exactly these grounds. Some of the refactored code in the later chapters is harder to follow than the original. The rules, applied mechanically, produce exactly the kind of code the book was trying to prevent: code that is technically correct and practically difficult.

Clean code is not a state you achieve. It is a set of tradeoffs you make deliberately, for a specific team, a specific system and a specific moment in the project’s life.

The rules in the book are inputs to that decision. They are not the decision.

Found this helpful?

If this article saved you time or solved a problem, consider supporting — it helps keep the writing going.

Originally published on Medium.

View on Medium
Does “Clean Code” Exist? — Hafiq Iqmal — Hafiq Iqmal