OBEY The Pragmatic Programmer by Andrew Hunt and David Thomas
Purpose
This repository follows The Pragmatic Programmer in the sense of Andrew Hunt and David Thomas:
work pragmatically, take responsibility for quality, automate what is repetitive, and keep code and process adaptable.
All code generation, edits, and reviews must optimize for:
- clear ownership and responsibility
- avoiding duplicated knowledge
- orthogonality
- incremental delivery
- ruthless feedback
- automation of repetitive work
- code that is easy to change and easy to reason about
This file is a binding engineering policy: MUST is binding, SHOULD is a strong default, and MUST NOT is forbidden.
Primary Directive
Be pragmatic, not dogmatic.
When uncertain, choose the option that:
- reduces knowledge duplication
- keeps concerns independent
- shortens feedback loops
- leaves the system easier to change
- makes intent clearer to future maintainers
Do not follow style or process rituals that do not improve outcomes.
Core Pragmatic Principles
Own the Result
- Take responsibility for the quality and changeability of the code you touch.
- Do not blame tooling, framework defaults, or “existing style” for avoidable bad design.
- Surface trade-offs, risks, and uncertainty explicitly.
Think Beyond the Local Edit
- Every change affects future maintainability.
- Small quick fixes that multiply future cost are usually a bad bargain.
- Leave the area better than you found it.
Favor Adaptability
- Build systems that are easy to observe, test, and change.
- Prefer flexible boundaries over brittle cleverness.
- Avoid premature commitment when requirements are still moving.
Named Pragmatic Habits
- Treat quality as a requirement to negotiate with users and sponsors, not as an abstract pursuit of perfection.
- Stop polishing when the software is good enough for its real users and risks.
- Keep a knowledge portfolio: invest in learning, diversify skills, and revisit stale assumptions.
- Communicate decisions, risks, and tradeoffs clearly enough that others can act on them.
- Watch for entropy and small broken windows before they become normal.
- Use Stone Soup tactics only to create real progress, not to hide missing agreement.
- Watch for boiled-frog drift where gradual degradation becomes invisible.
DRY Rules
DRY means do not duplicate knowledge, not merely do not duplicate text.
- A business rule should have one authoritative representation.
- Validation logic for the same concept should not be scattered.
- Status semantics, mappings, and calculations should not be copied across layers.
- Configuration and schema meaning should not be repeated inconsistently.
- Avoid duplicated process steps that can be automated.
Anti-patterns (MUST NOT):
- the same rule encoded in UI, API, service, and DB trigger with no ownership
- copy/paste with minor edits for “just this one case”
- duplicated manual deployment or testing steps
- one concept with multiple partially aligned implementations
Orthogonality Rules
- Keep components independent so one change does not force unrelated changes elsewhere.
- Minimize hidden couplings through globals, ambient context, or shared mutable state.
- Avoid overlapping responsibilities between modules.
- Separate policy from mechanism, data from presentation, orchestration from computation.
Anti-patterns (MUST NOT):
- one change requiring edits in many unrelated places
- one module knowing too much about internal details of others
- shared utility modules creating sideways coupling everywhere
Tracer Bullets and Iterative Delivery
- Prefer a thin end-to-end slice over a pile of isolated pieces.
- Use tracer bullets to validate architecture, integration, and assumptions early.
- Keep the first slice simple but real enough to prove the path.
- Refine from working feedback instead of predicting everything up front.
Anti-patterns (MUST NOT):
- building many layers before anything runs end to end
- treating prototypes as production without hardening
- waiting for perfect certainty before integrating
Reversibility, Domain Languages, and Requirements
- Preserve reversibility when requirements, vendors, platforms, databases, or deployment environments may change.
- Avoid irreversible commitments until evidence makes them worth the cost.
- Use a small domain language when it expresses domain rules more directly than general-purpose code.
- Keep domain languages readable by the people who must validate or change them.
- Dig for real requirements; do not accept current implementation details as requirements.
- Do not fall into the specification trap where prose keeps growing but uncertainty does not fall.
- Start building a working slice when further specification no longer reduces meaningful risk.
- Respect informed hesitation: if the team is not ready, identify the missing information or feedback.
Prototyping Rules
- Use prototypes to learn, not to pretend you are done.
- Be explicit about what a prototype proves and what it does not.
- Do not let experimental shortcuts silently become production defaults.
- Carry forward only the lessons or code that still deserve to survive.
Automation Rules
- Automate repetitive, error-prone, or easy-to-forget tasks.
- Prefer repeatable scripts over tribal-knowledge commands.
- Build, test, lint, format, package, and deploy steps should be reproducible.
- Keep local automation aligned with the project's shared build, test, and release automation.
Anti-patterns (MUST NOT):
- “works on my machine” build steps
- manual release rituals with many hidden prerequisites
- documentation that describes what a script should do instead of having the script
Feedback Loop Rules
- Shorten the time between change and feedback.
- Run relevant tests early and often.
- Use automated checks where they reduce real risk.
- Make failure visible fast.
- Prefer a cheap early signal over a late expensive surprise.
Design by Contract and Assertions
- Make assumptions explicit in code.
- Use assertions or invariant checks where they clarify impossible states.
- Distinguish between programmer errors, contract violations, and expected domain failures.
- Keep contracts close to the abstraction they protect.
Anti-patterns (MUST NOT):
- relying on comments for critical preconditions
- hiding invariant assumptions in scattered callers
- returning nonsense values for impossible states
Error Handling and Recovery
- Detect errors close to their source.
- Do not discard useful error context.
- Let callers distinguish retryable, recoverable, and permanent failures where relevant.
- Fail loudly enough to diagnose, but with boundaries that prevent system-wide collapse.
Naming and Communication Rules
- Code is communication first.
- Use names that reflect domain meaning and developer intent.
- Prefer clarity over cleverness.
- Write comments or docs where they convey decision rationale, contracts, or non-obvious behavior.
- Writing is part of engineering, not overhead.
Text and Data Rules
- Favor plain text and open formats for long-lived automation and integration where practical.
- Make scripts and configs inspectable and diffable.
- Keep serialization and config formats explicit and version-aware.
- Avoid opaque binary or framework-specific lock-in unless justified.
State and Concurrency Rules
- Treat shared mutable state as expensive.
- Prefer immutability, isolation, or explicit synchronization when state is shared.
- Keep concurrency assumptions visible.
- Do not add asynchronous complexity unless it clearly earns its cost.
Estimation and Increment Rules
- Break work into pieces that can be reasoned about, tested, and corrected.
- Keep plans and estimates honest about uncertainty.
- Prefer small deliverable increments to large hidden progress.
- Make risk visible early.
Tooling Rules
- Know and use the tools that amplify correctness and speed.
- Do not hand-do tasks that should be scripted.
- Keep editor, formatter, lint, tests, and local scripts aligned with team standards.
- Improve the toolchain when repeated friction appears.
Basic Tool Rules
- Use source control for every meaningful project, including small or solo work.
- Prefer inspectable plain text for long-lived scripts, configs, data, and generated sources when practical.
- Use shell tools for exploration, automation, and repeatable transformations where they fit.
- Use editor capabilities to reduce repetitive manual edits.
- Use text manipulation languages or scripts for systematic changes that would be error-prone by hand.
- Use code generators to remove duplicated mechanical work, but keep the source specification authoritative.
- When debugging, do not guess: reproduce, observe, isolate, explain, fix, and verify.
- Do not rely on generated code, tools, specifications, or formal methods you do not understand.
Resource and Coupling Rules
- Finish what you start when allocating, opening, locking, or otherwise acquiring resources.
- Release every resource you acquire, preferably in the opposite order from acquisition.
- Keep resource ownership local and explicit.
- Apply shy-code and Law of Demeter discipline so modules reveal only necessary information.
- Avoid temporal coupling; make ordering requirements explicit or remove them.
- Use metaprogramming only when it reduces duplication or improves adaptability without hiding behavior.
- Use blackboard-style coordination only when uncertain order, multiple sources, or opportunistic collaboration justify it.
- Understand algorithmic growth before writing or accepting performance-sensitive code.
Project and Team Rules
- Build pragmatic teams around shared responsibility, automation, fast feedback, and visible quality.
- Test unit behavior, integration, validation and verification, resource exhaustion, errors and recovery, performance, usability, and tests themselves where relevant.
- Treat writing as engineering work: docs, comments, commit messages, scripts, and tests must communicate intent.
- Set expectations explicitly with users and stakeholders.
- Take pride in code, tests, documentation, and generated artifacts.
- Be skeptical of methods, diagrams, and ceremonies that do not improve the work.
Broken Windows Rule
- Do not normalize local decay.
- Fix small quality problems before they signal that nobody cares.
- Tidy the code you touch where the cost is low and the value is immediate.
- Avoid leaving behind “temporary” hacks with no cleanup plan.
Review Rules
When reviewing code, actively look for:
- duplicated knowledge, not just duplicated lines
- hidden couplings
- missing automation opportunities
- long feedback loops
- local fixes that worsen future changeability
- unclear contracts or assumptions
- non-repeatable manual processes
- brittle integration points
- code that communicates poorly
Forbidden Patterns
Cargo-Cult Process
- rituals followed with no benefit
- documentation and checklists replacing automation
Knowledge Duplication
- same rule in many places
- copied logic because “layers need it too”
Non-Orthogonal Design
- modules with overlapping responsibilities
- changes leaking across boundaries by default
Manual Everything
- repeated human steps for build, test, release, setup, or validation
- hidden local environment assumptions
Prototype Fossilization
- experimental code promoted to production without redesign or hardening
Code Generation Rules
When generating code, default to:
- one clear source of truth for each rule
- orthogonal responsibilities
- fast local feedback
- automation over repeated manual work
- explicit contracts and assumptions
- readable names and communication
- incremental end-to-end slices when building new capabilities
Avoid by default:
- copy/paste rule duplication
- tangled modules
- fragile manual workflows
- overcommitting to an architecture before the first end-to-end path works
Testing Rules
- Keep tests runnable quickly and often.
- Prefer tests that align with the business or technical contract being protected.
- Use automation so validation is habitual, not heroic.
- Keep flaky or environment-dependent tests out of the critical feedback path where possible.
Review Checklist
Before finalizing any change, verify:
- Did we reduce duplicated knowledge?
- Are responsibilities more orthogonal after the change?
- Did we improve or preserve fast feedback?
- Did we automate anything repetitive that was hurting reliability?
- Are contracts and assumptions clearer?
- Is the code easier to communicate about?
- Did we avoid prototype shortcuts becoming silent production defaults?
- Did we fix at least one small “broken window” if it was in the touched area?
If any answer is no, revise before shipping.
Final Instruction
When uncertain, choose the option that:
- removes duplicated knowledge
- keeps concerns orthogonal
- shortens feedback loops
- improves automation
- leaves the codebase easier to change tomorrow
Be pragmatic, and make the right thing the easy thing.
1---2name: book-the-pragmatic-programmer-full3description: The Pragmatic Programmer (Hunt & Thomas) — Full rules — comprehensive mandatory coding standards. Use when asked to apply The Pragmatic Programmer principles or review code against The Pragmatic Programmer standards.4license: MIT5---6
7# OBEY The Pragmatic Programmer by Andrew Hunt and David Thomas
8
9## Purpose
10
11This repository follows **The Pragmatic Programmer** in the sense of Andrew Hunt and David Thomas:
12work pragmatically, take responsibility for quality, automate what is repetitive, and keep code and process adaptable.
13
14All code generation, edits, and reviews must optimize for:
15- clear ownership and responsibility
16- avoiding duplicated knowledge
17- orthogonality
18- incremental delivery
19- ruthless feedback
20- automation of repetitive work
21- code that is easy to change and easy to reason about
22
23This file is a binding engineering policy: `MUST` is binding, `SHOULD` is a strong default, and `MUST NOT` is forbidden.
24
25---
26
27## Primary Directive
28
29Be pragmatic, not dogmatic.
30
31When uncertain, choose the option that:
321. reduces knowledge duplication
332. keeps concerns independent
343. shortens feedback loops
354. leaves the system easier to change
365. makes intent clearer to future maintainers
37
38Do not follow style or process rituals that do not improve outcomes.
39
40---
41
42## Core Pragmatic Principles
43
44### Own the Result
451. Take responsibility for the quality and changeability of the code you touch.
462. Do not blame tooling, framework defaults, or “existing style” for avoidable bad design.
473. Surface trade-offs, risks, and uncertainty explicitly.
48
49### Think Beyond the Local Edit
501. Every change affects future maintainability.
512. Small quick fixes that multiply future cost are usually a bad bargain.
523. Leave the area better than you found it.
53
54### Favor Adaptability
551. Build systems that are easy to observe, test, and change.
562. Prefer flexible boundaries over brittle cleverness.
573. Avoid premature commitment when requirements are still moving.
58
59### Named Pragmatic Habits
601. Treat quality as a requirement to negotiate with users and sponsors, not as an abstract pursuit of perfection.
612. Stop polishing when the software is good enough for its real users and risks.
623. Keep a knowledge portfolio: invest in learning, diversify skills, and revisit stale assumptions.
634. Communicate decisions, risks, and tradeoffs clearly enough that others can act on them.
645. Watch for entropy and small broken windows before they become normal.
656. Use Stone Soup tactics only to create real progress, not to hide missing agreement.
667. Watch for boiled-frog drift where gradual degradation becomes invisible.
67
68---
69
70## DRY Rules
71
72DRY means **do not duplicate knowledge**, not merely do not duplicate text.
73
741. A business rule should have one authoritative representation.
752. Validation logic for the same concept should not be scattered.
763. Status semantics, mappings, and calculations should not be copied across layers.
774. Configuration and schema meaning should not be repeated inconsistently.
785. Avoid duplicated process steps that can be automated.
79
80Anti-patterns (MUST NOT):
81- the same rule encoded in UI, API, service, and DB trigger with no ownership
82- copy/paste with minor edits for “just this one case”
83- duplicated manual deployment or testing steps
84- one concept with multiple partially aligned implementations
85
86---
87
88## Orthogonality Rules
89
901. Keep components independent so one change does not force unrelated changes elsewhere.
912. Minimize hidden couplings through globals, ambient context, or shared mutable state.
923. Avoid overlapping responsibilities between modules.
934. Separate policy from mechanism, data from presentation, orchestration from computation.
94
95Anti-patterns (MUST NOT):
96- one change requiring edits in many unrelated places
97- one module knowing too much about internal details of others
98- shared utility modules creating sideways coupling everywhere
99
100---
101
102## Tracer Bullets and Iterative Delivery
103
1041. Prefer a thin end-to-end slice over a pile of isolated pieces.
1052. Use tracer bullets to validate architecture, integration, and assumptions early.
1063. Keep the first slice simple but real enough to prove the path.
1074. Refine from working feedback instead of predicting everything up front.
108
109Anti-patterns (MUST NOT):
110- building many layers before anything runs end to end
111- treating prototypes as production without hardening
112- waiting for perfect certainty before integrating
113
114---
115
116## Reversibility, Domain Languages, and Requirements
117
1181. Preserve reversibility when requirements, vendors, platforms, databases, or deployment environments may change.
1192. Avoid irreversible commitments until evidence makes them worth the cost.
1203. Use a small domain language when it expresses domain rules more directly than general-purpose code.
1214. Keep domain languages readable by the people who must validate or change them.
1225. Dig for real requirements; do not accept current implementation details as requirements.
1236. Do not fall into the specification trap where prose keeps growing but uncertainty does not fall.
1247. Start building a working slice when further specification no longer reduces meaningful risk.
1258. Respect informed hesitation: if the team is not ready, identify the missing information or feedback.
126
127---
128
129## Prototyping Rules
130
1311. Use prototypes to learn, not to pretend you are done.
1322. Be explicit about what a prototype proves and what it does not.
1333. Do not let experimental shortcuts silently become production defaults.
1344. Carry forward only the lessons or code that still deserve to survive.
135
136---
137
138## Automation Rules
139
1401. Automate repetitive, error-prone, or easy-to-forget tasks.
1412. Prefer repeatable scripts over tribal-knowledge commands.
1423. Build, test, lint, format, package, and deploy steps should be reproducible.
1434. Keep local automation aligned with the project's shared build, test, and release automation.
144
145Anti-patterns (MUST NOT):
146- “works on my machine” build steps
147- manual release rituals with many hidden prerequisites
148- documentation that describes what a script should do instead of having the script
149
150---
151
152## Feedback Loop Rules
153
1541. Shorten the time between change and feedback.
1552. Run relevant tests early and often.
1563. Use automated checks where they reduce real risk.
1574. Make failure visible fast.
1585. Prefer a cheap early signal over a late expensive surprise.
159
160---
161
162## Design by Contract and Assertions
163
1641. Make assumptions explicit in code.
1652. Use assertions or invariant checks where they clarify impossible states.
1663. Distinguish between programmer errors, contract violations, and expected domain failures.
1674. Keep contracts close to the abstraction they protect.
168
169Anti-patterns (MUST NOT):
170- relying on comments for critical preconditions
171- hiding invariant assumptions in scattered callers
172- returning nonsense values for impossible states
173
174---
175
176## Error Handling and Recovery
177
1781. Detect errors close to their source.
1792. Do not discard useful error context.
1803. Let callers distinguish retryable, recoverable, and permanent failures where relevant.
1814. Fail loudly enough to diagnose, but with boundaries that prevent system-wide collapse.
182
183---
184
185## Naming and Communication Rules
186
1871. Code is communication first.
1882. Use names that reflect domain meaning and developer intent.
1893. Prefer clarity over cleverness.
1904. Write comments or docs where they convey decision rationale, contracts, or non-obvious behavior.
1915. Writing is part of engineering, not overhead.
192
193---
194
195## Text and Data Rules
196
1971. Favor plain text and open formats for long-lived automation and integration where practical.
1982. Make scripts and configs inspectable and diffable.
1993. Keep serialization and config formats explicit and version-aware.
2004. Avoid opaque binary or framework-specific lock-in unless justified.
201
202---
203
204## State and Concurrency Rules
205
2061. Treat shared mutable state as expensive.
2072. Prefer immutability, isolation, or explicit synchronization when state is shared.
2083. Keep concurrency assumptions visible.
2094. Do not add asynchronous complexity unless it clearly earns its cost.
210
211---
212
213## Estimation and Increment Rules
214
2151. Break work into pieces that can be reasoned about, tested, and corrected.
2162. Keep plans and estimates honest about uncertainty.
2173. Prefer small deliverable increments to large hidden progress.
2184. Make risk visible early.
219
220---
221
222## Tooling Rules
223
2241. Know and use the tools that amplify correctness and speed.
2252. Do not hand-do tasks that should be scripted.
2263. Keep editor, formatter, lint, tests, and local scripts aligned with team standards.
2274. Improve the toolchain when repeated friction appears.
228
229### Basic Tool Rules
230- Use source control for every meaningful project, including small or solo work.
231- Prefer inspectable plain text for long-lived scripts, configs, data, and generated sources when practical.
232- Use shell tools for exploration, automation, and repeatable transformations where they fit.
233- Use editor capabilities to reduce repetitive manual edits.
234- Use text manipulation languages or scripts for systematic changes that would be error-prone by hand.
235- Use code generators to remove duplicated mechanical work, but keep the source specification authoritative.
236- When debugging, do not guess: reproduce, observe, isolate, explain, fix, and verify.
237- Do not rely on generated code, tools, specifications, or formal methods you do not understand.
238
239---
240
241## Resource and Coupling Rules
242
2431. Finish what you start when allocating, opening, locking, or otherwise acquiring resources.
2442. Release every resource you acquire, preferably in the opposite order from acquisition.
2453. Keep resource ownership local and explicit.
2464. Apply shy-code and Law of Demeter discipline so modules reveal only necessary information.
2475. Avoid temporal coupling; make ordering requirements explicit or remove them.
2486. Use metaprogramming only when it reduces duplication or improves adaptability without hiding behavior.
2497. Use blackboard-style coordination only when uncertain order, multiple sources, or opportunistic collaboration justify it.
2508. Understand algorithmic growth before writing or accepting performance-sensitive code.
251
252---
253
254## Project and Team Rules
255
2561. Build pragmatic teams around shared responsibility, automation, fast feedback, and visible quality.
2572. Test unit behavior, integration, validation and verification, resource exhaustion, errors and recovery, performance, usability, and tests themselves where relevant.
2583. Treat writing as engineering work: docs, comments, commit messages, scripts, and tests must communicate intent.
2594. Set expectations explicitly with users and stakeholders.
2605. Take pride in code, tests, documentation, and generated artifacts.
2616. Be skeptical of methods, diagrams, and ceremonies that do not improve the work.
262
263---
264
265## Broken Windows Rule
266
2671. Do not normalize local decay.
2682. Fix small quality problems before they signal that nobody cares.
2693. Tidy the code you touch where the cost is low and the value is immediate.
2704. Avoid leaving behind “temporary” hacks with no cleanup plan.
271
272---
273
274## Review Rules
275
276When reviewing code, actively look for:
277- duplicated knowledge, not just duplicated lines
278- hidden couplings
279- missing automation opportunities
280- long feedback loops
281- local fixes that worsen future changeability
282- unclear contracts or assumptions
283- non-repeatable manual processes
284- brittle integration points
285- code that communicates poorly
286
287---
288
289## Forbidden Patterns
290
291### Cargo-Cult Process
292- rituals followed with no benefit
293- documentation and checklists replacing automation
294
295### Knowledge Duplication
296- same rule in many places
297- copied logic because “layers need it too”
298
299### Non-Orthogonal Design
300- modules with overlapping responsibilities
301- changes leaking across boundaries by default
302
303### Manual Everything
304- repeated human steps for build, test, release, setup, or validation
305- hidden local environment assumptions
306
307### Prototype Fossilization
308- experimental code promoted to production without redesign or hardening
309
310---
311
312## Code Generation Rules
313
314When generating code, default to:
3151. one clear source of truth for each rule
3162. orthogonal responsibilities
3173. fast local feedback
3184. automation over repeated manual work
3195. explicit contracts and assumptions
3206. readable names and communication
3217. incremental end-to-end slices when building new capabilities
322
323Avoid by default:
324- copy/paste rule duplication
325- tangled modules
326- fragile manual workflows
327- overcommitting to an architecture before the first end-to-end path works
328
329---
330
331## Testing Rules
332
3331. Keep tests runnable quickly and often.
3342. Prefer tests that align with the business or technical contract being protected.
3353. Use automation so validation is habitual, not heroic.
3364. Keep flaky or environment-dependent tests out of the critical feedback path where possible.
337
338---
339
340## Review Checklist
341
342Before finalizing any change, verify:
343- Did we reduce duplicated knowledge?
344- Are responsibilities more orthogonal after the change?
345- Did we improve or preserve fast feedback?
346- Did we automate anything repetitive that was hurting reliability?
347- Are contracts and assumptions clearer?
348- Is the code easier to communicate about?
349- Did we avoid prototype shortcuts becoming silent production defaults?
350- Did we fix at least one small “broken window” if it was in the touched area?
351
352If any answer is no, revise before shipping.
353
354---
355
356## Final Instruction
357
358When uncertain, choose the option that:
3591. removes duplicated knowledge
3602. keeps concerns orthogonal
3613. shortens feedback loops
3624. improves automation
3635. leaves the codebase easier to change tomorrow
364
365Be pragmatic, and make the right thing the easy thing.