From kent-implementation-patterns
Use when designing a new feature/class/module or reviewing an implementation, diff, or PR — applies Kent Beck's Implementation Patterns (values, principles, and patterns) as a systematic lens for code that communicates intent and is cheap to change. Triggers on "design this", "review this code", "is this good code", code quality, readability, naming, structure.
How this skill is triggered — by the user, by Claude, or both
Slash command
/kent-implementation-patterns:kent-implementation-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Code is communication.** Most of a program's cost comes *after* first deploy, and
Code is communication. Most of a program's cost comes after first deploy, and most of that is spent understanding existing code. So the goal is code that communicates intent to the next reader and is cheap to change.
Don't review or design by ad-hoc instinct. Run a fixed lens so coverage is repeatable and you catch the structural issues that aren't staring back at you as bugs. The lens has three layers — apply them top-down:
Values (why) → Principles (how to decide) → Patterns (concrete moves).
Conflict? Prefer communication > simplicity > speculative flexibility.
| Principle | The question to ask |
|---|---|
| Local Consequences | Does a change here stay local, or ripple there? |
| Minimize Repetition | Is this idea expressed in more than one place? |
| Logic and Data Together | Does this logic live next to the data it uses? |
| Symmetry | Is the same idea expressed the same way everywhere? |
| Declarative Expression | Could this control flow be stated as a fact/table? |
| Rate of Change | Are things that change together grouped, and things that change on different clocks separated? |
patterns.md holds the full 77-pattern catalog, grouped by the principle each serves.
Work top-down through the lens — decide placement and names before writing bodies.
Then state, briefly, which patterns you applied and why — naming them makes the design reviewable.
Read the code as a reader first (does it tell a story?), then run the six principle-checks above as a pass. For every finding:
| Smell in the code | Reach for |
|---|---|
Nested if pyramid, let result then assign in branches | Guard Clause (early returns) |
| A method mixing high-level steps with low-level twiddling | Composed Method (one level of abstraction) |
Name describes how (linearSearch) | Intention-Revealing Name (name the what) |
| Same calc/loop copy-pasted across methods | Minimize Repetition → extract onto the owning object |
Primitive trio passed together (amount, currency, …) | Parameter Object → often a missing Value Object |
switch/if on a type tag, repeated on the same axis | Choosing Message / Delegation |
Magic number/string (0.2, 0x0004) | Constant with an intent-revealing name |
| Getter/setter pulling data out to compute elsewhere | move the computation in (Logic and Data Together) |
process() validates but refund() doesn't; mismatched return shapes | Symmetry |
Long if/elseif mapping input→output with no real sequence | Declarative Expression (table/map) |
Mixed-abstraction, nested, duplicated:
process(o: any, db: any) {
if (o != null) {
if (o.items != null && o.items.length > 0) {
if (o.customer != null && o.customer.active) {
let t = 0;
for (let i = 0; i < o.items.length; i++) t += o.items[i].price * o.items[i].qty;
if (o.customer.tier == "gold") t -= t * 0.1; // duplicated in refund()
else if (o.customer.tier == "silver") t -= t * 0.05;
o.total = t; o.tax = t * 0.2; o.grandTotal = o.total + o.tax;
db.flags |= 0x0004; // abstraction-level jar
db.save(o); return { ok: true, total: o.grandTotal };
} else return { ok: false, error: "inactive customer" };
} else return { ok: false, error: "no items" };
} else return { ok: false, error: "null order" };
}
Through the lens:
refund(). It belongs on an immutable Money/Order value, not
copy-pasted in a Processor. (This is the finding a generic review misses — it
extracts a private helper instead of moving logic to the data.)let result accumulator disappears.process should sit at one abstraction level;
db.flags |= 0x0004 (a Constant named FLAG_ORDER_PROCESSED) doesn't belong
beside business steps.refund() skips the validation process() does and returns a bare
number while process() returns a result object. Make their shapes parallel.{ gold: 0.1, silver: 0.05 }.// Money: immutable value object — logic lives with the data
class Money { /* +, *, withTax(), equals() … returns new Money */ }
process(order: Order, repo: OrderRepo): Result {
if (order == null) return fail("null order"); // Guard Clauses
if (!order.items.length) return fail("no items");
if (!order.customer.active) return fail("inactive customer");
const total = order.discountedSubtotal().withTax(TAX_RATE); // logic on the data
repo.save(order.markProcessed(total)); // named, not 0x0004
return ok(total);
}
== vs ===.When clients can't change with you (public API, library, plugin host), the
assumption "change is cheap" breaks — there, add complexity to protect clients:
hide fields, reveal only stable surface, prefer a Library-Class API, and stage
breaking changes (deprecate, parallel architectures, migration tools). See the
Evolving Frameworks section in patterns.md.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub pditommaso/kent-implementation-patterns --plugin kent-implementation-patterns