If you recently read Sylwia Laskowska’s viral article “Nobody Writes Clean Code. We All Just Pretend,” you probably felt a distinct physical sensation: the massive weight of Imposter Syndrome lifting off your shoulders.
Her central thesis—that “clean code” is often a theoretical ideal that dissolves upon contact with reality—is a breath of fresh air. But once we stop pretending, what comes next? If we admit that we can’t write perfect code, does that mean we resign ourselves to chaos?
Absolutely not.
The alternative to “Clean Code” isn’t “Bad Code.” It is Pragmatic Code.
This post explores how to transition from the guilt of imperfection to the confidence of strategic engineering. We’ll look at why “messy” is sometimes a feature, how “Clean Code” rules can actually ruin software, and how to survive in a codebase that’s less like a cathedral and more like a Johannesburg taxi rank on a Monday morning.
1. The “Good Enough” Spectrum: Context is King
One of the most damaging aspects of the Clean Code movement is the implication that there’s a single standard of quality. We often judge a 50-line shell script meant to run once with the same moral gavel we use for a banking transaction engine.
Pragmatic engineering requires us to judge code by its Fitness for Purpose, not its adherence to a textbook.
The Three Tiers of Code Lifespan
The “Throwaway” (0-1 Month): This is the POC, the once-off migration script, or the hotfix.
- Goal: Speed.
- Acceptable Sins: Hardcoded values, copy-pasting, no tests.
- The Trap: As Sylwia noted, “The POC that accidentally became production.” The solution isn’t to over-engineer the POC; it’s to isolate it so it can be replaced easily later.
The “Feature” (1-2 Years): Most standard application code.
- Goal: Maintainability and readability.
- Acceptable Sins: Minor duplication (WET over DRY), modest test coverage.
- Strategy: Optimise for the junior dev who’ll read this next year, not the architect who designed it.
The “Core” (5+ Years): The foundational libraries or critical infrastructure.
- Goal: Stability and Performance.
- Acceptable Sins: Complex abstractions (if necessary for performance), rigid testing.
- Strategy: Here, and only here, is where “Clean Code” dogma is truly worth the cost.
2. When “Clean” Becomes “Obscure”
The article touched on the “Perfectionist Senior” who creates paralysis. This often happens when we prioritise Rules over Cognitive Load.
Consider the “DRY” (Don’t Repeat Yourself) principle. It’s often taught as a commandment. But blindly removing duplication often introduces Coupling.
Case Study: The “Clean” Abstraction vs. The “WET” Reality
The “Clean” Code:
A developer notices two functions look similar, so they merge them into one “Universal Handler.”
// The "Clean" Abstraction
// It handles everything! But what does it actually DO?
function processUserEntity(entity, type, options = {}) {
const isAdmin = options.force || checkPermissions(entity);
if (type === 'REGISTRATION' && !options.skipEmail) {
sendWelcomeEmail(entity);
} else if (type === 'UPDATE' && options.notify) {
sendUpdateEmail(entity);
}
// A generic saver that handles 5 different edge cases based on invisible flags
return database.saveGeneric(entity, {
table: type === 'REGISTRATION' ? 'users' : 'updates',
validate: !isAdmin
});
}
This code is “Clean” by some metrics—it’s short, and there’s no duplication. But it’s a nightmare to maintain. To change the registration logic, you risk breaking the update logic. You’ve created a knot tighter than the M1 during load shedding.
The Pragmatic Code:
The pragmatic engineer realises that Registration and Profile Updates are different business flows that happen to look similar right now. They choose to Write Everything Twice (WET).
// The Pragmatic Approach
// More lines of code? Yes. Easier to read? Absolutely.
function registerUser(user) {
if (!checkPermissions(user)) throw new Error('Unauthorised');
sendWelcomeEmail(user);
return database.users.add(user);
}
function updateUserProfile(user, isAdminOverride) {
// Logic specific to updates can evolve independently here
if (!isAdminOverride && !checkPermissions(user)) {
throw new Error('Unauthorised');
}
// Maybe we don't send emails for updates? Easy to change.
return database.updates.save(user);
}
Key Takeaway: Code is read 10 times more often than it’s written. If your “Clean Code” abstraction forces the reader to jump between 5 files to understand a single button click, it’s not clean. It’s just tidy obfuscation.
3. Technical Debt is a Financial Instrument
Sylwia mentioned that “Excel wins. Always.” Business pressure dictates deadlines.
We often talk about Technical Debt as if it’s a moral failing. It isn’t. It’s a tool. Just like a business takes a loan to expand, an engineering team takes on Technical Debt to hit a market window.
The problem isn’t the debt; it’s the Repayment Plan.
The “Containment Strategy”
If you must write “dodgy” code to meet a deadline (like the [enableSpecialMode]="true" hack), don’t let it infect the whole codebase.
Isolate the Hack: Wrap the messy logic in a single function or class with a clean interface.
Comment the Why: Don’t comment // This adds 1 to i. Comment // HACK: Marketing needs this by Friday. This bypasses the validation layer. See Ticket JIRA-123. Delete after Q3 campaign.
The “Boy Scout Rule” (Modified): You don’t have to clean the whole campground. Just pick up one piece of rubbish. If you touch a messy file, rename one variable to be clearer. Extract one complex conditional. Incremental improvement beats the mythical “rewrite.”
4. Psychological Safety: The Anti-Spaghetti Ingredient
The most profound point in the original article was about fear: “When developers are scared, they don’t improve things – they work around them.”
Bad code is often a symptom of a culture that punishes mistakes. If a developer is afraid that a Senior Engineer will roast them for a suboptimal loop, they’ll hide that loop in a utility function where no one looks.
To actually improve code quality, we must shift the tone of Code Reviews:
From: “This is wrong. Change it.”
To: “This works, but I’m worried it might be hard to debug later because of X. What do you think about approach Y?”
We need to normalise saying: “I know this isn’t perfect, but it’s safe and it solves the problem. Let’s merge it and ticket a cleanup task.”
Conclusion: Be Kind to Your Code (and Yourself)
“Clean Code” is a direction, not a destination. It’s the North Star. You navigate by it, but you don’t expect to actually land on a star.
Real-world engineering is about trade-offs. It’s about deciding that shipping a slightly messy feature today is better than shipping a perfect feature after the company has gone bankrupt.
So, embrace the mess. Write the comment explaining why the mess exists. Isolate the ugliness. And most importantly, forgive yourself for not being a machine. As Sylwia said, we’re all just pretending. And that’s the only way anything ever gets built.
Now go forth and write some lekker, pragmatic code!





Leave a Reply