dry-principle/SKILL.md
Enforces the DRY (Don't Repeat Yourself) principle correctly, distinguishing true knowledge duplication from incidental code similarity. Use when evaluating whether to extract shared code, deciding if duplication is acceptable, applying the Rule of Three, avoiding premature abstraction, or reviewing code for the wrong abstraction anti-pattern.
npx skillsauth add kayaman/skills dry-principleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference: The Pragmatic Programmer (Hunt & Thomas), Tidy First? (Beck), Software Engineering at Google (Winters et al.)
The formal definition from Hunt & Thomas (1999): "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system."
DRY is about knowledge duplication, not code duplication. Two identical-looking code blocks that represent different business concepts are NOT a DRY violation. Two different-looking code blocks that encode the same business rule ARE a violation.
"If this business rule changes, would ALL of these locations need to change in exactly the same way?"
| Type | Description | Example | Fix |
|------|-------------|---------|-----|
| Code | Copy-pasted blocks | Same validation logic in two controllers | Extract shared function |
| Knowledge / Logic | Same business rule in multiple places | Tax calculation in order service AND invoice service | Single authoritative implementation |
| Documentation | Comments restating what code does | x = x + 1 // increment x | Delete the comment; the code is clear |
| Data | Derived values stored independently | Storing total separately from items | Derive on read, or use a single source of truth |
| Representation | Same concept across system boundaries | User defined separately in frontend and backend | Shared schema (Protobuf, OpenAPI, JSON Schema) |
"Duplication is far cheaper than the wrong abstraction."
The pattern that leads to the wrong abstraction:
The remedy: The fastest way forward is back. Re-introduce duplication, then re-abstract based on the actual patterns that emerge.
Every extraction creates a dependency. Extracting a shared utility between two services couples them — changes to the utility require coordinating both services.
Don Roberts, popularized by Fowler: "The first time you do something, just do it. The second time, wince at the duplication but do it anyway. The third time, refactor."
With only two examples, you cannot reliably identify the true pattern. By three, the commonalities become visible and the abstraction has a solid foundation.
"Avoid Hasty Abstractions" — coined by Kent C. Dodds (2020): "I'm fine with code duplication until you feel pretty confident that you know the use cases. At that point, the commonalities will 'scream at you for abstraction.'"
AHA is the synthesis of DRY and WET ("Write Everything Twice"):
| Approach | Rule | Risk | |----------|------|------| | DRY | Never repeat yourself | Premature abstraction; wrong abstraction | | WET | Write everything twice before extracting | Arbitrary threshold; ignores knowledge duplication | | AHA | Abstract when the pattern screams for it | Requires judgment; no fixed threshold |
When you encounter similar code, follow this sequence:
Is it the same knowledge? Apply the acid test. If different business rules happen to look similar, stop — leave them separate.
How many occurrences? If fewer than three, tolerate the duplication. Note it with a comment if helpful.
What's the coupling cost? If extraction creates a dependency across service, team, or deployment boundaries, prefer duplication.
Is the abstraction clear? If you can name the extracted concept and it represents a single, stable piece of knowledge, extract it. If the name is vague (CommonUtils.processData) or requires parameters to handle divergent cases, the abstraction is wrong.
Can you undo it? If the extraction turns out to be wrong, you must be willing to re-inline. Sunk cost is not a reason to keep a bad abstraction.
| Pitfall | Signal | Remedy |
|---------|--------|--------|
| Premature extraction | Shared function has boolean flags or parameters that select between behaviors | Re-inline; the two uses represent different knowledge |
| Utility dumping ground | Utils class grows to hundreds of methods | Break by domain concept; many "utilities" belong on domain objects |
| Cross-boundary coupling | Shared library forces coordinated deployments | Duplicate within each boundary; sync schema separately |
| Sunk cost preservation | "We already built this abstraction, let's keep extending it" | Re-introduce duplication; re-abstract from scratch |
| DRY on tests | Extracting test setup until tests are unreadable | Tests SHOULD be readable in isolation; duplication in tests is often acceptable |
| Documentation DRY | Code and comments say the same thing | Delete the comment; trust the code |
When evaluating duplication, verify:
| Book | Author(s) | Publisher | Year | |------|-----------|-----------|------| | The Pragmatic Programmer (2nd ed.) | Hunt & Thomas | Addison-Wesley | 2020 | | Tidy First? | Kent Beck | O'Reilly | 2023 | | A Philosophy of Software Design (2nd ed.) | John Ousterhout | Stanford | 2021 | | Software Engineering at Google | Winters, Manshreck, Wright | O'Reilly | 2020 | | Refactoring (2nd ed.) | Martin Fowler | Addison-Wesley | 2018 | | Five Lines of Code | Christian Clausen | Manning | 2021 |
tools
Guidance for designing charts, graphs, plots, dashboards, and data visualizations that communicate clearly and persuade. Use when creating or reviewing a visualization, choosing a chart type, picking a color palette, decluttering a busy graphic, fixing misleading axes or proportions, building a dashboard, annotating a figure, or turning data into a presentation, report, or data-driven story. Grounded in the standard data-visualization literature (Knaflic, Tufte, Cleveland & McGill, Cairo, Wilke, Munzner, Few, Berinato). Covers chart selection, graphical perception and encoding, color and accessibility, decluttering, graphical integrity, dashboards, and narrative. Does NOT cover building data pipelines or ETL, statistical modeling or analysis methods, BI tool/vendor selection, or general UI/UX layout (see ux-design-principles). Tool-agnostic, with optional Python recipes.
development
Architect and implement production-grade microservices systems in TypeScript (NestJS) and Python (FastAPI), including resilience, observability, testing, deployment, and migration guidance.
development
--- name: databricks-genie-spaces-best-practices description: Design, configure, curate, govern, monitor, and integrate Databricks AI/BI Genie Spaces — the natural-language-to-SQL surface over Unity Catalog. Covers space scoping, general instructions, parameterized example SQL, SQL functions, trusted assets, JOIN configuration, knowledge store, certified queries, benchmarks, monitoring tab, feedback loops, the Genie Conversation API, governance via Unity Catalog (row filters, column masks, embed
tools
Implement OTP and passwordless authentication on AWS for TypeScript projects using Cognito CUSTOM_AUTH triggers (default) or a custom DynamoDB-backed flow, with SES (email) and SNS (SMS) delivery. Use when the user mentions OTP, one-time password, passwordless login, magic link, Cognito custom auth, DefineAuthChallenge, CreateAuthChallenge, VerifyAuthChallengeResponse, SES verification email, SNS SMS code, or MFA over email/SMS. Covers architecture decision (Cognito vs custom), Lambda trigger handlers, SES/SNS notifiers, DynamoDB schema with TTL, rate limiting, constant-time comparison, threat model (enumeration, replay, brute force), and aws-sdk-client-mock testing.