@lenardangeloolajay/len-toolkit 1.1.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 (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -0
  3. package/bin/cli.js +244 -0
  4. package/package.json +35 -0
  5. package/src/installer.js +236 -0
  6. package/templates/configs/.editorconfig +12 -0
  7. package/templates/configs/sample.gitignore +8 -0
  8. package/templates/docs/FEATURE.md +40 -0
  9. package/templates/docs/HANDOFF.md +39 -0
  10. package/templates/docs/IMPLEMENTATION_PLAN.md +47 -0
  11. package/templates/docs/SPEC_INDEX.md +12 -0
  12. package/templates/docs/VERIFICATION.md +14 -0
  13. package/templates/docs/product/ARCHITECTURE.md +22 -0
  14. package/templates/docs/product/CONSTRAINTS.md +22 -0
  15. package/templates/docs/product/DATA_MODEL.md +22 -0
  16. package/templates/docs/product/OVERVIEW.md +22 -0
  17. package/templates/examples/flutter-handoff/EXERCISES.md +16 -0
  18. package/templates/examples/flutter-handoff/HANDOFF.md +32 -0
  19. package/templates/examples/flutter-handoff/docs/SPEC_INDEX.md +19 -0
  20. package/templates/examples/flutter-handoff/docs/evidence/FEAT-001-verification.md +14 -0
  21. package/templates/examples/flutter-handoff/docs/features/FEAT-001-local-note.md +40 -0
  22. package/templates/examples/flutter-handoff/docs/plans/FEAT-001-implementation.md +43 -0
  23. package/templates/examples/flutter-handoff/docs/product/ARCHITECTURE.md +24 -0
  24. package/templates/examples/flutter-handoff/docs/product/CONSTRAINTS.md +13 -0
  25. package/templates/examples/flutter-handoff/docs/product/DATA_MODEL.md +20 -0
  26. package/templates/examples/flutter-handoff/docs/product/OVERVIEW.md +26 -0
  27. package/templates/rules/.cursorrules +7 -0
  28. package/templates/rules/AGENTS.md +61 -0
  29. package/templates/rules/GEMINI.md +7 -0
  30. package/templates/skills/a-philosophy-of-software-design/SKILL.md +11 -0
  31. package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.md +370 -0
  32. package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.mini.md +46 -0
  33. package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.nano.md +35 -0
  34. package/templates/skills/clean-architecture/SKILL.md +11 -0
  35. package/templates/skills/clean-architecture/clean-architecture.md +515 -0
  36. package/templates/skills/clean-architecture/clean-architecture.mini.md +49 -0
  37. package/templates/skills/clean-architecture/clean-architecture.nano.md +36 -0
  38. package/templates/skills/clean-code/SKILL.md +11 -0
  39. package/templates/skills/clean-code/clean-code.md +297 -0
  40. package/templates/skills/clean-code/clean-code.mini.md +47 -0
  41. package/templates/skills/clean-code/clean-code.nano.md +32 -0
  42. package/templates/skills/code-complete/SKILL.md +11 -0
  43. package/templates/skills/code-complete/code-complete.md +354 -0
  44. package/templates/skills/code-complete/code-complete.mini.md +56 -0
  45. package/templates/skills/code-complete/code-complete.nano.md +41 -0
  46. package/templates/skills/council/SKILL.md +37 -0
  47. package/templates/skills/designing-data-intensive-applications/SKILL.md +11 -0
  48. package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.md +393 -0
  49. package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.mini.md +55 -0
  50. package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.nano.md +34 -0
  51. package/templates/skills/domain-driven-design/SKILL.md +11 -0
  52. package/templates/skills/domain-driven-design/domain-driven-design.md +979 -0
  53. package/templates/skills/domain-driven-design/domain-driven-design.mini.md +48 -0
  54. package/templates/skills/domain-driven-design/domain-driven-design.nano.md +39 -0
  55. package/templates/skills/domain-driven-design-distilled/SKILL.md +11 -0
  56. package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.md +317 -0
  57. package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.mini.md +56 -0
  58. package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.nano.md +41 -0
  59. package/templates/skills/implementation-plan/SKILL.md +42 -0
  60. package/templates/skills/implementing-domain-driven-design/SKILL.md +11 -0
  61. package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.md +337 -0
  62. package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.mini.md +57 -0
  63. package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.nano.md +37 -0
  64. package/templates/skills/patterns-of-enterprise-application-architecture/SKILL.md +11 -0
  65. package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.md +404 -0
  66. package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.mini.md +54 -0
  67. package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.nano.md +35 -0
  68. package/templates/skills/ponytail/SKILL.md +124 -0
  69. package/templates/skills/ponytail-audit/SKILL.md +45 -0
  70. package/templates/skills/ponytail-debt/SKILL.md +48 -0
  71. package/templates/skills/ponytail-gain/SKILL.md +17 -0
  72. package/templates/skills/ponytail-help/SKILL.md +42 -0
  73. package/templates/skills/ponytail-review/SKILL.md +61 -0
  74. package/templates/skills/refactoring/SKILL.md +11 -0
  75. package/templates/skills/refactoring/refactoring.md +433 -0
  76. package/templates/skills/refactoring/refactoring.mini.md +49 -0
  77. package/templates/skills/refactoring/refactoring.nano.md +37 -0
  78. package/templates/skills/refactoring-guru/SKILL.md +11 -0
  79. package/templates/skills/refactoring-guru/refactoring-guru.md +765 -0
  80. package/templates/skills/refactoring-guru/refactoring-guru.mini.md +64 -0
  81. package/templates/skills/refactoring-guru/refactoring-guru.nano.md +41 -0
  82. package/templates/skills/release-it/SKILL.md +11 -0
  83. package/templates/skills/release-it/release-it.md +382 -0
  84. package/templates/skills/release-it/release-it.mini.md +48 -0
  85. package/templates/skills/release-it/release-it.nano.md +38 -0
  86. package/templates/skills/security-audit/AI-AND-LLM.md +83 -0
  87. package/templates/skills/security-audit/ATTACK-CLASSES.md +130 -0
  88. package/templates/skills/security-audit/CLIENT-SIDE.md +83 -0
  89. package/templates/skills/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
  90. package/templates/skills/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
  91. package/templates/skills/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
  92. package/templates/skills/security-audit/HUNTING.md +251 -0
  93. package/templates/skills/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
  94. package/templates/skills/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
  95. package/templates/skills/security-audit/RECONNAISSANCE.md +156 -0
  96. package/templates/skills/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
  97. package/templates/skills/security-audit/SKILL.md +192 -0
  98. package/templates/skills/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
  99. package/templates/skills/security-audit/VALIDATION-AND-REPORTING.md +186 -0
  100. package/templates/skills/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
  101. package/templates/skills/security-audit/report-schema.json +461 -0
  102. package/templates/skills/security-audit/validate-coverage-ledger.cjs +872 -0
  103. package/templates/skills/security-audit/validate-coverage-ledger.test.cjs +740 -0
  104. package/templates/skills/security-audit/validate-findings.cjs +773 -0
  105. package/templates/skills/security-audit/validate-findings.test.cjs +652 -0
  106. package/templates/skills/spec/SKILL.md +55 -0
  107. package/templates/skills/the-pragmatic-programmer/SKILL.md +11 -0
  108. package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.md +359 -0
  109. package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.mini.md +65 -0
  110. package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.nano.md +44 -0
  111. package/templates/skills/working-effectively-with-legacy-code/SKILL.md +11 -0
  112. package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.md +371 -0
  113. package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.mini.md +50 -0
  114. package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.nano.md +35 -0
@@ -0,0 +1,371 @@
1
+ # OBEY Working Effectively with Legacy Code by Michael Feathers
2
+
3
+ ## Purpose
4
+
5
+ This repository follows the discipline of **Working Effectively with Legacy Code** in the sense of Michael Feathers:
6
+ make risky existing code changeable by gaining understanding, creating seams, and establishing tests.
7
+
8
+ All code generation, edits, and reviews must optimize for:
9
+ - safe change in poorly understood code
10
+ - characterization before redesign
11
+ - breaking dependencies that block tests
12
+ - introducing seams
13
+ - reducing fear around modification
14
+ - incremental improvement instead of heroic rewrites
15
+
16
+ This file is a binding engineering policy: `MUST` is binding, `SHOULD` is a strong default, and `MUST NOT` is forbidden.
17
+
18
+ ---
19
+
20
+ ## Primary Directive
21
+
22
+ Legacy code is code that is expensive to change safely.
23
+ In practice, the default assumption is:
24
+
25
+ **If a part of the code lacks trustworthy tests, treat it as legacy code.**
26
+
27
+ When modifying legacy code:
28
+ 1. understand what it does now
29
+ 2. protect that behavior with tests where possible
30
+ 3. find or create a seam
31
+ 4. break dependencies that prevent observation or isolation
32
+ 5. make the requested change
33
+ 6. leave the area more testable than before
34
+
35
+ Do not begin with a rewrite unless explicitly required.
36
+
37
+ ---
38
+
39
+ ## Non-Negotiable Rules
40
+
41
+ 1. **Do Not Rewrite by Reflex**
42
+ - Prefer targeted extraction and improvement.
43
+ - Rewrite only when explicitly requested or clearly safer than continued change.
44
+
45
+ 2. **Characterize Before You Redesign**
46
+ - When current behavior is uncertain, capture it.
47
+ - Use characterization tests to document what the code does today, even if the behavior is ugly.
48
+
49
+ 3. **Find or Create a Seam**
50
+ - A seam is a place where behavior can be changed without editing the surrounding code directly.
51
+ - Use seams to inject doubles, isolate dependencies, and observe behavior.
52
+
53
+ 4. **Break Dependencies Deliberately**
54
+ - Remove direct dependence on time, randomness, files, network, process environment, globals, frameworks, and static construction where they block testing.
55
+
56
+ 5. **Leave the Code More Changeable**
57
+ - Every change should ideally improve testability, visibility, or modularity.
58
+
59
+ ---
60
+
61
+ ## Default Workflow for Legacy Changes
62
+
63
+ 1. Identify the exact area affected.
64
+ 2. Determine whether trusted tests already protect the behavior.
65
+ 3. If not, add characterization tests around current behavior where possible.
66
+ 4. Identify the dependency that makes change difficult.
67
+ 5. Introduce or exploit a seam.
68
+ 6. Break the blocking dependency.
69
+ 7. Make the functional change.
70
+ 8. Refactor for clarity and keep the seam or new structure if it still pays for itself.
71
+
72
+ Short form: identify change points, find test points, break dependencies, write tests, make changes, then refactor.
73
+
74
+ Do not start by cleaning the whole module.
75
+
76
+ ---
77
+
78
+ ## Testing Strategy Rules
79
+
80
+ ### Characterization Tests
81
+ 1. Use characterization tests when you do not yet know whether the current behavior is intentional.
82
+ 2. Test externally visible behavior first.
83
+ 3. Prefer narrow tests around the slice you are about to modify.
84
+ 4. Capture ugly behavior if real consumers rely on it.
85
+ 5. Once behavior is protected, improve structure safely.
86
+ 6. Mark suspicious current behavior for clarification instead of silently "fixing" it during characterization.
87
+ 7. Use sensing variables or temporary probes only to confirm that a test reaches the intended path; remove them after use.
88
+
89
+ ### New Behavior Tests
90
+ 1. Add focused tests for the requested change.
91
+ 2. Keep old behavior tests unless the behavior change is intentional.
92
+ 3. Separate tests that describe legacy behavior from tests that describe the new requirement when useful.
93
+
94
+ ### Testability Improvements
95
+ 1. Make dependencies explicit.
96
+ 2. Remove hard-coded collaborators.
97
+ 3. Break apart mixed responsibilities that force expensive setup.
98
+ 4. Reduce constructor side effects and static initialization side effects.
99
+
100
+ ---
101
+
102
+ ## Seam Rules
103
+
104
+ ### What Counts as a Useful Seam
105
+ A useful seam is any boundary that allows substitution, observation, or interception.
106
+
107
+ Examples:
108
+ - constructor injection
109
+ - parameter injection
110
+ - extracted method
111
+ - wrapper around static call
112
+ - adapter around framework object
113
+ - factory indirection
114
+ - module boundary
115
+ - link seam, import seam, or preprocessing seam where the language/build system supports it
116
+ - subclass seam when forced by language constraints
117
+
118
+ ### Required Behavior
119
+ 1. Use the smallest seam that unlocks the change.
120
+ 2. Prefer explicit seams over magical test hooks.
121
+ 3. Prefer seams that remain useful after the current task.
122
+ 4. Create seams near hard dependencies, not randomly in the code.
123
+ 5. Separate sensing from separation: decide whether the seam observes behavior, substitutes a dependency, or both.
124
+ 6. Use link and preprocessing seams carefully; they can unlock tests but do not usually improve design by themselves.
125
+
126
+ ---
127
+
128
+ ## Dependency Breaking Rules
129
+
130
+ When legacy code is hard to test, first look for these dependency types:
131
+
132
+ ### Hidden Inputs
133
+ - current time
134
+ - random values
135
+ - environment variables
136
+ - thread-local state
137
+ - static singletons
138
+ - global configuration
139
+ - implicit current user or request
140
+
141
+ ### Hard Outputs
142
+ - direct file writes
143
+ - direct network calls
144
+ - process exits
145
+ - direct database writes
146
+ - direct message publication
147
+ - logging used as control flow
148
+
149
+ ### Construction Problems
150
+ - constructors that do real work
151
+ - new allocations of complex collaborators buried inside methods
152
+ - factory calls hidden deep in behavior
153
+ - object graphs built in the middle of logic
154
+
155
+ ### Required Moves
156
+ - wrap static and global access
157
+ - inject clocks, random generators, external interfaces, and hard collaborators
158
+ - split construction from use
159
+ - extract side effects behind explicit collaborators
160
+ - narrow the code under test to a manageable slice
161
+
162
+ ---
163
+
164
+ ## Test Selection and Understanding Rules
165
+
166
+ 1. Use effect sketches when the impact of a change is unclear.
167
+ 2. Start from the change point and trace affected values, calls, fields, outputs, and collaborators outward.
168
+ 3. Choose test points where effects can be observed with useful precision.
169
+ 4. Use interception points when several planned changes can be protected by one broader test.
170
+ 5. Use pinch points when many effects pass through one narrow point.
171
+ 6. Treat broad tests at interception points as a first step toward narrower tests.
172
+ 7. Use scratch refactoring to understand code, but discard it unless later backed by tests and review.
173
+ 8. Sketch, mark, or group responsibilities in large code before moving behavior.
174
+ 9. Do not check in exploratory restructuring that was only used to learn.
175
+
176
+ ---
177
+
178
+ ## Preferred Legacy Techniques
179
+
180
+ ### Sprout Method
181
+ Use when new behavior can be added without deeply editing fragile code.
182
+
183
+ Rules (MUST unless marked SHOULD or MUST NOT):
184
+ - extract the new behavior into a new method
185
+ - keep the old code mostly untouched
186
+ - route to the new method from a small insertion point
187
+
188
+ ### Sprout Class
189
+ Use when a new responsibility does not fit the old class or the old class is too risky to reshape first.
190
+
191
+ Rules (MUST unless marked SHOULD or MUST NOT):
192
+ - add a focused new collaborator
193
+ - delegate from the legacy class
194
+ - slowly move behavior over if later justified
195
+
196
+ ### Wrap Method
197
+ Use when you need pre/post behavior around a risky method or a better way to observe effects.
198
+
199
+ ### Wrap Class
200
+ Use when a class is too hard to test directly and behavior can be mediated through a new abstraction.
201
+
202
+ ### Extract and Override Call
203
+ Use only when language constraints leave few better options.
204
+ Prefer composition once a cleaner route appears.
205
+
206
+ ---
207
+
208
+ ## Dependency-Breaking Technique Index
209
+
210
+ - USE Adapt Parameter when a method needs only a narrow view of a hard-to-create parameter.
211
+ - USE Break Out Method Object when a large method has local state that blocks extraction and testing.
212
+ - USE Definition Completion when missing definitions block tests in languages that allow completion in test code.
213
+ - USE Encapsulate Global References when globals or singletons prevent substitution.
214
+ - USE Expose Static Method when useful logic does not need instance state but is trapped behind instance setup.
215
+ - USE Extract and Override Factory Method when construction of a hard dependency must vary under test.
216
+ - USE Extract Implementer or Extract Interface when concrete dependencies make compilation or substitution hard.
217
+ - USE Introduce Instance Delegator when static behavior needs an instance seam.
218
+ - USE Parameterize Constructor or Parameterize Method when hidden collaborators should become explicit inputs.
219
+ - USE Primitivize Parameter only when the real type is too costly to bring into a harness and primitive data is enough for the new logic.
220
+ - USE Pull Up Feature or Push Down Dependency to move behavior or dependencies to a more testable level in a hierarchy.
221
+ - USE Replace Global Reference with Getter when direct global access needs a seam.
222
+ - USE Subclass and Override Method only when safer composition seams are not available.
223
+ - USE Supersede Instance Variable when a test needs to replace a hard dependency held in a field.
224
+ - USE Template Redefinition, Text Redefinition, link seams, or preprocessing seams only when language or build constraints make ordinary object seams impractical.
225
+
226
+ ---
227
+
228
+ ## Legacy Refactoring Heuristics
229
+
230
+ 1. Work near the change point, not across the whole system.
231
+ 2. Prefer one small dependency break over a broad redesign.
232
+ 3. If a test requires too much setup, the design is telling you something useful.
233
+ 4. If code is impossible to observe, expose outcomes through smaller units.
234
+ 5. If code is impossible to invoke without full runtime setup, isolate the policy from the runtime.
235
+ 6. If code depends on many details, separate policy from mechanism.
236
+ 7. If the old code cannot be safely changed, insert new code beside it and redirect gradually.
237
+
238
+ ---
239
+
240
+ ## Handling Risky Areas
241
+
242
+ ### Large Methods
243
+ - carve out pure computation first
244
+ - isolate side effects second
245
+ - add tests around extracted parts
246
+ - avoid editing many branches at once
247
+
248
+ ### Static and Global Dependencies
249
+ - create a wrapper or façade
250
+ - move callers to the wrapper
251
+ - inject the wrapper where possible
252
+ - reduce direct calls incrementally
253
+
254
+ ### Database-Heavy Code
255
+ - separate query and mapping concerns from policy
256
+ - test policy without a real database where possible
257
+ - keep integration tests for actual persistence behavior
258
+
259
+ ### UI or Framework Code
260
+ - move decision logic out of handlers and callbacks
261
+ - test the moved logic independently
262
+ - keep adapters thin
263
+
264
+ ### Constructors Doing Too Much
265
+ - stop doing I/O, network, or configuration lookup in constructors
266
+ - move setup into factories, builders, or composition roots
267
+ - keep constructed objects easy to instantiate under test
268
+
269
+ ---
270
+
271
+ ## Review Rules
272
+
273
+ When reviewing legacy-oriented changes, actively look for:
274
+ - no tests around modified logic
275
+ - structural and behavioral changes mixed together
276
+ - broad edits in poorly understood modules
277
+ - hidden global dependencies left untouched
278
+ - hard-coded collaborators
279
+ - direct static calls
280
+ - constructors with side effects
281
+ - business logic trapped in framework entry points
282
+ - places where a sprout method or sprout class lowers risk
283
+
284
+ ---
285
+
286
+ ## Forbidden Patterns
287
+
288
+ ### Rewrite as the First Move
289
+ - replacing a subsystem before understanding current behavior
290
+ - rebuilding instead of gaining test leverage
291
+ - assuming old behavior is irrelevant because the code looks bad
292
+
293
+ ### No-Safety Change
294
+ - changing legacy code with no tests or observation strategy
295
+ - large edits with no characterization
296
+ - relying on manual reasoning alone for risky behavior
297
+
298
+ ### Hidden Dependency Expansion
299
+ - adding more globals, statics, ambient context, or framework reach-through in already hard-to-test code
300
+ - embedding new hard dependencies in the same style as the legacy code
301
+
302
+ ### Cosmetic Refactoring Only
303
+ - renaming and formatting while leaving the real dependency knots intact
304
+ - “cleanup” that does not make the next change safer
305
+
306
+ ---
307
+
308
+ ## Code Generation Rules
309
+
310
+ When asked to modify legacy code, default to producing:
311
+ - characterization tests where needed
312
+ - small seams
313
+ - wrappers around hard dependencies
314
+ - explicit collaborators
315
+ - extracted pure logic
316
+ - minimal structural edits that unlock safe change
317
+
318
+ Preferred first moves:
319
+ - extract method
320
+ - wrap static call
321
+ - inject collaborator
322
+ - split construction from behavior
323
+ - move logic out of framework entry points
324
+ - introduce a focused new class for new behavior
325
+ - add a narrow characterization test
326
+
327
+ Preferred avoidance:
328
+ - huge dependency-breaking rewrites
329
+ - replacing old modules wholesale
330
+ - introducing large new architectures before basic seams exist
331
+ - mocking untestable structure instead of improving it
332
+
333
+ ---
334
+
335
+ ## Testing Rules
336
+
337
+ 1. Prefer fast tests around the behavior you are changing.
338
+ 2. Use characterization tests to lock current behavior before deeper edits.
339
+ 3. Prefer tests at the highest level that still isolate the change safely.
340
+ 4. Keep integration tests for real boundaries, but do not depend on them alone.
341
+ 5. Once a seam exists, test through the seam.
342
+
343
+ ---
344
+
345
+ ## Review Checklist
346
+
347
+ Before finalizing any change, verify:
348
+ - Did we treat untested code as risky legacy code?
349
+ - Did we capture current behavior where it was unclear?
350
+ - Did we create or exploit a seam?
351
+ - Did we reduce at least one hard dependency?
352
+ - Is the changed area easier to test than before?
353
+ - Did we avoid a rewrite as the first move?
354
+ - Did we keep edits local to the requested change?
355
+ - Did we separate structural changes from behavior changes where practical?
356
+ - Did we leave the code more changeable than we found it?
357
+
358
+ If any answer is no, revise before shipping.
359
+
360
+ ---
361
+
362
+ ## Final Instruction
363
+
364
+ When uncertain, choose the smallest change that:
365
+ 1. increases understanding
366
+ 2. increases testability
367
+ 3. breaks one hard dependency
368
+ 4. preserves current behavior
369
+ 5. makes the next change cheaper
370
+
371
+ Reject big rewrites and heroic cleanup when a seam and a test would do.
@@ -0,0 +1,50 @@
1
+ # OBEY Working Effectively with Legacy Code by Michael Feathers
2
+
3
+ ## When to use
4
+
5
+ Use when changing code that is expensive to change safely because behavior is unclear, tests are weak or missing, dependencies are hidden, or runtime/framework setup blocks local feedback.
6
+
7
+ ## Primary bias to correct
8
+
9
+ Gain control before improving design. Understand current behavior, protect what must stay, create the smallest useful seam, break the dependency that blocks feedback, make the requested change, then leave the area more testable.
10
+
11
+ ## Decision rules
12
+
13
+ - Treat any area without trustworthy tests as legacy code; do not start with rewrite or module-wide cleanup unless that is explicitly required or clearly safer.
14
+ - Before editing, state the requested behavior change and the current behavior that must remain; characterize uncertain or suspicious behavior instead of silently fixing it.
15
+ - Follow the legacy loop: identify the change point, check existing protection, add characterization where possible, find or create a seam, break the blocking dependency, change behavior, then refactor locally.
16
+ - Prefer fast, focused tests around the slice being changed; use broader interception or integration tests only when they are the safest first observation point.
17
+ - Choose test points by tracing effects outward from the change point through values, calls, fields, outputs, collaborators, interception points, and pinch points.
18
+ - Use the smallest seam that allows substitution, observation, or interception; make clear whether the seam is for sensing, separation, or both.
19
+ - Break dependencies deliberately: expose hidden inputs, hard outputs, hard construction, globals, statics, ambient context, and framework callbacks only where they block testing or safe change.
20
+ - Keep behavior changes, structural refactorings, and cleanup separate; verify small steps and avoid checking in exploratory restructuring used only for understanding.
21
+ - When direct edits are risky, add behavior with sprout method, sprout class, wrap method, wrap class, or extract-and-override style moves, then fold the temporary structure into better design when tests support it.
22
+ - For hard-to-test methods, split construction from use, extract side effects behind collaborators, carve pure computation first, and isolate policy from runtime, persistence, UI, or framework mechanisms.
23
+ - Use dependency-breaking techniques according to the actual barrier: adapt narrow parameters, extract interfaces or implementers, parameterize constructors or methods, encapsulate globals, introduce instance delegators, override factories/calls, or use link/preprocessing seams only when ordinary object seams are impractical.
24
+ - In large code, sketch effects and group responsibilities before moving behavior; let excessive setup, impossible observation, and repeated changes point to smaller extracted responsibilities.
25
+ - During review, treat no tests around modified logic, mixed structural and behavioral edits, broad edits in poorly understood modules, hard-coded collaborators, global/static reach-through, constructor side effects, and business logic trapped in framework entry points as legacy-change risks.
26
+ - Reject changes that expand hidden dependencies, mock around untestable structure without improving it, rename or format while leaving the real dependency knots intact, or introduce large architecture before basic seams exist.
27
+ - Leave the touched area easier to understand, test, or change; do not mistake test-only seams, wrappers, subclass tricks, or build tricks for design improvement by themselves.
28
+
29
+ ## Trigger rules
30
+
31
+ - When behavior is uncertain, consumers may rely on ugly behavior, or a branch/path is hard to prove, add characterization or another explicit observation path before changing semantics.
32
+ - When tests require too much setup or a class cannot be instantiated cheaply, break the first real barrier: constructor work, hidden allocation, factory call, global state, static construction, framework object, or hard parameter.
33
+ - When time, randomness, environment, thread-local state, current user/request, files, network, process exits, database writes, messages, or control-flow logging block repeatable tests, wrap or inject that boundary.
34
+ - When a large method or class defeats local reasoning, sketch effects, find interception or pinch points, extract pure computation first, and avoid editing many branches at once.
35
+ - When changing database-heavy, UI, framework, or API-boundary code, separate policy from query/mapping/persistence, handlers/callbacks, adapters, and runtime setup; keep real-boundary integration tests where they matter.
36
+ - When a seam is magical, temporary, public-for-test, subclass-only, link/preprocessor-based, or probe/sensing-variable-based, add a cleanup obligation and remove it once safer structure exists.
37
+ - When repeated edits cluster across several places, remove duplication incrementally under tests instead of launching a broad redesign.
38
+ - When rewrite or heroic cleanup feels tempting, choose the smallest sprout, wrap, seam, characterization, or refactoring step that makes today's requested change safer.
39
+
40
+ ## Final checklist
41
+
42
+ - Untested or weakly tested area treated as legacy risk?
43
+ - Behavior delta and behavior-to-preserve stated?
44
+ - Uncertain current behavior characterized or explicitly observed?
45
+ - Tests close enough and fast enough to diagnose the change?
46
+ - Smallest useful seam chosen, with sensing vs separation clear?
47
+ - Blocking dependency reduced without expanding hidden dependencies?
48
+ - Behavior change, refactoring, and cleanup kept separate?
49
+ - Temporary seam or dependency-breaking trick has a cleanup path?
50
+ - Touched area is more understandable, testable, or changeable?
@@ -0,0 +1,35 @@
1
+ # OBEY Working Effectively with Legacy Code by Michael Feathers
2
+
3
+ ## When to use
4
+
5
+ Use when changing poorly tested or poorly understood code under a tight context budget.
6
+
7
+ ## Primary bias to correct
8
+
9
+ Legacy work starts with control, not cleanup, rewrite, or elegance.
10
+
11
+ ## Decision rules
12
+
13
+ - Treat code without trustworthy tests as legacy code: state what changes and what must remain.
14
+ - Characterize uncertain current behavior before changing it, including ugly behavior consumers may rely on.
15
+ - Use the legacy loop: find the change point, find an observation point, create or exploit a seam, break the blocking dependency, test, change, then refactor locally.
16
+ - Prefer fast focused tests; use broader harnesses only as temporary first coverage when no narrow test point exists.
17
+ - Create the narrowest useful seam for sensing or separation, and break only dependencies that block feedback.
18
+ - Use sprout, wrap, parameterize, inject, extract, or override moves when direct edits would be unsafe.
19
+ - Keep behavior changes, structural refactorings, and cleanup separate and small.
20
+ - Do not leave test-only seams, hidden dependencies, wrappers, globals, subclass tricks, or link/preprocessor tricks without a cleanup plan.
21
+
22
+ ## Trigger rules
23
+
24
+ - When behavior is unclear, characterize first.
25
+ - When constructors, globals, statics, frameworks, I/O, clocks, randomness, environment, or deep object graphs block testing, break one dependency at the narrowest point.
26
+ - When a large method or class defeats local reasoning, sketch effects and create a seam before semantic edits.
27
+ - When rewrite or broad cleanup feels tempting, choose the next smaller verified move.
28
+
29
+ ## Final checklist
30
+
31
+ - Behavior characterized?
32
+ - Feedback fast enough?
33
+ - Dependency isolated?
34
+ - One kind of change?
35
+ - Safer and clearer now?