The Art of Writing Clean Code

You will read this function far more often than you wrote it, and most of those readings will happen while something is broken and someone is waiting. Clean code is not aesthetics. It is reducing the cost of the next change.
Naming Is the Cheapest Documentation
A name should answer why, not what. data, temp, and result describe nothing. Booleans read best as questions, functions as verbs, and collections as plurals. Avoid abbreviations that only make sense to whoever typed them first.
```js
// Before
function proc(d, f) {
const r = [];
for (const x of d) if (x.s === 1 && x.t > f) r.push(x);
return r;
}// After function findActiveOrdersAfter(orders, cutoffDate) { return orders.filter( (order) => order.status === Status.Active && order.createdAt > cutoffDate ); } ```
The second version needs no comment. That is the goal: comments should explain why a decision was made, because the code already explains what it does.
Guard Clauses Over Nesting
Deep nesting forces the reader to hold conditions in their head. Handle the exits first and let the main path sit unindented at the end.
```js
function publish(article, user) {
if (!user.canPublish) throw new ForbiddenError();
if (!article.title) throw new ValidationError('title required');
if (article.publishedAt) return article;return repository.publish(article.id, { publishedAt: new Date() }); } ```
One Level of Abstraction Per Function
The common smell is a function that validates a payload, formats a currency string, and issues an HTTP request. Each is fine; together they mean the function has three reasons to change and cannot be tested in isolation. If you cannot name a function without using and, it is doing more than one thing.
Make Illegal States Unrepresentable
The strongest form of clean code is code where the mistake will not compile. A status enum beats three loosely coupled booleans. A required constructor parameter beats a comment saying you must call init first. Types and structure enforce invariants that documentation only requests.
Habits That Compound
- Replace magic numbers with named constants. 86400 means nothing; SECONDS_PER_DAY is self-explanatory.
- Keep parameter lists short. Beyond three, pass an object with named fields and stop worrying about argument order.
- Delete dead code instead of commenting it out. Version control already remembers.
- Write the test that reproduces the bug before fixing it, so the bug cannot return quietly.
- Leave the file slightly better than you found it, but keep refactoring in separate commits from behaviour changes so reviewers can follow both.
The Limit
Clean is contextual, not absolute. A prototype validating an idea should not carry a full abstraction layer, and extracting every three-line block into its own function makes code harder to follow, not easier. Optimise for the reader who arrives in eight months with no context, and stop there.
Enjoyed this article?
Share it with your network and join the conversation.