| name | programming-principles |
| description | Apply distilled coding principles from 14 classic software books to code review, refactoring, design, and implementation decisions. Do not use for language- or framework-specific tutorials, tool manuals, or tasks already governed by a project's established conventions. |
| license | MIT |
| compatibility | Platform-agnostic. Works with any agent that supports the Agent Skills directory format. No external dependencies. |
| metadata | {"source":"https://github.com/mattpocock/agent-rules-books"} |
Programming Principles (14 Books)
Principles distilled from the mattpocock/agent-rules-books repo โ 14 pre-made
AGENTS.md rule sets derived from classic software engineering books. Use this
skill directly during code review, refactoring, design, and implementation.
For deeper per-book coverage, load the relevant reference file.
Task-to-Book Mapping
When the task involves... Load / apply principles from
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Everyday implementation & code review Clean Code, Code Complete
Refactoring existing code Refactoring, WELC
Architecture / dependency management Clean Architecture, APoSD
Domain modeling / business rules DDD, DDD Distilled, IDDD
Enterprise app patterns / layering PoEAA
Production reliability / stability Release It!
Data consistency / scalability / events DDIA
Engineering craft / automation Pragmatic Programmer
Designing APIs / module boundaries APoSD
Legacy code / risky changes WELC, Refactoring
How to Perform a Code Assessment
For a structured, reproducible workflow that combines book principles with
actual repo exploration, see references/code-assessment-workflow.md. It
covers: loading the evaluation framework, reading the repo and GitHub context,
deduplicating against existing issues/PRs, classifying findings by book +
priority, and deciding whether each merits an issue.
Cross-Cutting Principles
Principles synthesized from multiple books, organized by concern.
Naming & Communication
- One term per concept across the codebase. RENAMING is design work.
- Names reveal abstraction, not mechanism. Prefer domain vocabulary over
technical implementation detail.
- Functions are verbs, classes/types are nouns, booleans are predicates.
- A name needing a comment to explain it is the wrong name.
- Comments exist for rationale, contracts, warnings, and non-obvious constraints
โ never to narrate code or compensate for bad names.
Functions & Routines
- ONE level of abstraction per function. Tell the story top-down.
- Keep parameters few. Boolean flags mean split the function.
- Separate commands (mutate) from queries (answer). Never both.
- When a module exceeds ~400 lines or requires scrolling to understand its
full scope, it's a candidate for decomposition. Split by stable
responsibility boundary, not by execution order or framework convention.
- The happy path must be readable. Isolate error handling, edge cases, and
cleanup from the main flow.
- A function too long to name precisely is too long. Extract.
Architecture & Boundaries
- Source dependencies point INWARD toward higher-level policy. Domain and use
cases never import frameworks, databases, UI, or vendor SDKs.
- Every external dependency โ HTTP clients, filesystems, databases, vendor
SDKs โ must sit behind a trait or interface owned by inner layers. Direct
instantiation of infrastructure code inside application or domain logic is
a structural violation (Dependency Inversion Principle).
- Frameworks, databases, delivery mechanisms, and devices are outer-layer
details. Keep them behind ports, gateways, and adapters.
- Organize by business capability / use case first, NOT by technical layer
(controllers/, services/, repositories/).
- The dependency rule: inner layers OWN the interfaces they need; outer layers
IMPLEMENT them.
- Choose boundaries by volatility and policy importance, not by size or habit.
- A wrapper, layer, or abstraction must HIDE more complexity than it adds.
Pass-through layers are debt.
Data & State
- Prefer types that make invalid states unrepresentable. Use enums for closed
sets, Value Objects for meaningful primitives, and booleans only for binary
meanings.
- Make data ownership explicit: distinguish source of truth from derived,
cached, or ephemeral data.
- Treat shared mutable state, globals, and ambient context as costs that must
earn themselves.
- Keep identity, lifecycle, mutation, and loading behavior visible.
- One authoritative representation per piece of system knowledge. Derive or
generate everything else.
Testing
- Tests are production code: readable, deterministic, aligned with behavior.
- Keep tests focused on externally visible behavior, not internal
implementation details.
- Add a characterization test before changing behavior in untested code.
- When fixing a bug, add a regression test that would have caught it.
- Treat ignored, flaky, or skipped tests as unresolved questions.
- The Boy Scout Rule for tests: leave the test suite cleaner than you found it.
Error & Failure Handling
- Distinguish: programmer errors (assert), contract violations (panic/fail),
expected domain failures (return/result type), retryable failures, and
permanent failures.
- Treat every dependency, timeout, retry, queue, and degraded state as capable
of failing in slow, partial, or prolonged ways.
- Timeouts on ALL outbound calls. No infinite waits. Finite retries with
exponential backoff and jitter. Never retry validation errors or permanent
failures โ distinguish retryable from non-retryable outcomes.
- Validate external input at trust boundaries. Never trust shape, size, or
semantics of things from outside the process.
- Fail fast when continuing hides unrecoverable trouble. Let-it-crash only with
supervision and isolation.
Refactoring & Change
- Refactoring is behavior-preserving structural improvement. Never disguise a
feature or redesign as cleanup.
- Work in small, reversible, buildable steps. Split patches too large for
local reasoning.
- Identify the structural friction blocking a change. Refactor BEFORE the
feature only when it makes the feature safer or simpler.
- Target the current blocking smell, not every smell in sight. Stop when the
next cleanup would be speculative.
- Remove duplication when the SAME edit appears a third time.
- Decompose when a module exceeds ~400 lines or handles 3+ distinct
responsibilities. A module you can't name in a single sentence is
doing too much โ extract the cohesive sub-concepts.
- Prefer the simplest named move: rename, extract, inline, move, split, or
substitute.
Per-Book Compressed Rules
Clean Code (Martin)
Readability, local reasoning, maintainability. Corrects: "working code = clean."
- Functions: one thing, one level of abstraction, top-down narrative
- Names: intention-revealing, pronounceable, one concept per term
- No boolean flags, no output parameters, no hidden side effects
- Comments only for rationale/constraints, never to narrate
- Tests as production code: readable, deterministic, fast
- Boy Scout Rule: leave touched code cleaner
A Philosophy of Software Design (Ousterhout)
Deep modules, information hiding, complexity reduction. Corrects: "familiar patterns = simple."
- Deep modules: small interface, meaningful hidden complexity. Reject thin wrappers.
- Pull complexity downward into the module that owns the detail
- Design interfaces around what callers need to know, not how impl works
- Reduce exception surface via stronger invariants. Define away invalid states.
- Comments document design decisions and hidden complexity
- Names, consistency, and obviousness ARE design information
Clean Architecture (Martin)
Business rules independent of frameworks/databases/UI. Corrects: "details = architecture."
- Dependencies point inward. Domain never imports frameworks, DB, UI, vendors.
- Entities guard enterprise invariants; Use Cases orchestrate one action
- Frameworks, DB, delivery = outer-layer details behind Ports/Adapters
- Inner layers OWn interfaces; outer layers IMPLEMENT
- Use cases are not merged by sharing; duplication from different actors stays
- Core tests run without real DB, network, framework, or hardware
Code Complete (McConnell)
Construction discipline, defect reduction, verifiable code. Corrects: "typing = construction."
- Sketch pseudocode at consistent abstraction before complex routines
- Input validation at every trust boundary. Assertions for programmer assumptions.
- Handle errors at the right abstraction. Never silently continue from corruption.
- Rising complexity IS defect risk. Split tangled routines.
- Build in small, verifiable increments. Integrate often.
- Comments explain intent, constraints, contracts โ not mechanics.
Domain-Driven Design (Evans) + DDD Distilled (Vernon)
Ubiquitous language, bounded contexts, tactical patterns. Corrects: "model = data schema."
- Name the Bounded Context before interpreting any term or module
- One term per concept within the context. Code speaks Ubiquitous Language.
- Aggregates: small, one root, invariant-protected, one per transaction default
- Value Objects: immutable, validated at construction, compare by value
- Repositories return domain objects, not tables or ORM rows
- Domain Events: past-tense business facts, not property-change notifications
- Anti-corruption layer at every context boundary
- Core Domain gets richer modeling; supporting subdomains stay simpler
Implementing DDD (Vernon)
Practical DDD: aggregates, events, services, persistence. Corrects: "renamed CRUD = DDD."
- Reference other Aggregates by identity, not by object graph
- Domain Services for operations that fit no Entity or Value Object
- Application Services coordinate use cases โ they don't own domain decisions
- CQRS when consistency or representation needs justify separate models
- Event Sourcing only when the event sequence IS the right persistence model
- Test invariants, valid/invalid state transitions, and events directly
Patterns of Enterprise Application Architecture (Fowler)
Layering, patterns for enterprise apps. Corrects: "more patterns = better design."
- Choose business logic pattern by force: Transaction Script โ Table Module โ Domain Model
- Service Layer for use-case coordination and transaction boundaries
- Repository speaks domain terms; Data Mapper keeps SQL out of domain objects
- Unit of Work for one logical commit; Identity Map for one identity per scope
- Remote Facade + DTOs at cross-layer boundaries โ never leak domain internals
- Session state chosen deliberately: client, server, or DB with scaling accounted for
Refactoring (Fowler)
Behavior-preserving structural improvement. Corrects: "cleanup = rewrite."
- Preserve observable behavior. Isolate behavior change from structural change.
- Small, reversible, testable steps. Safety net before risky work.
- Preparatory refactoring: reshape blocking structure BEFORE the feature
- Targeted at the current blocking smell, not every smell in sight
- Simplest named move: rename, extract, inline, move, encapsulate, substitute
- Stop when the requested change is easy and the blocking smell is gone
Working Effectively with Legacy Code (Feathers)
Safe change in untested code. Corrects: "rewrite = first move."
- Legacy = code without trustworthy tests. Characterize before redesign.
- Find or create a seam: place to change behavior without editing surrounding code
- Break the ONE blocking dependency before making the change
- Sprout Method, Sprout Class, Wrap Method, Wrap Class for insertion
- Leave the area more testable than found
- Reject: hidden dependency expansion, cosmetic-only refactoring, big rewrites
Designing Data-Intensive Applications (Kleppmann)
Distributed data, consistency, events, replication. Corrects: "everything is local/ordered/exactly-once."
- Source of truth, derived representations, and consistency expectations must be EXPLICIT
- Treat crashes, partial writes, duplicates, and timeouts as normal input
- Write semantics: durable when? visible when? conflicts how? stale reads allowed?
- Events describe facts. Consumers tolerate lag, duplicates, replay, versioned payloads.
- Schemas, APIs, and events evolve across old/new readers/writers
- Partition by workload-relevant locality; make hot-key and cross-partition costs explicit
- Transactions and isolation matched to actual invariants, not blanket defaults
Release It! (Nygard)
Production reliability, stability patterns. Corrects: "happy path = production readiness."
- Timeouts on every outbound call. No infinite waits. Bounded retries with backoff.
- Circuit breakers, bulkheads, fast failure to isolate dependency failures
- Design overload behavior: finite queues, load shedding, capacity for critical traffic
- Startup, health checks, migrations, and operational controls: restartable, observable
- Validate external responses for shape, plausibility, and semantics before trusting
- Observability at every boundary: latency, saturation, errors, queue depth, breaker state
The Pragmatic Programmer (Hunt & Thomas)
Engineering craft, accountability, automation. Corrects: "local edit = done."
- One authoritative source per fact. Everything else derives or traces.
- Preserve orthogonality: independent components, narrow interfaces, separated concerns
- Tracer bullets over piles of isolated pieces. Validate architecture end-to-end early.
- Automate repetitive, error-prone, easy-to-forget work
- Shorten feedback loops: relevant tests, automated checks, cheap early signals
- Broken windows: fix or visibly contain small quality decay before it normalizes
- Debug from reproduced facts: observe, isolate, explain, fix, verify
Refactoring.Guru
Smell catalog and technique catalog. Corrects: "pattern = always the answer."
- Diagnose the smell before choosing the technique
- Prefer the simplest treatment: rename before extract, extract before redesign
- Each smell has a specific root cause and treatment path
- See
references/refactoring-guru.full.md for the full catalog
Compatibility Guide
Books that CONFLICT (do not load as equal guidance):
- DDD โ PoEAA โ different data ownership paradigms
- IDDD โ PoEAA โ same conflict at implementation level
Books that OVERLAP (choose one, they push similar pressure):
- Clean Code ๐ Pragmatic Programmer, Code Complete, APoSD โ code quality
- DDD ๐ DDD Distilled, IDDD โ DDD at different depths; pick the level you need
- Clean Architecture ๐ IDDD, PoEAA โ architecture/layering overlap
- Refactoring ๐ Refactoring.Guru โ code improvement; choose Refactoring for strategy, Guru for catalog
All other pairs are complementary. Default: one primary always-on book, others
loaded on-demand per task.
Local Reference Files
Each book's mini rule set is available as a local reference file under
references/. Load any with:
skill_view(name='programming-principles', file_path='references/{book-dir}.mini.md')
| File | Book |
|---|
references/a-philosophy-of-software-design.mini.md | A Philosophy of Software Design |
references/clean-architecture.mini.md | Clean Architecture |
references/clean-code.mini.md | Clean Code |
references/code-complete.mini.md | Code Complete |
references/designing-data-intensive-apps.mini.md | Designing Data-Intensive Applications |
references/domain-driven-design.mini.md | Domain-Driven Design |
references/domain-driven-design-distilled.mini.md | DDD Distilled |
references/implementing-domain-driven-design.mini.md | Implementing DDD |
references/patterns-of-eaa.mini.md | Patterns of Enterprise App Architecture |
references/refactoring.mini.md | Refactoring |
references/refactoring-guru.mini.md | Refactoring.Guru |
references/release-it.mini.md | Release It! |
references/the-pragmatic-programmer.mini.md | The Pragmatic Programmer |
references/working-effectively-with-legacy-code.mini.md | Working Effectively with Legacy Code |
references/code-assessment-workflow.md | Assessment methodology โ not a book, but the workflow for combining all books against a real repo |
Each book also has a full version (11-42 KB) for deep reference when you need
the complete rule catalog. Load on demand:
skill_view(name='programming-principles', file_path='references/{name}.full.md')
Note: references/refactoring-guru.full.md is an index that routes to two part
files (refactoring-guru.full-smells-and-priorities.md and
refactoring-guru.full-technique-playbook-and-safety.md). Loading the index
shows the "Parts of this reference" table; then load the specific part you need.
| Full File | Book | Size |
|---|
references/a-philosophy-of-software-design.full.md | A Philosophy of Software Design | 13 KB |
references/clean-architecture.full.md | Clean Architecture | 17 KB |
references/clean-code.full.md | Clean Code | 13 KB |
references/code-complete.full.md | Code Complete | 12 KB |
references/designing-data-intensive-apps.full.md | Designing Data-Intensive Applications | 16 KB |
references/domain-driven-design.full.md | Domain-Driven Design | 42 KB |
references/domain-driven-design-distilled.full.md | DDD Distilled | 11 KB |
references/implementing-domain-driven-design.full.md | Implementing DDD | 12 KB |
references/patterns-of-eaa.full.md | Patterns of Enterprise App Architecture | 15 KB |
references/refactoring.full.md | Refactoring | 17 KB |
references/refactoring-guru.full.md | Refactoring.Guru | index + 2 parts |
references/release-it.full.md | Release It! | 13 KB |
references/the-pragmatic-programmer.full.md | The Pragmatic Programmer | 13 KB |
references/working-effectively-with-legacy-code.full.md | Working Effectively with Legacy Code | 13 KB |
Progressive disclosure pattern: load the mini file for daily guidance (triggers,
decision rules, final checklist). Load the full file only for deep sessions,
audits, or when you need the complete rule catalog with code-smell indexes and
technique references.
Known Weaknesses (from repo criticism)
- No empirical measurement of improvement โ these are principle-based, not
benchmarked. Apply judgment about whether rules improve actual outcomes.
- Loading too many rule sets at once causes context saturation. Use at most one
primary always-on set + one task-specific on-demand set.
- Rules are book-derived, not incident-derived. The highest-value agent rules
come from real failures, not theory.
- Risk of pseudo-compliance: agent follows the letter of rules while missing
the actual task. Test outputs against real requirements, not rule conformity.