Rules
The DDD plugin enforces code quality through 14 rules that activate automatically when writing or reviewing code. Each rule targets specific files via glob patterns and has an assigned impact level.
Rules replace the previous monolithic software-architecture skill with focused, composable guidelines that Claude applies contextually based on the files being edited.
Rules Overview
Architecture Rules
Clean Architecture & DDD
Keep business logic in pure domain and use case layers, free of framework or infrastructure dependencies.
Key principles:
Domain Layer - Business entities independent of frameworks
Use Case Layer - Application-specific business rules
Interface Layer - Controllers, presenters, gateways
Infrastructure Layer - Frameworks, databases, external services
Domain must never import from infrastructure
Use abstract repository interfaces for dependency inversion
Separation of Concerns
Do NOT mix business logic with UI components or place database queries directly in controllers. Maintain clear architectural boundaries.
Layer responsibilities:
Controllers
HTTP concerns, request/response
Business rules, database queries
Services
Business logic, orchestration
HTTP details, data persistence
Repositories
Data access, query building
Business decisions, HTTP concerns
Functional Core, Imperative Shell
Keep business logic in pure functions; push all side effects to an outer imperative shell that orchestrates the core.
Pure core - Deterministic, no side effects, testable without mocks
Imperative shell - Handles I/O (database, HTTP, logging, file I/O)
Enables easy composition, parallelization, and testing
Function Design Rules
Command-Query Separation
Functions must either return a value (query) or cause a side effect (command), never both. Mutations hidden by assignments are anti-patterns.
Principle of Least Astonishment
Functions must do exactly what their name and signature suggest. No hidden side effects or unexpected behavior:
getUsermust not mutate statePure queries don't throw
All side effects explicit at call site
Clearly named wrappers advertise combined behavior
Call-Site Honesty
Logging calls must be visible and explicit at the call site, not buried inside utility functions. Separate policy (when/whether to log) from mechanism (how to format).
Explicitness Rules
Explicit Control Flow
Error conditions and control flow decisions must be visible at the call site, never hidden inside helper functions. Pure functions (mechanisms) return values; the caller decides policy (throw, log, branch).
Explicit Data Flow
If a function produces a result, return it explicitly. Never rely on mutation of input parameters to communicate output. Use const for assignments and prefer pure expressions over procedures.
Explicit Side Effects
Make side effects visible where they are triggered. Orchestration should be a transparent table of contents — each side effect (persistence, notifications, external calls) as a distinct line, readable without drilling into implementations.
Code Quality Rules
Error Handling
Never silently swallow exceptions. Use typed error handling and log all errors with context before rethrowing:
Typed catch blocks distinguishing domain vs. system errors
Log with sufficient context (operation name, IDs)
Extract complex error handling into reusable handlers
Distinguish between expected and unexpected failures
Domain-Specific Naming
Avoid generic module names. Use domain-specific names that reflect bounded contexts:
utils.js
OrderCalculator.js
Domain-specific purpose
helpers/misc.js
UserAuthenticator.js
Clear responsibility
common/shared.js
InvoiceGenerator.js
Single bounded context
Library-First Approach
Always search for existing libraries or services before writing custom code. Custom code is justified only for:
Domain-specific business logic
Performance-critical paths with special requirements
Security-sensitive code requiring full control
Cases where existing solutions don't meet requirements after thorough evaluation
Early Return Pattern
Use early returns for error conditions and edge cases to reduce nesting and keep the happy path visible. Guard clauses at function start, maximum 3 levels of nesting.
Function & File Size Limits
Decompose functions longer than 80 lines (target: 50 lines each) and keep files under 200 lines. Each function should serve a single purpose. Extract cohesive blocks into named functions when limits are exceeded.
Last updated