{"slug":"pragmatic-programmer-3","title":"pragmatic-programmer","summary":"Apply meta-principles of software craftsmanship: DRY, orthogonality, tracer bullets, and design by contract. Use when the user mentions \"best practices\", \"pragmatic approach\", \"broken windows\", \"tracer bullet\", \"software craftsmanship\", \"avoid technical debt\", \"code ownership\", o","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-13T18:25:04.329219Z","repo":{"url":"https://github.com/wondelai/skills","stars":2263,"forks":230,"license":"MIT","updatedAt":"2026-09-10T21:48:01Z"},"bodyHtml":"<hr>\n<h2>name: pragmatic-programmer\ndescription: 'Apply meta-principles of software craftsmanship: DRY, orthogonality, tracer bullets, and design by contract. Use when the user mentions \"best practices\", \"pragmatic approach\", \"broken windows\", \"tracer bullet\", \"software craftsmanship\", \"avoid technical debt\", \"code ownership\", or \"how do I become a better developer\". Also trigger when evaluating build-vs-buy decisions, designing estimation approaches, or choosing between reversible and irreversible architectural decisions. Covers estimation, domain languages, and reversibility. For code-level quality, see clean-code. For refactoring techniques, see refactoring-patterns.'\nlicense: MIT\nmetadata:\nauthor: wondelai\nversion: \"1.4.0\"</h2>\n<h1>The Pragmatic Programmer Framework</h1>\n<p>A systems-level approach to software craftsmanship from Hunt &amp; Thomas' \"The Pragmatic Programmer\" (20th Anniversary Edition). Apply these meta-principles when designing systems, reviewing architecture, writing code, or advising on engineering culture -- how to think about software, not just how to write it.</p>\n<h2>Core Principle</h2>\n<p><strong>Care about your craft.</strong> Software development demands continuous learning, disciplined practice, and personal responsibility -- pragmatic programmers think beyond the immediate problem to context, trade-offs, and long-term consequences. Great software comes from great habits: avoid duplication ruthlessly, keep components orthogonal, and treat every line of code as a living asset that must earn its place. The goal is not perfection -- it is systems that are easy to change, easy to understand, and easy to trust.</p>\n<h2>Scoring</h2>\n<p><strong>Goal: 10/10.</strong> Score against the seven Quick Diagnostic rows: award ~1.4 points per row answered \"yes\" (7 yes = 10). Then band the result:</p>\n<ul>\n<li><strong>9-10</strong>: every principle holds -- DRY knowledge, orthogonal layers, a working tracer slice, contracts at boundaries, no broken windows, reversible vendor/DB choices, ranged estimates.</li>\n<li><strong>5-6</strong>: 1-2 violations that cost real change-effort (e.g. business logic coupled to the DB, single-point estimates).</li>\n<li><strong>&lt;=3</strong>: pervasive duplication, global state, or accumulated broken windows -- entropy is winning.</li>\n</ul>\n<p>Always state the score, name the failing diagnostic rows, and give the specific fix from the Action column to reach 10/10.</p>\n<h2>The Seven Meta-Principles</h2>\n<p>Seven principles for building software that lasts:</p>\n<h3>1. DRY (Don't Repeat Yourself)</h3>\n<p><strong>Core concept:</strong> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. DRY is about knowledge, not code -- duplicated logic, business rules, or configuration are far more dangerous than duplicated syntax.</p>\n<p><strong>Why it works:</strong> Duplicated knowledge must be changed in multiple places; eventually one gets missed, introducing inconsistency. DRY reduces the surface area for bugs and makes systems easier to change.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>DRY applies to knowledge and intent, not textual similarity -- two identical code blocks serving different business rules are NOT duplication</li>\n<li>Four types of duplication: imposed (environment forces it), inadvertent (developers don't realize), impatient (too lazy to abstract), inter-developer (multiple people duplicate)</li>\n<li>Comments that restate the code violate DRY -- explain <em>why</em>, not <em>what</em></li>\n<li>Database schemas, API specs, and documentation duplicate knowledge unless generated from a single source</li>\n<li>The opposite of DRY is WET: \"Write Everything Twice\" or \"We Enjoy Typing\"</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Config values</strong></td>\n<td>Single source of truth</td>\n<td>DB connection in one env file, referenced everywhere</td>\n</tr>\n<tr>\n<td><strong>Validation rules</strong></td>\n<td>Shared schema</td>\n<td>One JSON Schema or Zod schema for client and server</td>\n</tr>\n<tr>\n<td><strong>API contracts</strong></td>\n<td>Generate from spec</td>\n<td>OpenAPI spec generates types, docs, and client code</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/dry-orthogonality.md\">references/dry-orthogonality.md</a> when classifying a specific duplication or deciding whether two code blocks are truly the same knowledge -- per-type examples and mitigations for the four duplication types.</p>\n<h3>2. Orthogonality</h3>\n<p><strong>Core concept:</strong> Two components are orthogonal if changes in one do not affect the other. Design systems where components are self-contained, independent, and have a single, well-defined purpose.</p>\n<p><strong>Why it works:</strong> Decoupling localizes change -- a fix in one module can't ripple into unrelated ones, so blast radius stays bounded. Change the database layer and the UI should not break; change the auth provider and business logic should not care.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>Ask: \"If I dramatically change the requirements behind a function, how many modules are affected?\" The answer should be one</li>\n<li>Eliminate effects between unrelated things -- a logging change should never break billing</li>\n<li>Layered architectures promote orthogonality: presentation, domain logic, data access</li>\n<li>Avoid global data -- every consumer of global state is coupled to it</li>\n<li>Frameworks that force you to inherit from their classes reduce orthogonality</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Architecture</strong></td>\n<td>Layered separation</td>\n<td>Controller -&gt; Service -&gt; Repository, each replaceable</td>\n</tr>\n<tr>\n<td><strong>Dependencies</strong></td>\n<td>Dependency injection</td>\n<td>Pass a <code>Notifier</code> interface, not a <code>SlackClient</code> concrete class</td>\n</tr>\n<tr>\n<td><strong>Testing</strong></td>\n<td>Isolated unit tests</td>\n<td>Test business logic without database, network, or filesystem</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/dry-orthogonality.md\">references/dry-orthogonality.md</a> when measuring coupling or refactoring toward decoupled layers -- the change-impact and stranger tests, layered-architecture diagram, and the helicopter analogy.</p>\n<h3>3. Tracer Bullets and Prototypes</h3>\n<p><strong>Core concept:</strong> Tracer bullets are end-to-end implementations connecting all layers of the system with minimal functionality. Unlike prototypes (which are throwaway), tracer bullet code is production code -- thin but real.</p>\n<p><strong>Why it works:</strong> Tracer bullets give immediate end-to-end feedback before you invest in filling out every feature. Users see something real, developers have a framework to build on, and integration issues surface early.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>Tracer bullet: thin but complete path through the system (UI -&gt; API -&gt; DB) -- you keep it</li>\n<li>Prototype: focused exploration of a single risky aspect -- you throw it away</li>\n<li>Use tracer bullets when \"shooting in the dark\" -- vague requirements, unproven architecture</li>\n<li>If a tracer misses, adjust and fire again -- the cost of iteration is low</li>\n<li>Label prototypes clearly as throwaway -- never let one become production code</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>New project</strong></td>\n<td>Vertical slice</td>\n<td>One feature end-to-end: button -&gt; API -&gt; DB -&gt; response</td>\n</tr>\n<tr>\n<td><strong>Uncertain tech</strong></td>\n<td>Spike prototype</td>\n<td>Test WebSocket performance before committing</td>\n</tr>\n<tr>\n<td><strong>Microservice</strong></td>\n<td>Walking skeleton</td>\n<td>Hello-world service through the full CI/CD pipeline</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/tracer-bullets.md\">references/tracer-bullets.md</a> when deciding tracer vs. prototype on a new project or building a walking skeleton -- the shooting-in-the-dark decision, iteration loop, and common pitfalls.</p>\n<h3>4. Design by Contract and Assertive Programming</h3>\n<p><strong>Core concept:</strong> Define and enforce the rights and responsibilities of software modules through preconditions (what must be true before), postconditions (what is guaranteed after), and invariants (what is always true). When a contract is violated, fail immediately and loudly.</p>\n<p><strong>Why it works:</strong> Contracts make assumptions explicit. Instead of silently corrupting data or limping along in an invalid state, the system crashes at the point of the problem -- dead programs tell no lies.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>Preconditions: caller's responsibility -- \"I accept only positive integers\"</li>\n<li>Postconditions: routine's guarantee -- \"I will return a sorted list\"</li>\n<li>Invariants: always true -- \"Account balance never goes negative\"</li>\n<li>Crash early: a dead program does far less damage than a crippled one</li>\n<li>Use assertions for things that should never happen; error handling for things that might</li>\n<li>In dynamic languages, implement contracts through runtime checks and guard clauses</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Function entry</strong></td>\n<td>Precondition guard</td>\n<td><code>assert age &gt;= 0, \"Age cannot be negative\"</code> at function start</td>\n</tr>\n<tr>\n<td><strong>Class state</strong></td>\n<td>Invariant validation</td>\n<td><code>validate!</code> called after every state mutation</td>\n</tr>\n<tr>\n<td><strong>API boundary</strong></td>\n<td>Schema validation</td>\n<td>Validate request body against schema before processing</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/contracts-assertions.md\">references/contracts-assertions.md</a> when adding contracts to a routine or deciding assertion vs. error handling -- worked pre/post/invariant patterns, dynamic-language guard clauses, and the assertions-vs-error-handling boundary.</p>\n<h3>5. The Broken Window Theory</h3>\n<p><strong>Core concept:</strong> One broken window -- a badly designed piece of code, a poor management decision, a hack that \"we'll fix later\" -- starts the rot. Once a system shows neglect, entropy accelerates and discipline collapses.</p>\n<p><strong>Why it works:</strong> Psychology. When code is clean, developers feel social pressure to keep it that way; when code is already messy, the threshold for adding more mess drops to zero. Quality is a team habit, not an individual heroic effort.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>Don't leave broken windows (bad designs, wrong decisions, poor code) unrepaired</li>\n<li>If you can't fix it now, board it up: a TODO with a ticket, a disabled feature, a stub</li>\n<li>Be a catalyst for change: show people a working glimpse of the future (stone soup)</li>\n<li>Watch for slow degradation (boiled frog) -- monitor tech debt metrics over time</li>\n<li>The first hack is the most expensive because it gives permission for all subsequent hacks</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Legacy code</strong></td>\n<td>Board up windows</td>\n<td>Wrap bad code in a clean interface before adding features</td>\n</tr>\n<tr>\n<td><strong>Code review</strong></td>\n<td>Zero-tolerance for new debt</td>\n<td>Reject PRs adding <code>// TODO: fix later</code> without a ticket</td>\n</tr>\n<tr>\n<td><strong>Tech debt</strong></td>\n<td>Debt budget</td>\n<td>Allocate 20% of each sprint to fixing broken windows</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/broken-windows.md\">references/broken-windows.md</a> when a team is normalizing neglect or you need to drive a turnaround -- repair strategies, the stone-soup catalyst play, and building a culture of quality.</p>\n<h3>6. Reversibility and Flexibility</h3>\n<p><strong>Core concept:</strong> There are no final decisions. Build systems that make it easy to change your mind about databases, frameworks, vendors, architecture, and deployment targets -- the cost of change should be proportional to the scope of change.</p>\n<p><strong>Why it works:</strong> Requirements change, vendors get acquired, technologies fall out of favor. If your architecture hard-codes assumptions about any of these, every change becomes a rewrite; flexible architecture treats decisions as configuration, not structure.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>Abstract third-party dependencies behind your own interfaces -- never let vendor APIs leak into business logic</li>\n<li>The \"forking road\" test: could you switch from Postgres to DynamoDB in a week? If not, you're coupled</li>\n<li>Metadata-driven systems (config files, feature flags) are more flexible than hard-coded logic</li>\n<li>YAGNI applies to premature abstraction too -- don't build flexibility you don't need yet</li>\n<li>Reversibility is not predicting the future; it's not painting yourself into a corner</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Database</strong></td>\n<td>Repository pattern</td>\n<td>Business logic calls <code>repo.save(user)</code>, not <code>pg.query(...)</code></td>\n</tr>\n<tr>\n<td><strong>External API</strong></td>\n<td>Adapter/wrapper</td>\n<td><code>PaymentGateway</code> interface wraps Stripe; swap to Braintree later</td>\n</tr>\n<tr>\n<td><strong>Feature flags</strong></td>\n<td>Runtime toggles</td>\n<td>New checkout flow behind a flag, rollback in seconds</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/reversibility.md\">references/reversibility.md</a> when committing to a vendor or framework, or weighing how reversible a decision must be -- per-layer reversibility patterns, the forking-road test, and when NOT to optimize for reversibility.</p>\n<h3>7. Estimation and Knowledge Portfolio</h3>\n<p><strong>Core concept:</strong> Learn to estimate reliably by understanding scope, building models, decomposing into components, and assigning ranges. Manage your learning like a financial portfolio: invest regularly, diversify, and rebalance.</p>\n<p><strong>Why it works:</strong> Honest estimation builds trust with stakeholders (\"1-3 weeks\" beats a confidently wrong \"2 weeks\"). A knowledge portfolio keeps you relevant as technologies shift -- the programmer who stops learning stops being effective.</p>\n<p><strong>Key insights:</strong></p>\n<ul>\n<li>Ask \"what is this estimate for?\" -- context determines precision (budget planning vs. sprint planning)</li>\n<li>Use PERT: (Optimistic + 4x Most Likely + Pessimistic) / 6</li>\n<li>Decompose into components and estimate each; the sum is more accurate than a single guess</li>\n<li>Keep an estimation log: compare estimates to actuals and calibrate</li>\n<li>Portfolio rules: invest regularly (learn weekly), diversify beyond your stack, mix safe and speculative bets, learn emerging tech early (buy low)</li>\n</ul>\n<p><strong>Code applications:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Context</th>\n<th>Pattern</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Sprint planning</strong></td>\n<td>Range estimates</td>\n<td>\"3-5 days\" with confidence level, not a single number</td>\n</tr>\n<tr>\n<td><strong>New technology</strong></td>\n<td>Time-boxed spike</td>\n<td>\"2 days evaluating; then I can estimate properly\"</td>\n</tr>\n<tr>\n<td><strong>Learning</strong></td>\n<td>Weekly investment</td>\n<td>1 hour/week on a new language, tool, or domain</td>\n</tr>\n</tbody>\n</table>\n<p>See: <a href=\"references/estimation-portfolio.md\">references/estimation-portfolio.md</a> when producing an estimate you'll be held to or calibrating past misses -- the PERT and decomposition procedures, an estimation-log calibration loop, and portfolio rebalancing.</p>\n<h2>Common Mistakes</h2>\n<table>\n<thead>\n<tr>\n<th>Mistake</th>\n<th>Why It Fails</th>\n<th>Fix</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>DRY-ing similar-looking code that serves different purposes</td>\n<td>Couples unrelated concepts; changes to one break the other</td>\n<td>Only DRY knowledge, not coincidental code similarity</td>\n</tr>\n<tr>\n<td>Skipping tracer bullets, building layer-by-layer</td>\n<td>Integration issues surface late; no end-to-end feedback</td>\n<td>Build one thin vertical slice first</td>\n</tr>\n<tr>\n<td>Ignoring broken windows \"because we'll refactor later\"</td>\n<td>Entropy accelerates; later never comes; morale drops</td>\n<td>Fix immediately or board up with a tracked ticket</td>\n</tr>\n<tr>\n<td>Estimates as single-point commitments</td>\n<td>False precision erodes trust when missed</td>\n<td>Always give ranges with confidence levels</td>\n</tr>\n<tr>\n<td>Making everything \"flexible\" upfront</td>\n<td>Over-engineering; abstraction without evidence of need</td>\n<td>Add flexibility when you have concrete evidence you'll need it</td>\n</tr>\n<tr>\n<td>Removing production assertions \"for performance\"</td>\n<td>Bugs assertions would catch now silently corrupt data</td>\n<td>Keep critical assertions; benchmark before removing any</td>\n</tr>\n<tr>\n<td>Global state \"for convenience\"</td>\n<td>Destroys orthogonality; everything coupled to everything</td>\n<td>Use dependency injection and explicit parameters</td>\n</tr>\n</tbody>\n</table>\n<h2>Quick Diagnostic</h2>\n<table>\n<thead>\n<tr>\n<th>Question</th>\n<th>If No</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Can I change the database without touching business logic?</td>\n<td>Orthogonality violation</td>\n<td>Introduce repository/adapter pattern</td>\n</tr>\n<tr>\n<td>Do I have an end-to-end slice working?</td>\n<td>Missing tracer bullet</td>\n<td>Build one vertical slice before expanding</td>\n</tr>\n<tr>\n<td>Is every business rule defined in exactly one place?</td>\n<td>DRY violation</td>\n<td>Identify the authoritative source; remove duplicates</td>\n</tr>\n<tr>\n<td>Would a new developer call this codebase \"clean\"?</td>\n<td>Broken windows present</td>\n<td>Schedule a dedicated cleanup sprint</td>\n</tr>\n<tr>\n<td>Do my estimates include ranges and confidence levels?</td>\n<td>Estimation problem</td>\n<td>Switch to PERT or range-based estimates</td>\n</tr>\n<tr>\n<td>Can I roll back this deployment in under 5 minutes?</td>\n<td>Reversibility gap</td>\n<td>Add feature flags and blue-green deploys</td>\n</tr>\n<tr>\n<td>Am I learning something new every week?</td>\n<td>Knowledge portfolio stagnant</td>\n<td>Schedule weekly learning time and track it</td>\n</tr>\n</tbody>\n</table>\n<h2>Further Reading</h2>\n<ul>\n<li><a href=\"https://www.amazon.com/Pragmatic-Programmer-journey-mastery-Anniversary/dp/0135957052?tag=wondelai00-20\">The Pragmatic Programmer: Your Journey to Mastery, 20th Anniversary Edition</a> by Andrew Hunt and David Thomas</li>\n</ul>\n<h2>About the Authors</h2>\n<p><strong>Andrew Hunt</strong> and <strong>David Thomas</strong> co-founded the Pragmatic Bookshelf and were among the 17 original authors of the Agile Manifesto. Thomas coined \"DRY\" and \"Code Kata\" and co-authored <em>Programming Ruby</em> (the Pickaxe book); Hunt focuses on how teams learn, communicate, and maintain quality. Together they wrote <em>The Pragmatic Programmer</em>, one of the most influential software books ever published.</p>\n","files":[{"path":"references/broken-windows.md","sizeBytes":11791,"isText":true},{"path":"references/contracts-assertions.md","sizeBytes":13596,"isText":true},{"path":"references/dry-orthogonality.md","sizeBytes":11207,"isText":true},{"path":"references/estimation-portfolio.md","sizeBytes":13975,"isText":true},{"path":"references/reversibility.md","sizeBytes":14232,"isText":true},{"path":"references/tracer-bullets.md","sizeBytes":12129,"isText":true},{"path":"SKILL.md","sizeBytes":16557,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-13T18:27:02.03296Z","sha256":"37A1436630833380B9B9CB78C9E5F077199DA20F16C7B08F92655FAFD05D6056","sizeBytes":39255},"review":null,"source":{"repositoryUrl":"https://github.com/wondelai/skills","path":"plugins/wondelai-skills/skills/pragmatic-programmer","license":"MIT","commit":"c172996495bed0fcd26896a9416b2093fd7073f0","subtreeSha":"87F4E25498AF2540E75638F2E1587EDE58EB58EA309DF9B2F6A50A4866DBEE68","lastSyncedAt":"2026-09-25T23:12:05.357068Z"},"reviewedAt":"2026-09-13T18:30:52.793633Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/wondelai/skills/tree/main/plugins/wondelai-skills/skills/pragmatic-programmer"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install wondelai-skills@llmmart"},{"target":"git","command":"git clone https://github.com/wondelai/skills.git"}]}