@booklib/skills 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CONTRIBUTING.md +122 -0
  2. package/README.md +20 -2
  3. package/ROADMAP.md +36 -0
  4. package/animation-at-work/evals/evals.json +44 -0
  5. package/animation-at-work/examples/after.md +64 -0
  6. package/animation-at-work/examples/before.md +35 -0
  7. package/animation-at-work/scripts/audit_animations.py +295 -0
  8. package/bin/skills.js +552 -42
  9. package/clean-code-reviewer/SKILL.md +109 -1
  10. package/clean-code-reviewer/evals/evals.json +121 -3
  11. package/clean-code-reviewer/examples/after.md +48 -0
  12. package/clean-code-reviewer/examples/before.md +33 -0
  13. package/clean-code-reviewer/references/api_reference.md +158 -0
  14. package/clean-code-reviewer/references/practices-catalog.md +282 -0
  15. package/clean-code-reviewer/references/review-checklist.md +254 -0
  16. package/clean-code-reviewer/scripts/pre-review.py +206 -0
  17. package/data-intensive-patterns/evals/evals.json +43 -0
  18. package/data-intensive-patterns/examples/after.md +61 -0
  19. package/data-intensive-patterns/examples/before.md +38 -0
  20. package/data-intensive-patterns/scripts/adr.py +213 -0
  21. package/data-pipelines/evals/evals.json +45 -0
  22. package/data-pipelines/examples/after.md +97 -0
  23. package/data-pipelines/examples/before.md +37 -0
  24. package/data-pipelines/scripts/new_pipeline.py +444 -0
  25. package/design-patterns/evals/evals.json +46 -0
  26. package/design-patterns/examples/after.md +52 -0
  27. package/design-patterns/examples/before.md +29 -0
  28. package/design-patterns/scripts/scaffold.py +807 -0
  29. package/domain-driven-design/SKILL.md +120 -0
  30. package/domain-driven-design/evals/evals.json +48 -0
  31. package/domain-driven-design/examples/after.md +80 -0
  32. package/domain-driven-design/examples/before.md +43 -0
  33. package/domain-driven-design/scripts/scaffold.py +421 -0
  34. package/effective-java/evals/evals.json +46 -0
  35. package/effective-java/examples/after.md +83 -0
  36. package/effective-java/examples/before.md +37 -0
  37. package/effective-java/scripts/checkstyle_setup.py +211 -0
  38. package/effective-kotlin/evals/evals.json +45 -0
  39. package/effective-kotlin/examples/after.md +36 -0
  40. package/effective-kotlin/examples/before.md +38 -0
  41. package/effective-python/evals/evals.json +44 -0
  42. package/effective-python/examples/after.md +56 -0
  43. package/effective-python/examples/before.md +40 -0
  44. package/effective-python/references/api_reference.md +218 -0
  45. package/effective-python/references/practices-catalog.md +483 -0
  46. package/effective-python/references/review-checklist.md +190 -0
  47. package/effective-python/scripts/lint.py +173 -0
  48. package/kotlin-in-action/evals/evals.json +43 -0
  49. package/kotlin-in-action/examples/after.md +53 -0
  50. package/kotlin-in-action/examples/before.md +39 -0
  51. package/kotlin-in-action/scripts/setup_detekt.py +224 -0
  52. package/lean-startup/evals/evals.json +43 -0
  53. package/lean-startup/examples/after.md +80 -0
  54. package/lean-startup/examples/before.md +34 -0
  55. package/lean-startup/scripts/new_experiment.py +286 -0
  56. package/microservices-patterns/SKILL.md +140 -0
  57. package/microservices-patterns/evals/evals.json +45 -0
  58. package/microservices-patterns/examples/after.md +69 -0
  59. package/microservices-patterns/examples/before.md +40 -0
  60. package/microservices-patterns/scripts/new_service.py +583 -0
  61. package/package.json +2 -8
  62. package/refactoring-ui/evals/evals.json +45 -0
  63. package/refactoring-ui/examples/after.md +85 -0
  64. package/refactoring-ui/examples/before.md +58 -0
  65. package/refactoring-ui/scripts/audit_css.py +250 -0
  66. package/skill-router/SKILL.md +142 -0
  67. package/skill-router/evals/evals.json +38 -0
  68. package/skill-router/examples/after.md +63 -0
  69. package/skill-router/examples/before.md +39 -0
  70. package/skill-router/references/api_reference.md +24 -0
  71. package/skill-router/references/routing-heuristics.md +89 -0
  72. package/skill-router/references/skill-catalog.md +156 -0
  73. package/skill-router/scripts/route.py +266 -0
  74. package/storytelling-with-data/evals/evals.json +47 -0
  75. package/storytelling-with-data/examples/after.md +50 -0
  76. package/storytelling-with-data/examples/before.md +33 -0
  77. package/storytelling-with-data/scripts/chart_review.py +301 -0
  78. package/system-design-interview/evals/evals.json +45 -0
  79. package/system-design-interview/examples/after.md +94 -0
  80. package/system-design-interview/examples/before.md +27 -0
  81. package/system-design-interview/scripts/new_design.py +421 -0
  82. package/using-asyncio-python/evals/evals.json +43 -0
  83. package/using-asyncio-python/examples/after.md +68 -0
  84. package/using-asyncio-python/examples/before.md +39 -0
  85. package/using-asyncio-python/scripts/check_blocking.py +270 -0
  86. package/web-scraping-python/evals/evals.json +46 -0
  87. package/web-scraping-python/examples/after.md +109 -0
  88. package/web-scraping-python/examples/before.md +40 -0
  89. package/web-scraping-python/scripts/new_scraper.py +231 -0
  90. /package/{effective-python-skill → effective-python}/SKILL.md +0 -0
  91. /package/{effective-python-skill → effective-python}/ref-01-pythonic-thinking.md +0 -0
  92. /package/{effective-python-skill → effective-python}/ref-02-lists-and-dicts.md +0 -0
  93. /package/{effective-python-skill → effective-python}/ref-03-functions.md +0 -0
  94. /package/{effective-python-skill → effective-python}/ref-04-comprehensions-generators.md +0 -0
  95. /package/{effective-python-skill → effective-python}/ref-05-classes-interfaces.md +0 -0
  96. /package/{effective-python-skill → effective-python}/ref-06-metaclasses-attributes.md +0 -0
  97. /package/{effective-python-skill → effective-python}/ref-07-concurrency.md +0 -0
  98. /package/{effective-python-skill → effective-python}/ref-08-robustness-performance.md +0 -0
  99. /package/{effective-python-skill → effective-python}/ref-09-testing-debugging.md +0 -0
  100. /package/{effective-python-skill → effective-python}/ref-10-collaboration.md +0 -0
