Clean Code (Robert C. Martin) guide to produce and challenge code that is readable, durable, simple, and consistent. Covers naming, functions, comments, smells, and refactor heuristics. Complements `/solid` (SOLID principles) and `/anti-overengineering` (YAGNI/KISS). Activate during the REFACTOR phase of the TDD cycle and during implementation self-review.
التثبيت
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Clean Code (Robert C. Martin) guide to produce and challenge code that is readable, durable, simple, and consistent. Covers naming, functions, comments, smells, and refactor heuristics. Complements `/solid` (SOLID principles) and `/anti-overengineering` (YAGNI/KISS). Activate during the REFACTOR phase of the TDD cycle and during implementation self-review.
triggers
["clean code","readability","refactor","code smell","naming","intention.?revealing","boy.?scout","function too long","too many arguments","challenge.*code"]
Once the pattern is decided (/anti-overengineering) and responsibilities are placed (/solid), /clean-code makes intent self-evident.
The 5 pillars
1. SOLID Design — delegated to /solid
Activate /solid for SRP, OCP, LSP, ISP, DIP. Mentioned here only as a structuring reminder: clean code rests on well-placed responsibilities.
2. Readability first
"The ratio of time spent reading to writing code is well over 10:1. We are constantly reading old code as part of the effort to write new code." — Robert C. Martin
Naming (chap. 2)
Intention-revealing: the name should be enough to understand. If you write a comment to explain, the name is broken.
OK daysSinceLastReview — KO d, days, elapsed
OK filterMergedPullRequests(prs) — KO processPrs(prs, true)
No disinformation: accountList must be a List, otherwise accounts.
Perceptible distinction: getActiveAccount() vs getActiveAccounts() is a time bomb. Prefer getCurrentAccount() vs getAllActiveAccounts().
Searchable: short names only for short scopes (loop index = index in a 3-line loop — not i even though short).
No encoding: no Hungarian notation (strName, bIsActive), no I prefix for interfaces.
No flag arguments: render(isPublic: true) → renderPublic() + renderPrivate().
No hidden side effects: a function named checkPassword(user, password) that ALSO resets the session is a trap.
Command-Query Separation: either the function modifies state, or it returns info. Not both.
Prefer exceptions to error codes: for invariants, throw a typed BusinessRuleViolation. No return null or return { error: ... } smuggled as control flow. Use discriminated unions ({ status: 'success' | 'failed' }) for expected outcomes (cf. coding-standards.md § Error Typing).
Comments (chap. 4)
"The proper use of comments is to compensate for our failure to express ourself in code." — Martin
Project rule (CLAUDE.md): zero comments except if vital. Self-documenting code first.
Code rephrased in prose (// fetch the user above const user = ...)
Formatting (chap. 5)
Variables close to their usage: no grouped declarations at the top of a function.
Newspaper metaphor: top of the file = overview (main exports), bottom = details (private helpers).
Top-down readability: calling functions above called functions.
3. Sustainable quality
"Leave the campground cleaner than you found it." — Boy Scout Rule
Boy Scout Rule: each touched file should be slightly cleaner. Renaming a confusing variable adjacent to the diff scope = OK. Out-of-scope structural refactor = NO (cf. scope-discipline.md).
TDD as quality guard rail: refactor ONLY with green tests. If no tests cover the touched area, write a characterization test before.
Method manipulates more attributes of another class than its own
Move the method
G15 Selector Arguments
Booleans/enums that choose a behavior
Split into multiple functions
G20 Function Names Should Say What They Do
Must read the body to know
Rename
G23 Prefer Polymorphism to If/Else Chains
Switch on a type
Polymorphism or mapping object
G28 Encapsulate Conditionals
if (a && !b && c.isExpired())
Extract as if (shouldRemove(x))
G30 One Thing
"This function does X and Y"
Split
G34 One Level of Abstraction
Mix orchestration + detail
Extract the detail
G35 Magic Numbers
if (count > 7)
Named constant MAX_RETRIES
4. Simplicity
Delegated to /anti-overengineering: YAGNI, KISS, do not anticipate hypothetical business.
Clean Code side-effects:
No "just in case" parameters. A function has only the parameters it needs now.
No dead code: if a function is no longer called, delete it. git log is the history.
No speculative abstraction (AbstractBaseFactoryProvider) for a single use case.
5. Consistency
One convention per context: if the module uses entitiesById: Record<id, Entity>, the neighbor should too. No mixing Map<id, Entity> in the same Bounded Context.
Project patterns to respect (cf. coding-standards.md):
Gateway = interface (port) in entities/ + impl (adapter) in interface-adapters/gateways/
Use case = class implementing UseCase<Input, Output> interface
Controller = transforms inbound events into use case calls, no business logic
Presenter = pure function (domainData) => viewModel
View = Humble Object (zero logic, render only)
Factory usage: factories in src/tests/factories/ are mandatory for test data. Never hardcoded.