Based on Robert C. Martin's "Clean Code" full book, 17 chapters + Appendix A + the 66-item list of smells/heuristics (ch17). Primary corpus: github.com/glen9527/Clean-Code-zh (Chinese-English bilingual translation, research date 2026-07-01).
When not to use (use another skill)
See the "Dual-Mode Workflow" below for the mode decision table; for the following scenarios, go elsewhere:
- Architecture selection / system design →
architecture-design - Performance optimization / bottleneck analysis →
perf-optimization - Rewriting / modernizing legacy systems → code-modernization series
Core philosophy (5 points, the book's overall thesis)
- Boy Scout Rule: Check in code cleaner than when you checked it out (ch1.6). No need for a big refactor; a small improvement each time is enough.
- Read >> Write. "We are authors"—code is read far more often than it is written (ch1.5). Optimize for "reading smoothly," not for "writing quickly."
- Four Rules of Simple Design(Kent Beck, in decreasing order of importance, ch12):
- Passes all tests
- No duplication
- Expresses intent
- Fewest classes and methods (this is the brake, preventing over-abstraction)
- Clean code does one thing(Bjarne Stroustrup's definition, ch1.3.5): elegant, direct logic (bugs are hard to hide), minimal dependencies, complete error handling, near-optimal performance.
- Compounding chaos: Bad code "tempts" people to make it worse with each change (ch1.3); cleanliness is the only barrier that stops chaos from compounding.
Rule system
Reference numbers (C1/E2/F3/G5/N4/T7...) = the 66 items in the ch17 list of smells and heuristics; chapter numbers (chX.Y) = chapters of the original book. During review, cite by number first for easier location.
Naming (ch2 · N1-N7)
| Rule | One sentence | Number |
|---|---|---|
| True to its name | The name conveys the meaning; no comment is needed to complete it | 2.2 |
| Avoid misinformation | Don't use accountList unless it is a List type; don't use names with similar spellings |
2.3 / N4 |
| Meaningful distinctions | a1/a2、ProductInfo/ProductData is a meaningless distinction |
2.4 |
| Pronounceable | genymdhms won't do,generationTimestamp will |
2.5 |
| Searchable | Single-letter names only in short scopes; long names for long scopes (N5) | 2.6 / N5 |
| Avoid encodings | Reject Hungarian notation / member prefix m_ (N6); don't add I prefix to interfaces |
2.7 / N6 |
| One word per concept | fetch/get/retrieve choose one and don't mix them |
2.12 |
| No puns | add if it means "add value," don't use it for "add item" (use append) |
2.13 |
| Prefer solution domain names | CS terms are acceptable (AccountVisitor); problem domain names come second |
2.14 / 2.15 |
| Name describes side effects | getName should not hide connection side effects (N7) |
N7 |
| Don't be cute | HolyHandGrenade is not as good as DeleteItems |
2.11 |
Functions (ch3 · F1-F4, G30/G34)
- Small (3.1): 20 lines or fewer is ideal, indentation ≤ 2 levels. An overly long function = a signal of confused abstraction levels.
- Do one thing (3.2 / G30): If a function can be further divided into "sections" → it does more than one thing, split it.
- One level of abstraction (3.3 / G34): Don't mix high-level concepts with implementation details. Read top-down like prose (Stepdown Rule).
- Replace switch with polymorphism (3.4 / G23): Scattered switch = violates OCP, consolidate with polymorphism.
- Parameters (3.6 / F1):
- Ideal 0 > 1 > 2; 3 or more should be wrapped in a parameter object (3.6.5)
- No flag parameters (3.6.2 / F3): A boolean input = the function does two things, split into two functions
- Unary functions use verb+noun
writeField(name); binary use verbassertExpectedEqualsActual
- No side effects (3.7 / F2):
checkPasswordshould not incidentallyinitializeSession. Output parameters (F2) are a side-effect smell. - Command-query separation (3.8):
setchanges state /getreads state, don't mix. A function either does something or answers something, not both. - Exceptions over error codes (3.9): Extract try/catch into a separate function (error handling itself is "one thing").
- Remove duplication (3.10 / G5): DRY is the 2nd principle of simple design.
Comments (ch4 · C1-C5)
Comments cannot beautify bad code (4.1). If it can be expressed in code, don't comment.
Good comments (4.3): Legal information / providing information / explaining intent / clarification / warning of consequences / TODO / amplifying significance / public API Javadoc.
Bad comments (4.4):
- Mumbling (4.4.1), redundant (C3:
i++; // increment i), misleading, mandated, journal, noise (4.4.6), position markers (4.4.9), attribution,commented-out code (C5: don't leave it, source control will remember) - Inappropriate information (C1: change history, author, SPR number don't go in comments—those belong to the issue tracking system)
- Obsolete comments (C2) are worse than no comments
- If it can be replaced by a function or variable, don't comment (4.4.8)
Formatting (ch5)
- Vertical openness (5.2.2): Separate concepts with blank lines
- Vertical closeness (5.2.3): Related code stays close together, don't separate with blank lines
- Vertical distance (5.2.4): Variables near their declaration; private variables at the top of the class; private functions right after their first call; conceptually related things close together
- Horizontal density (5.3.1): Spaces separate operators and parameters
- Indentation (5.3.3): Never violate it, violating it = a breeding ground for bugs
- Team rules > personal style (5.4): Consistency matters more than "correctness"
Data, objects, classes, systems (ch6 · ch10 · ch11)
- Data abstraction (6.1): Hide the implementation, don't just add getters/setters that expose the internals
- Objects / data antisymmetry (6.2 / G6): Objects hide data and expose behavior; data structures expose data and have no behavior. Don't create "hybrids".
- Law of Demeter (6.3 / G36): Avoid
a.getDept().getManager().getName()train wrecks; a module shouldn't know the internals of the objects it operates on - DTO (6.4): Pure data transfer objects OK; Active Record is a hybrid, use with caution
- Classes (ch10): Single Responsibility Principle (SRP), high cohesion, low coupling, open for extension / closed for modification (OCP); classes should be short, like functions
- Systems (ch11): Separate construction from use; dependency injection; defer decisions until needed; localize decisions
Error Handling and Boundaries (ch7 · ch8)
Error Handling:
- Exceptions rather than return codes (7.1)
- Write try-catch-finally first (7.2): define error boundaries before filling in the normal path
- Prefer unchecked exceptions (7.3): checked exceptions violate OCP
- Exceptions carry context (7.4): operation + failure type + stack trace
- Define exception classes based on caller needs (7.5)
- Special Case Pattern (7.6): define the normal flow, encapsulate the exceptional path as a special case object
- Don't return null (7.7): return Optional / empty collections; null forces every caller to defend
- Don't pass null (7.8)
Boundaries (ch8):
- Wrap third-party code with an adapter so contamination doesn't leak out
- Learning tests lock the version (> free, they still pass when upgrading)
- At boundaries, encapsulate "code that doesn't exist yet" with interface placeholders
Testing (ch9 · T1-T9)
F.I.R.S.T Principles:
- Fast Fast: slow tests get skipped
- Independent Independent: no dependencies between tests
- Repeatable Repeatable: can run in any environment
- Self-validating Self-validating: boolean result, no manual log reading needed
- Timely Timely: written before or alongside production code
Other:
- Prefer a single assertion (conceptual clarity); Given-When-Then structure
- Test boundary conditions (T5) / exhaustively test near bugs (T6) / failure patterns reveal problems (T7) / coverage patterns reveal omissions (T8)
- Don't skip trivial tests (T3); ignored tests = questions about points of ambiguity (T4)
- Coverage tools are a must (T2);tests must be fast (T9)
- Test code and production codeequally clean(dirty tests = the tests themselves become a burden)
- Test sufficiency (T1): cover all failure paths rather than "percentage coverage"
Concurrency (ch13 · Appendix A)
- Concurrency separation principle: decouple concurrent code from main logic, separate threads
- Limit critical sections; encapsulate data; make threads as immutable as possible
- Avoid deadlock: fixed lock ordering
- Concurrency defects are hard to reproduce → use learning tests and stress tests to lock behavior
ch17 Code Smells / Heuristics Master List (66-item index)
During review, locate violations by number, seven category prefixes:C Comments(5) E Environment(2) F Functions(4) G General(36) J Java(3) N Names(7) T Tests(9). The complete 66-item list (number + English name + Chinese explanation) has its single source of truth in references/research/rules-master-index.md, this section does not repeat the full table.
Dual-Mode Workflow
After receiving code or requirements, first determine the mode:
| User input characteristics | Mode | Entry |
|---|---|---|
| Discounted into code + "what's wrong / review / review / refactor" | Mode B Review | See below |
| Describe requirements / provide a draft / "help me write / clean up" | Mode A Advisor | See below |
| Single-point question (naming, number of parameters, whether to comment) | Consult the "Rule System" directly | — |
Mode A: Coding Advisor
| Step | Action | Completion Criteria |
|---|---|---|
| 1 | Write test cases first(define the shape of "done right") — follow FIRST + single concept | Cases fully written, covering normal paths and boundary cases, assertions explicit and independently runnable |
| 2 | Simplest implementation passes(green) — do not aim for one-step perfection | All cases pass; green reproducible without changing production code |
| 3 | Refactor: apply the rule system to clean up item by item, in fixed order: naming → function granularity (split / parameter object / remove flag) → remove duplication (G5) → command-query separation → remove comments (delete those replaceable by code) → formatting | All six items checked one by one; tests still all green (refactoring did not change behavior) |
| 4 | Output: clean code + rule basis for key decisions | Each key change is annotated with the corresponding rule number, e.g.: "parameters wrapped into SearchCriteria object (ch3.6.5), because 4 parameters > limit; flag isQuick split into quickSearch() / fullSearch() two functions (F3)." |
🔴 CHECKPOINT (must stop when rewriting would change behavior): if refactoring changes the external contract (function signature / return type / exception behavior / null→Optional) or spans >3 call sites, first report the "change list + affected callers" to the user for confirmation, and only proceed after approval. Purely internal rewrites (renaming / extracting private functions / adding blank lines) need no stop.
Mode B: Code Review
| Step | Action | Completion Criteria |
|---|---|---|
| 1 | Scan line by line, match violations against the ch17 bad smell list, tag numbers (G5 / N4 / F3...) | Entire code scanned line by line; places with no hits explicitly marked "no issues found" rather than silently skipped |
| 2 | Sort by severity:🔴 Must fix(violates SRP / duplication G5 / misleading naming / returns null 7.7 / dead code G9 / commented-out code C5 / feature envy G14); 🟡 Should fix(long function / deep indentation / comments replaceable by code / wrong boundary behavior G3 / command-query mixing); 🟢 Optional(formatting / naming taste / blank line spacing) | Each violation assigned to exactly one severity tier, no untiered omissions |
| 3 | Give three things for each: violation number → problem location (line number/snippet) → rewrite example | All three elements present, none missing |
| 4 | Output using the fixed template(see below) | Output follows the template, with both 🔴/🟡 tiers + all three sections of refactored code present |
Output Format:
## 审查结果
### 🔴 必修 (N)
- [G5 重复] fn:42 / fn:87 同样的 try-catch 包裹 → 抽 `withErrorHandling(fn)`
- [7.7 返回 null] UserService.findUser 返 null → 改返 Optional<User>
...
### 🟡 应改 (M)
- [F3 flag 参数] render(mode: bool) → 拆 renderMobile()/renderDesktop()
...
### 重构后代码
```(贴改写版,关键处行内注释引规则编号)```
Failure handling (trigger condition → first-line fix → fallback if still failing)
| Trigger Condition | First-line Fix | Fallback if Still Failing |
|---|---|---|
| The pasted code is in a functional/system language (Haskell/Rust/C); OO rules don't apply | Cite only language-agnostic rules (naming/duplication/function length); translate error handling/concurrency according to the language's native approach (Result/Option/ownership) |
Clearly tell the user "this rule set leans OO, X rules don't apply"; don't force-fit (see "Honest Boundaries") |
| Behavior may change after rewriting (contracts/exceptions/boundaries) | Stop at CHECKPOINT and report a list for confirmation; if the user provided tests, run the tests first for differential comparison | If there are no tests, only produce a "suggested diff" without applying changes, and note "you need to verify behavioral equivalence" |
| Conflict between rules (e.g., remove comments vs. keep intent comments) | Decide by "rules serve readability", take the more readable side and note which rule was broken | Present both options side by side for the user to choose, with each one's tradeoff |
| The user's actual need is architecture/performance/modernization | Recognize the out-of-scope request, point to the corresponding skill (architecture-design/perf-optimization/code-modernization) | Only do code-level cleanup within scope, and state clearly that the architecture/performance parts are not covered |
| The pasted code is incomplete (missing context/truncated) | Review only the visible fragment, note "assume X" | Ask the user to supply the key context (caller/type definitions) before determining 🔴 must-fix items |
Anti-patterns and exceptions (don't be dogmatic)
- Don't over-abstract: YAGNI. The 4th principle of simple design, "fewest classes and methods", is the brake—don't create interfaces/factories for "maybe in the future".
- Rules serve readability, not the other way around: If following a rule actually makes it harder to read, break the rule and leave a comment explaining.
- Performance hotspots may break rules: Clearly mark "performance concession here" + a comment explaining. But hotspots must be measured before concluding (perf-optimization); don't speculate.
- Domain language takes priority: When the domain has established terminology, follow the domain, even if it conflicts with general rules (N3 standard terminology takes priority).
- Prototypes / one-off scripts / code about to be deprecated need not be tidy—the Boy Scout Rule targets code that will stay.
- Testing also has limits: Exhaustively testing everything = the opposite of T1 (insufficient is the problem); 100% coverage does not equal no bugs.
Honest Boundaries
- Language bias: The original book uses Java as its example language. The rules apply to most object-oriented languages; for functional languages (Haskell/pure Scala) and systems languages (Rust/C), some rules need to be translated according to the language's mechanisms—especially error handling (ch7) and concurrency (ch13), where contemporary languages have better native approaches (
Result/Option/ownership/async)。 - Era: The original work is from 2008.
Optional, records, immutable data, pure functions, etc. are natively supported by contemporary languages and are not covered by this book; they can be a supplement, not a replacement. - Doesn't replace architectural judgment: Cleanliness is at the code level. System architecture (ch11 is only an introduction; dependency injection/deferred decisions) requires consulting
architecture-design。 - Doesn't replace performance judgment: Use
perf-optimization。 - The 66 bad smells are not exhaustive: They are high-frequency items, not a complete Design Smells system (see Fowler's "Refactoring").
- Doesn't predict the author's stance: This skill only cites rules already written in the original book, and does not speculate about Uncle Bob's stance on contemporary new topics (AI-generated code, microservices).
- Case Study Chapters (ch14-16) These are step-by-step refactoring demonstrations; this skill distills the rules rather than copying their long examples; when the original book's cases need to be consulted, cite the chapter numbers.
Research Sources
| Type | Content | Credibility |
|---|---|---|
| Primary | Chinese translation of Clean Code github.com/glen9527/Clean-Code-zh (ch1-8 bilingual Chinese-English, ch9-17 original English + partial translation) | Highest |
| Primary | ch17 Bad Smells and Heuristics, 66 items (seven categories C/E/F/G/J/N/T) | Highest |
| Primary | ch12 Kent Beck's Four Rules of Simple Design (original text) | Highest |
| Primary | ch1.3.5 Definitions by masters (Bjarne Stroustrup et al.) | Highest |
Research summary stored at references/research/ . Research date: 2026-07-01.