@@ -0,0 +1,282 @@
1
+ # Clean Code — Practices Catalog
2
+
3
+ Catalog of the most actionable principles from Robert C. Martin's
4
+ *Clean Code: A Handbook of Agile Software Craftsmanship*, organized by category.
5
+ Each entry includes the heuristic code, a short description, and the key test question.
6
+
7
+ ---
8
+
9
+ ## Naming
10
+
11
+ ### N1 — Choose Descriptive Names
12
+ **Code:** N1
13
+ **Description:** A name should reveal its purpose so completely that the code reads like
14
+ well-written prose. If a name requires a comment to explain it, it doesn't do its job.
15
+ **Test question:** If someone reads only this name, do they know *why* this thing exists,
16
+ *what* it does, and *how* it's used?
17
+
18
+ ### N2 — Names at the Appropriate Level of Abstraction
19
+ **Code:** N2
20
+ **Description:** Names should match the abstraction level of the code they appear in.
21
+ A `Modem` interface's `dial(phoneNumber)` reveals implementation; `connect(connectionLocator)`
22
+ expresses the concept. Names at the right level can outlast implementation changes.
23
+ **Test question:** Would this name still make sense if the underlying implementation changed?
24
+
25
+ ### N4 — Unambiguous Names
26
+ **Code:** N4
27
+ **Description:** When two things in the same scope could be confused, names must be
28
+ precise enough to remove ambiguity. `doRename()` is ambiguous; `renamePageAndOptionallyAllReferences()`
29
+ is not. Verbosity in a name is cheaper than confusion in a reader.
30
+ **Test question:** Could a reader confuse this name with anything else in the same context?
31
+
32
+ ### N5 — Long Names for Long Scopes
33
+ **Code:** N5
34
+ **Description:** Single-letter variables are fine in a 3-line loop; in a 300-line function,
35
+ they are inscrutable. The length of a name should correspond to the size of the scope
36
+ it lives in. Long-lived names deserve investment.
37
+ **Test question:** If this variable were referenced 50 lines from its declaration,
38
+ would its name still be self-explanatory?
39
+
40
+ ### N7 — Names Should Describe Side Effects
41
+ **Code:** N7
42
+ **Description:** If a function named `getOos()` creates an `ObjectOutputStream` when
43
+ none exists, the name lies. Names must reflect everything the function does, including
44
+ side effects. `createOrReturnOos()` is honest.
45
+ **Test question:** Does this function's name describe *everything* it does, including
46
+ any state it changes?
47
+
48
+ ---
49
+
50
+ ## Functions
51
+
52
+ ### Do One Thing (G30)
53
+ **Code:** G30
54
+ **Description:** A function should do one thing, do it well, and do it only. The test:
55
+ can you extract a meaningful sub-function from the body? If yes, the function is doing
56
+ more than one thing. Functions that do one thing cannot be reasonably subdivided.
57
+ **Test question:** Can you extract a meaningfully named sub-function from this function's body?
58
+
59
+ ### F1 — Too Many Arguments
60
+ **Code:** F1
61
+ **Description:** The ideal number of function arguments is zero. One is fine. Two requires
62
+ thought. Three requires strong justification. More than three is almost always wrong.
63
+ When a function needs many related arguments, they usually form a concept that deserves
64
+ its own class or struct.
65
+ **Test question:** Could two or more arguments be wrapped into a meaningful object?
66
+
67
+ ### F3 — Flag Arguments Are Ugly
68
+ **Code:** F3
69
+ **Description:** Passing a boolean to a function is a clear sign the function does two
70
+ things — one for `true`, one for `false`. This violates "do one thing." The solution
71
+ is always to split the function into two: one for each behavior.
72
+ **Test question:** Does this function take a boolean that controls which of two paths it takes?
73
+
74
+ ### F2 — Output Arguments
75
+ **Code:** F2
76
+ **Description:** Arguments are inputs. Readers naturally assume you pass things *in* to
77
+ a function, not that a function writes results *back* through its parameters.
78
+ `appendFooter(s)` is confusing; `report.appendFooter()` is not.
79
+ **Test question:** Is the caller expected to read a result out of one of the arguments
80
+ passed to this function?
81
+
82
+ ### G5 — Duplication
83
+ **Code:** G5
84
+ **Description:** Duplication is the root of all evil in software. Duplicated code means
85
+ two chances to make the same mistake, two places to change when the logic evolves,
86
+ and two diverging truths. Every duplication should be addressed — usually by extraction,
87
+ TEMPLATE METHOD, or STRATEGY.
88
+ **Test question:** Does the same algorithm, condition, or business rule appear in more
89
+ than one place?
90
+
91
+ ### G19 — Use Explanatory Variables
92
+ **Code:** G19
93
+ **Description:** Complex calculations should be broken into named intermediate variables
94
+ that explain each step. `(hourlyRate * hoursWorked) - taxRate` becomes three named
95
+ variables that document the calculation's intent without a comment.
96
+ **Test question:** Would a named intermediate variable replace the need for a comment
97
+ explaining this expression?
98
+
99
+ ### G28 — Encapsulate Conditionals
100
+ **Code:** G28
101
+ **Description:** Boolean logic is hard to scan. Extract conditions into functions with
102
+ meaningful names. `if (shouldBeDeleted(timer))` reads like prose. `if (timer.hasExpired() && !timer.isRecurrent())`
103
+ requires the reader to parse logic rather than understand intent.
104
+ **Test question:** Can the condition be extracted into a function whose name expresses
105
+ what the condition means?
106
+
107
+ ### G29 — Avoid Negative Conditionals
108
+ **Code:** G29
109
+ **Description:** Negative conditionals are harder to understand than positive ones.
110
+ `buffer.shouldCompact()` is easier to parse than `!buffer.shouldNotCompact()`. Prefer
111
+ the positive form. When you need the negative, double-negatives (`not not`) are never acceptable.
112
+ **Test question:** Is this conditional expressed in its positive form?
113
+
114
+ ---
115
+
116
+ ## Comments
117
+
118
+ ### C5 — Commented-Out Code
119
+ **Code:** C5
120
+ **Description:** Commented-out code is an abomination. No one will delete it because
121
+ everyone assumes someone else put it there for a reason. It accumulates like sediment.
122
+ Delete it. Version control remembers everything. This is the single most important
123
+ comment smell to eliminate.
124
+ **Test question:** Is there any code that has been commented out?
125
+
126
+ ### C3 — Redundant Comments
127
+ **Code:** C3
128
+ **Description:** A comment that describes exactly what the code already says clearly
129
+ is pure noise. It clutters the file, takes time to read, and can drift out of sync.
130
+ If the code is clear, the comment is unnecessary. If the comment adds nothing, remove it.
131
+ **Test question:** Could you delete this comment and lose no information?
132
+
133
+ ### C2 — Obsolete Comments
134
+ **Code:** C2
135
+ **Description:** Comments age badly. A comment that was accurate when written becomes
136
+ misleading after the code changes. Misleading comments are worse than no comments —
137
+ they actively corrupt the reader's mental model.
138
+ **Test question:** Does this comment accurately describe what the code currently does?
139
+
140
+ ### Intent vs. Explanation
141
+ **Code:** (general — Ch. 4)
142
+ **Description:** The only valuable comments explain *why* — intent, rationale, warnings.
143
+ Comments that explain *what* the code does are redundant with the code itself. Invest in
144
+ renaming and restructuring until the *what* is obvious; then write a comment only if
145
+ the *why* is not.
146
+ **Test question:** Does this comment explain *why* rather than *what*?
147
+
148
+ ---
149
+
150
+ ## Error Handling
151
+
152
+ ### Don't Return Null
153
+ **Code:** (Ch. 7)
154
+ **Description:** Every null return is a potential NullPointerException waiting to happen.
155
+ If a function can return null, every caller must check — and one check missed causes a
156
+ runtime crash. Return a Special Case object (`Collections.emptyList()`, `NullEmployee`),
157
+ throw an exception, or use Optional.
158
+ **Test question:** Does this function return null to indicate failure or absence?
159
+
160
+ ### Don't Pass Null
161
+ **Code:** (Ch. 7)
162
+ **Description:** Passing null as a function argument is even worse than returning it.
163
+ There is no reasonable way for a function to handle an argument being null except with
164
+ defensive checks throughout. Use overloading, Optional, or default values instead.
165
+ **Test question:** Is null passed as an argument to any function?
166
+
167
+ ### Exceptions Carry Context
168
+ **Code:** (Ch. 7)
169
+ **Description:** A thrown exception should tell the receiver what operation failed and
170
+ why. An exception message of "Error" or a bare stack trace is useless in a log.
171
+ Include the operation being attempted and the failure type.
172
+ **Test question:** Does this exception message tell a reader what operation failed and why?
173
+
174
+ ### Special Case Pattern
175
+ **Code:** (Ch. 7, Martin Fowler)
176
+ **Description:** When a function is asked for something that might not exist
177
+ (a customer with no orders, a user with no profile), returning null forces every
178
+ caller to handle the absence. The Special Case pattern encapsulates the "nothing here"
179
+ behavior into an object that behaves like the real thing — callers don't need to check.
180
+ **Test question:** Is there a null check that could be replaced with a Special Case object?
181
+
182
+ ---
183
+
184
+ ## Objects and Data Structures
185
+
186
+ ### G36 — Law of Demeter (Avoid Transitive Navigation)
187
+ **Code:** G36
188
+ **Description:** Code should not navigate through a chain of objects to get at behavior
189
+ deep inside the structure: `a.getB().getC().doSomething()`. This couples the caller to
190
+ the entire chain. Expose what you need directly, or restructure so each class talks
191
+ only to its immediate collaborators.
192
+ **Test question:** Does this line navigate more than one association to get at behavior?
193
+
194
+ ### G14 — Feature Envy
195
+ **Code:** G14
196
+ **Description:** A method that uses another class's data more than its own is envious
197
+ of that class. This is a sign the method probably belongs in the other class. Move the
198
+ behavior to where the data lives.
199
+ **Test question:** Does this method use more fields or methods of another class than its own?
200
+
201
+ ### G23 — Prefer Polymorphism to Switch/If-Else Chains
202
+ **Code:** G23
203
+ **Description:** `switch` statements that check a type tag repeat themselves across the
204
+ codebase. When you add a new type, you must find and update every switch. Polymorphism
205
+ centralizes the variation in one place — the class hierarchy.
206
+ **Test question:** Does this switch or if-else chain select behavior based on a type tag?
207
+
208
+ ---
209
+
210
+ ## Classes
211
+
212
+ ### Single Responsibility Principle
213
+ **Code:** (Ch. 10)
214
+ **Description:** A class should have one, and only one, reason to change. If you can
215
+ describe what a class does only by using "and" or "or," it has more than one responsibility.
216
+ A class with multiple responsibilities is coupled to multiple change vectors.
217
+ **Test question:** Can this class be described in one sentence without "and" or "or"?
218
+
219
+ ### G8 — Too Much Information
220
+ **Code:** G8
221
+ **Description:** Well-defined interfaces expose little and demand little. A class with
222
+ many public methods, or a data class with many public fields, is hard to understand
223
+ and hard to change. The best interfaces hide almost everything.
224
+ **Test question:** Does this interface expose more than the caller absolutely needs?
225
+
226
+ ### Open-Closed Principle
227
+ **Code:** (Ch. 10)
228
+ **Description:** Classes should be open for extension but closed for modification.
229
+ When new behavior is needed, new code should be added — not existing code changed.
230
+ This is achieved through abstraction: depend on interfaces, not concretions.
231
+ **Test question:** Would adding a new variant of this behavior require modifying existing classes?
232
+
233
+ ---
234
+
235
+ ## Systems and Boundaries
236
+
237
+ ### G35 — Keep Configurable Data at High Levels
238
+ **Code:** G35
239
+ **Description:** Constants and configurable data (server addresses, timeout values,
240
+ feature limits) should be defined at the top of the system and passed down. Burying
241
+ a magic constant deep inside a business function makes it invisible and fragile.
242
+ **Test question:** Are there constants buried in low-level logic that should be defined at a higher level?
243
+
244
+ ### Wrap Third-Party APIs
245
+ **Code:** (Ch. 8)
246
+ **Description:** Third-party interfaces should not scatter through your codebase.
247
+ Wrap them in your own abstraction so you control the vocabulary, can mock them in tests,
248
+ and can swap them with a single change. The wrapping point is the clean boundary.
249
+ **Test question:** Can you change the underlying third-party library by modifying only one class?
250
+
251
+ ### G13 — Artificial Coupling
252
+ **Code:** G13
253
+ **Description:** Coupling two modules that have no structural reason to be related forces
254
+ them to change together. Artificial coupling often appears as a utility function placed
255
+ in a class because it was convenient, or a constant defined in a class that has nothing
256
+ to do with it.
257
+ **Test question:** Does this module have a dependency that exists only for convenience, not structure?
258
+
259
+ ---
260
+
261
+ ## Tests
262
+
263
+ ### T1 — Insufficient Tests
264
+ **Code:** T1
265
+ **Description:** A test suite is insufficient if it does not cover everything that could
266
+ possibly break. Developers must not be satisfied by a coverage number — they must think
267
+ about what the code does and verify each behavior.
268
+ **Test question:** Is there any behavior in this code that no test exercises?
269
+
270
+ ### T5 — Test Boundary Conditions
271
+ **Code:** T5
272
+ **Description:** Bugs hide at the edges. Empty collections, zero values, maximum values,
273
+ negative numbers, null inputs — boundary conditions are exactly where assumptions break.
274
+ Every algorithm has its edges; every edge deserves a test.
275
+ **Test question:** Are the minimum, maximum, and edge-case inputs tested?
276
+
277
+ ### F.I.R.S.T.
278
+ **Code:** (Ch. 9)
279
+ **Description:** Good tests are Fast (run in milliseconds), Independent (no order dependency),
280
+ Repeatable (same result in any environment), Self-validating (pass or fail, no manual check),
281
+ and Timely (written with the production code). Tests that violate these are not maintained.
282
+ **Test question:** Can every test in this suite be run in isolation, in any order, in any environment?
@@ -0,0 +1,254 @@
1
+ # Clean Code — Code Review Checklist
2
+
3
+ Systematic checklist for reviewing code against the principles from Robert C. Martin's
4
+ *Clean Code: A Handbook of Agile Software Craftsmanship*.
5
+
6
+ ---
7
+
8
+ ## Chapter 2 — Meaningful Names
9
+
10
+ ### Intention and Clarity
11
+ - [ ] **N1 — Descriptive names** — Does every name (variable, function, class) tell you *why* it exists, *what* it does, and *how* it's used? Would a name require a comment to explain it?
12
+ - [ ] **N4 — Unambiguous names** — Is each name precise and unambiguous? Could `rename()` instead be `renamePageAndOptionallyAllReferences()`? Would a more specific name prevent confusion?
13
+ - [ ] **N2 — Appropriate abstraction level** — Do names match the level of abstraction of the code? Is `dial(phoneNumber)` where `connect(connectionLocator)` would be more general and honest?
14
+
15
+ ### Avoiding Misinformation and Noise
16
+ - [ ] **No disinformation** — Do any names actively mislead? Is `accountList` actually not a `List`? Are platform abbreviations (`hp`, `aix`, `sco`) used as variable names?
17
+ - [ ] **No meaningless distinctions** — Are names meaningfully different from each other? Is there `ProductData` vs. `ProductInfo`, `data` vs. `info`, `a1` vs. `a2`? Noise words add nothing.
18
+ - [ ] **N6 — No encodings** — Is there Hungarian notation, `m_` member prefixes, or `I`-prefixed interface names? Modern IDEs make these unnecessary.
19
+
20
+ ### Conventions and Consistency
21
+ - [ ] **Class names** — Are class names nouns or noun phrases (`Customer`, `WikiPage`, `Account`)? Are vague names like `Manager`, `Processor`, `Data`, `Info` avoided?
22
+ - [ ] **Method names** — Are method names verbs or verb phrases (`postPayment`, `deletePage`, `save`)? Do accessors, mutators, and predicates use `get`/`set`/`is` prefixes?
23
+ - [ ] **One word per concept** — Is one consistent word used per abstract concept across the codebase? Is the code mixing `fetch`, `retrieve`, and `get` for equivalent operations?
24
+ - [ ] **No puns** — Is the same word used for two different purposes? Does `add` mean "concatenate" in one place and "insert into collection" in another?
25
+ - [ ] **N3 — Standard nomenclature** — Are design pattern names used when patterns are applied (`AccountVisitor`, `JobQueue`)? Does code near domain concepts use domain vocabulary?
26
+ - [ ] **N5 — Scope-appropriate length** — Is `i` used in a 5-line loop but a 500-line scope? The length of a name should correspond to the size of its scope.
27
+
28
+ ### Context
29
+ - [ ] **Meaningful context** — Does `state` alone appear where `addrState` or an `Address` class would clarify? Does the surrounding structure provide context?
30
+ - [ ] **No gratuitous context** — Are class or variable names prefixed with an application abbreviation (e.g., every class starting with `GSD`)? Short, clear names are better.
31
+ - [ ] **Pronounceable** — Could every name be discussed in conversation? Is `genymdhms` used where `generationTimestamp` belongs?
32
+ - [ ] **Searchable** — Are single-letter variables and magic numbers scoped to very short blocks where their meaning is unambiguous?
33
+
34
+ ---
35
+
36
+ ## Chapter 3 — Functions
37
+
38
+ ### Size and Focus
39
+ - [ ] **Small** — Are functions short? Does each block within `if`, `else`, and `while` resolve to one line, ideally a function call? Would any function fit on one screen?
40
+ - [ ] **G30 / Do one thing** — Can you extract a meaningfully named function from the body? If yes, the function is doing more than one thing.
41
+ - [ ] **One level of abstraction** — Does the function mix high-level intent (e.g., `renderPage()`) with low-level manipulation (e.g., direct string concatenation)? Functions should read top-down, each leading to the next level of abstraction (the Stepdown Rule).
42
+ - [ ] **G34 — Descend only one level** — Does each function descend exactly one level of abstraction below the function's stated name?
43
+
44
+ ### Arguments
45
+ - [ ] **F1 — Argument count** — Does any function take more than three arguments? Three requires strong justification. More than three: extract into an argument object.
46
+ - [ ] **F3 — Flag arguments** — Does any function take a boolean parameter? A flag argument loudly declares the function does two things. Split it into two functions.
47
+ - [ ] **F2 — Output arguments** — Does any argument serve as an output? Output arguments are counterintuitive. Use return values, or use `this`/`self`.
48
+ - [ ] **Argument objects** — When 2-3 arguments are closely related (e.g., `x, y, radius`), should they be grouped into an object (`Point center, double radius`)?
49
+
50
+ ### Side Effects and Structure
51
+ - [ ] **No side effects** — Does a function named `checkPassword` also initialize a session? Does a function do something other than what its name says?
52
+ - [ ] **Command-Query Separation** — Does any function both modify state *and* return a value? Functions should either do something or answer something, never both.
53
+ - [ ] **F4 — Dead functions** — Are there functions that are never called? Delete them; version control remembers.
54
+ - [ ] **G5 — No duplication** — Is any algorithm, validation rule, or business logic repeated? Is TEMPLATE METHOD or STRATEGY applicable?
55
+
56
+ ### Error Handling
57
+ - [ ] **Exceptions over return codes** — Are error conditions signaled by throwing exceptions rather than returning error codes?
58
+ - [ ] **Error handling is one thing** — If a function has a `try` block, does the function do *only* error handling? Are the bodies of `try` and `catch` extracted into their own functions?
59
+ - [ ] **Switch statements** — If a switch statement exists, is it buried in an abstract factory that uses polymorphism? Is it the only such switch in the codebase for that type?
60
+
61
+ ---
62
+
63
+ ## Chapter 4 — Comments
64
+
65
+ ### Bad Comments to Eliminate
66
+ - [ ] **C5 — Commented-out code** — Is there any code that has been commented out? Delete it. Version control remembers. This is the worst comment smell.
67
+ - [ ] **C3 — Redundant comments** — Does any comment restate what the code already says clearly? (`i++; // increment i`). Does the comment take longer to read than the code?
68
+ - [ ] **C2 — Obsolete comments** — Do any comments describe behavior that the code no longer performs? Have comments drifted from the code they annotate?
69
+ - [ ] **C1 — Inappropriate information** — Do comments contain changelogs, author attributions, dates, or metadata that belongs in version control?
70
+ - [ ] **C4 — Poorly written comments** — Are any comments grammatically wrong, rambling, or unclear? If a comment is worth writing, it's worth writing well.
71
+ - [ ] **Noise comments** — Are there comments like `/** Default constructor */` or `/** The day of the month */` that state the obvious?
72
+ - [ ] **Closing brace comments** — Are there comments like `} // while` or `} // if`? These indicate functions that are too long. Shorten the function instead.
73
+ - [ ] **Byline comments** — Are there `// Added by Rick` comments? Version control tracks authorship.
74
+
75
+ ### Good Comments to Verify
76
+ - [ ] **Intent comments** — Do comments explain *why* a decision was made, not *what* the code does? This is the only comment form that adds value not already in the code.
77
+ - [ ] **Warning comments** — Are there consequences worth warning future developers about (e.g., `// Don't run unless you have time to kill`)?
78
+ - [ ] **TODO comments** — Are TODO comments specific and actionable? Are they tracked and not accumulating as permanent clutter?
79
+ - [ ] **Public API documentation** — Do all public APIs have clear documentation comments that explain parameters, return values, and exceptions?
80
+
81
+ ---
82
+
83
+ ## Chapter 5 — Formatting
84
+
85
+ - [ ] **Newspaper metaphor** — Does each source file read like a newspaper? Is the class name at the top, high-level abstractions near the top, and details near the bottom?
86
+ - [ ] **Vertical openness** — Are separate concepts separated by blank lines? Can distinct sections (imports, fields, methods) be visually distinguished?
87
+ - [ ] **Vertical density** — Are closely related lines grouped tightly together without blank lines breaking up what belongs together?
88
+ - [ ] **Vertical distance** — Are variables declared close to their first use? Are related functions close to each other, with callers above callees?
89
+ - [ ] **Line length** — Are all lines short enough to avoid horizontal scrolling? Is a consistent maximum line length enforced across the team?
90
+ - [ ] **Team rules** — Does the formatting match team conventions? Is an automated formatter (Prettier, Black, ktlint, gofmt) enforced?
91
+
92
+ ---
93
+
94
+ ## Chapter 6 — Objects and Data Structures
95
+
96
+ - [ ] **Data/Object anti-symmetry** — Is data hiding appropriate? Do objects expose behavior and hide data? Do data structures expose data and have no significant behavior?
97
+ - [ ] **G36 / Law of Demeter** — Does any method call a method on an object returned by another method (`a.getB().getC().doSomething()`)? Does the code navigate association chains it should not know about?
98
+ - [ ] **No train wrecks** — Are chained method calls (`a.getB().getC().getD()`) broken up into intermediate variables or redesigned?
99
+ - [ ] **No hybrids** — Are there classes that are half-object (hiding data behind methods) and half-data structure (exposing fields directly)? These are the worst of both worlds.
100
+ - [ ] **DTOs** — Are Data Transfer Objects (database rows, API payloads) simple data structures with public fields and no behavior?
101
+
102
+ ---
103
+
104
+ ## Chapter 7 — Error Handling
105
+
106
+ - [ ] **Exceptions over return codes** — Are all error conditions communicated by exceptions, not return codes or sentinel values?
107
+ - [ ] **Try-catch-finally first** — When writing functions that can fail, does the structure start with the `try-catch-finally` to define the transaction boundary?
108
+ - [ ] **Context with exceptions** — Do thrown exceptions include the failed operation and the type of failure? Are raw stack traces the only diagnostic?
109
+ - [ ] **Caller-defined exception classes** — Are third-party exceptions wrapped into a common type that the caller needs, rather than leaking library-specific exception hierarchies?
110
+ - [ ] **Special Case pattern** — Is null returned where a Special Case object (e.g., `NullEmployee`, `Collections.emptyList()`) would let the caller avoid special-case logic?
111
+ - [ ] **Don't return null** — Does any function return `null` to indicate failure or absence? Every null return is a potential crash. Return a Special Case object or throw.
112
+ - [ ] **Don't pass null** — Is `null` passed as a function argument? This forces defensive null checks everywhere. Use Optional, overloading, or a Special Case.
113
+
114
+ ---
115
+
116
+ ## Chapter 8 — Boundaries
117
+
118
+ - [ ] **Wrap third-party APIs** — Are third-party interfaces accessed directly throughout the codebase? Do you control the vocabulary for the dependency, or does the dependency control yours?
119
+ - [ ] **Learning tests** — Are third-party APIs explored and verified through learning tests? Do these tests serve as living documentation of expected behavior?
120
+ - [ ] **Clean boundaries** — Is third-party knowledge isolated to specific adapter/wrapper classes? Would a library swap require changes in more than one place?
121
+
122
+ ---
123
+
124
+ ## Chapter 9 — Unit Tests
125
+
126
+ ### Test Quality
127
+ - [ ] **T1 — Sufficient tests** — Does the test suite cover everything that could possibly break? Are there critical paths, edge cases, or error conditions with no tests?
128
+ - [ ] **Readable tests** — Is each test readable? Does it follow BUILD-OPERATE-CHECK (Arrange-Act-Assert / Given-When-Then)?
129
+ - [ ] **One concept per test** — Does each test verify one and only one concept? When a test fails, is it immediately obvious what is broken?
130
+ - [ ] **T3 — No skipped trivial tests** — Are trivial tests skipped or deleted? Even trivial tests have documentary value.
131
+ - [ ] **T4 — Ignored tests documented** — Are any tests marked as skipped or ignored? Does each have a clear note about the ambiguity or open question it represents?
132
+
133
+ ### F.I.R.S.T. Properties
134
+ - [ ] **T9 — Fast** — Do all tests run quickly? Would slow tests cause developers to avoid running them?
135
+ - [ ] **Independent** — Do tests depend on each other? Can they be run in any order?
136
+ - [ ] **Repeatable** — Do tests pass in every environment (local, CI, other machines)?
137
+ - [ ] **Self-validating** — Do tests produce a clear pass/fail with no manual inspection required?
138
+ - [ ] **Timely** — Were tests written alongside or before the production code they cover?
139
+
140
+ ### Coverage and Boundaries
141
+ - [ ] **T2 — Coverage tool** — Is a coverage tool being used? Are coverage gaps reviewed, not just a coverage number?
142
+ - [ ] **T5 — Boundary conditions** — Are boundary conditions tested? Off-by-one errors, empty collections, maximum sizes, negative values?
143
+ - [ ] **T6 — Near bugs** — When a bug is found and fixed, are exhaustive tests added for the surrounding code? Bugs cluster.
144
+ - [ ] **T7 — Failure patterns** — Do test failures form a pattern? Can that pattern diagnose the root cause rather than a symptom?
145
+ - [ ] **T8 — Coverage patterns** — Does the pattern of uncovered code reveal structural problems?
146
+
147
+ ---
148
+
149
+ ## Chapter 10 — Classes
150
+
151
+ - [ ] **Small (by responsibility)** — Is each class small? Measured not in lines but in *responsibilities*. Can you describe what the class does without using "and" or "or"?
152
+ - [ ] **Single Responsibility Principle** — Does each class have one, and only one, reason to change? Is there any mixing of business logic, persistence, presentation, or logging?
153
+ - [ ] **High cohesion** — Do most methods in the class use most of the instance variables? Are there methods that touch only 1-2 fields — a sign they belong elsewhere?
154
+ - [ ] **Open-Closed Principle** — Can the behavior of the class be extended without modifying it? Do new features require changing existing classes, or adding new ones?
155
+ - [ ] **Dependency Inversion** — Do high-level classes depend on abstractions (interfaces/abstract classes) rather than concrete implementations?
156
+
157
+ ---
158
+
159
+ ## Chapter 11 — Systems
160
+
161
+ - [ ] **Separate construction from use** — Is object construction (dependency wiring) mixed into business logic? Construction should happen at startup; business logic should work with already-built objects.
162
+ - [ ] **Dependency injection** — Are dependencies injected rather than instantiated inside classes? Does any business logic call `new` on a concrete class it shouldn't know about?
163
+ - [ ] **Cross-cutting concerns** — Are cross-cutting concerns (logging, security, transactions) handled through aspects, decorators, or interceptors rather than scattered throughout business logic?
164
+ - [ ] **G35 — Configurable data at high levels** — Are magic constants and configurable values (hostnames, limits, feature flags) defined at the top level and passed down, not buried deep in low-level code?
165
+
166
+ ---
167
+
168
+ ## Chapter 17 — Smells and Heuristics (Full Heuristic Reference)
169
+
170
+ ### Comments (C-codes)
171
+ - [ ] **C1** — Does any comment contain changelog entries, author names, dates, or other metadata that belongs in version control?
172
+ - [ ] **C2** — Does any comment describe behavior that the current code no longer performs? Is it stale?
173
+ - [ ] **C3** — Does any comment simply restate what the code says clearly on its own?
174
+ - [ ] **C4** — Is any comment poorly written, rambling, or grammatically incorrect?
175
+ - [ ] **C5** — Is there any commented-out code? Delete it immediately.
176
+
177
+ ### General (G-codes)
178
+ - [ ] **G1** — Does any source file contain code in multiple languages (HTML embedded in Java, SQL inline in Python)?
179
+ - [ ] **G2** — Does the code implement what a reader would obviously expect from the function/class name? (Principle of Least Surprise)
180
+ - [ ] **G3** — Has the code been tested at all boundary conditions? Not just the happy path.
181
+ - [ ] **G4** — Are any safeties disabled? Overridden warnings? Silently caught exceptions? Commented-out assertions?
182
+ - [ ] **G5** — Is any code, algorithm, or business rule duplicated? Every duplication should be addressed with TEMPLATE METHOD, STRATEGY, or extraction.
183
+ - [ ] **G6** — Are any methods or variables at the wrong level of abstraction? Do lower-level details appear in higher-level classes?
184
+ - [ ] **G7** — Do any base classes import or depend on their derived classes?
185
+ - [ ] **G8** — Do any interfaces expose more methods than the caller needs? Do data classes expose more fields than necessary?
186
+ - [ ] **G9** — Is there any unreachable code, dead conditional branches, or functions that can never be called?
187
+ - [ ] **G10** — Are variables or utility functions defined far from where they are used?
188
+ - [ ] **G11** — Is the same concept handled differently in different parts of the codebase?
189
+ - [ ] **G12** — Is there clutter: unused variables, empty constructors, functions that are never called?
190
+ - [ ] **G13** — Are there artificial couplings between modules that share no structural relationship?
191
+ - [ ] **G14** — Do methods use data from another class more than their own? Feature Envy — move the method closer to the data.
192
+ - [ ] **G15** — Do any functions take boolean or enum selector arguments to choose behavior? Split into separate functions.
193
+ - [ ] **G16** — Are there magic numbers, Hungarian notation, or run-on expressions that obscure intent?
194
+ - [ ] **G17** — Is any functionality placed in a surprising module or class? (Principle of Least Surprise for placement)
195
+ - [ ] **G18** — Are there static methods that should be instance methods? Would the behavior need to vary polymorphically?
196
+ - [ ] **G19** — Are complex calculations broken into named intermediate variables that explain each step?
197
+ - [ ] **G20** — Does `date.add(5)` exist where `date.addDays(5)` would be clearer? Do function names say what they do?
198
+ - [ ] **G21** — Is there any algorithm that was arrived at by trial-and-error? Does the author understand why the algorithm works?
199
+ - [ ] **G22** — Does any module assume something about another module without making that assumption explicit in the structure?
200
+ - [ ] **G23** — Are there `if/else` or `switch/case` chains where polymorphism would be cleaner and more extensible?
201
+ - [ ] **G24** — Does the code follow the team's standard conventions for naming, formatting, and structure?
202
+ - [ ] **G25** — Are there magic numbers (3, 86400, 0.01) that should be named constants?
203
+ - [ ] **G26** — Is float used for currency? Are concurrent data structures used without locks? Is precision being assumed where it must be enforced?
204
+ - [ ] **G27** — Is a naming convention used where an abstract method would force compliance? (`switch` on type tag vs. polymorphic method)
205
+ - [ ] **G28** — Are complex conditionals extracted into descriptive boolean functions? (`if (shouldBeDeleted(timer))` vs. `if (timer.hasExpired() && !timer.isRecurrent())`)
206
+ - [ ] **G29** — Are conditionals written positively where possible? (`if (buffer.shouldCompact())` vs. `if (!buffer.shouldNotCompact())`)
207
+ - [ ] **G30** — Do functions do more than one thing? (Same as Ch. 3 — "Do one thing")
208
+ - [ ] **G31** — Are there hidden temporal couplings where one function must be called before another with no structural enforcement?
209
+ - [ ] **G32** — Is there unexplained structure — decisions made without a discernible reason?
210
+ - [ ] **G33** — Are boundary conditions (`level + 1`, `offset + 1`) encapsulated in explanatory variables rather than scattered inline?
211
+ - [ ] **G34** — Do functions descend more than one level of abstraction below the function's name?
212
+ - [ ] **G35** — Are configurable constants buried deep in a function body rather than defined at the highest meaningful level?
213
+ - [ ] **G36** — Does any code reach through a chain of associations to get at data? (`a.getB().getC()`) — Law of Demeter violation.
214
+
215
+ ### Names (N-codes)
216
+ - [ ] **N1** — Are all names descriptive? Do they make the code readable on its own?
217
+ - [ ] **N2** — Are names appropriate for the level of abstraction? Not too specific, not too vague?
218
+ - [ ] **N3** — Are standard names from design patterns and domain language used where applicable?
219
+ - [ ] **N4** — Are names precise enough to be unambiguous between similar concepts?
220
+ - [ ] **N5** — Do names scale in length with their scope? Long names for long-lived variables, short for tightly scoped.
221
+ - [ ] **N6** — Is there any encoding in names (Hungarian notation, `m_` prefix, type suffixes)?
222
+ - [ ] **N7** — Do function names describe side effects? Does `getOos()` that creates an object need to be `createOrReturnOos()`?
223
+
224
+ ### Tests (T-codes)
225
+ - [ ] **T1** — Does the test suite cover all logic that could possibly break?
226
+ - [ ] **T2** — Is a coverage tool being used and its output reviewed?
227
+ - [ ] **T3** — Are trivial tests present? They have documentary value even if they seem obvious.
228
+ - [ ] **T4** — Are ignored/skipped tests marked with a note explaining the open question?
229
+ - [ ] **T5** — Are boundary conditions tested?
230
+ - [ ] **T6** — When a bug is fixed, are exhaustive tests added for the surrounding logic?
231
+ - [ ] **T7** — Are patterns of test failure used to diagnose root causes?
232
+ - [ ] **T8** — Is the pattern of uncovered code analyzed for structural insight?
233
+ - [ ] **T9** — Do all tests run fast enough that developers run them frequently?
234
+
235
+ ---
236
+
237
+ ## Quick Review Workflow
238
+
239
+ 1. **Naming pass** — Read every name. Does each name reveal intent? Would any name require a comment to explain it?
240
+ 2. **Function pass** — Evaluate each function: size, argument count, single responsibility, no side effects, no flag args.
241
+ 3. **Comment audit** — Eliminate C1-C5 smells. Verify any surviving comments add intent not present in the code.
242
+ 4. **Structure check** — Formatting, vertical distance, newspaper metaphor, class cohesion.
243
+ 5. **Error handling** — No null returns, no error codes, exceptions with context, Special Case pattern where applicable.
244
+ 6. **G-code scan** — Run through G1-G36 for systemic smells.
245
+ 7. **Test quality** — F.I.R.S.T., T1-T9, one concept per test, boundary conditions.
246
+
247
+ ## Severity Levels
248
+
249
+ | Severity | Description | Examples |
250
+ |----------|-------------|---------|
251
+ | **Critical** | Fundamentally undermines readability or introduces likely bugs | Commented-out code (C5), null returns on failure, disabled safeties (G4), dead code (G9) |
252
+ | **High** | Meaningful quality violations that should be fixed | Flag arguments (F3), train wrecks (G36), feature envy (G14), insufficient tests (T1) |
253
+ | **Medium** | Non-idiomatic patterns that hurt long-term maintainability | Magic numbers (G25), negative conditionals (G29), missing boundary tests (T5), misleading names |
254
+ | **Low** | Polish and refinements | Noise comments (C3), missing explanatory variables (G19), minor convention violations (G24) |