DDD Architecture Validator
Validate Domain-Driven Design layer separation, dependency rules, and architectural patterns. Non-destructive analysis providing actionable recommendations.
What This Skill Does
Performs comprehensive analysis of DDD architecture:
- •Dependency Rule Validation: Checks layer isolation and dependencies
- •Domain Layer Purity: Ensures zero framework dependencies
- •Pattern Compliance: Validates entities, value objects, repositories
- •Decorator Validation: Checks
@injectable()usage - •Import Analysis: Detects unauthorized dependencies
When to Use This Skill
Use when you need to:
- •Validate architecture before committing code
- •Check new features for DDD compliance
- •Review refactored code
- •Ensure layer separation
Examples:
- •"Validate the User context for DDD compliance"
- •"Check if my Product domain layer has any violations"
- •"Analyze Order context for dependency rule violations"
Dependency Rule
The validator enforces this hierarchy:
Presentation → Application → Domain
↓ ↓
Infrastructure
Rules:
- •Domain has ZERO external dependencies
- •Application depends only on Domain
- •Infrastructure implements Domain interfaces
- •Presentation depends on Application and Domain
Validation Checks
Domain Layer Checks
Zero Dependencies:
- •❌ No Mongoose, Elysia, tsyringe imports
- •❌ No infrastructure imports
- •❌ No application imports
- •✅ Only domain files and Node.js built-ins
Entity Patterns:
- •✅ Private constructor
- •✅ Static
create()method - •✅ Static
reconstitute()method - •✅ Getters for properties
- •❌ No public properties
- •❌ No database annotations
Value Object Patterns:
- •✅ Immutable (readonly properties)
- •✅ Private constructor
- •✅ Static
create()with validation - •✅
equals()method - •❌ No mutable properties
Repository Interfaces:
- •✅ Interface (not class)
- •✅ Returns domain entities
- •✅ Uses domain types
- •❌ No implementation details
- •❌ No database-specific methods
Application Layer Checks
UseCase Patterns:
- •✅
@injectable()decorator present - •✅ Repositories injected with string token
- •✅ Use cases injected by class
- •✅ Single
execute()method - •❌ No HTTP concerns
- •✅ Emits domain events
Import Restrictions:
- •✅ Can import Domain layer
- •✅ Can import tsyringe for DI
- •✅ Can import global utilities
- •❌ Cannot import Infrastructure
- •❌ Cannot import Presentation
Infrastructure Layer Checks
Repository Implementations:
- •✅ Implements domain interface
- •✅
@injectable()decorator - •✅ Uses mapper for conversions
- •❌ Never exposes persistence details
Mapper Patterns:
- •✅ Static
toDomain()method - •✅ Static
toPersistence()method - •❌ No business logic
Presentation Layer Checks
Controller Patterns:
- •✅
@injectable()decorator - •✅ Injects use cases (not repositories)
- •✅ Maps domain errors to HttpException
- •❌ No business logic
- •✅ Returns plain objects
Route Patterns:
- •✅ Versioned with
/v1/ - •✅ Controller methods bound with
.bind() - •✅ Zod schemas applied
- •✅ Swagger metadata present
Report Format
Critical Issues (Must Fix)
Violations that break core DDD principles:
CRITICAL: Domain importing framework dependency File: src/contexts/user/domain/entities/user.entity.ts:3 Issue: Importing 'injectable' from tsyringe in domain layer Fix: Remove @injectable() from entity. Only use in application/infrastructure/presentation. CRITICAL: Public entity constructor File: src/contexts/user/domain/entities/user.entity.ts:10 Issue: Constructor is public, should be private Fix: Change to private constructor with static factory methods
Warnings (Should Fix)
Deviations from best practices:
WARNING: Missing reconstitute method File: src/contexts/user/domain/entities/user.entity.ts Issue: Only create() found, missing reconstitute() Recommendation: Add static reconstitute() for loading from database
Suggestions (Nice to Have)
Improvements:
SUGGESTION: Extract Email into value object File: src/contexts/user/domain/entities/user.entity.ts:15 Current: Using string for email Recommendation: Create Email value object with validation
Common Violations
Domain Layer Issues
Framework Imports:
// ❌ WRONG
import { injectable } from 'tsyringe';
import { Schema } from 'mongoose';
// ✅ CORRECT
import { randomUUID } from 'crypto';
import { Email } from '../value-objects/email.vo';
Public Constructor:
// ❌ WRONG
export class User {
constructor(public id: string, public name: string) {}
}
// ✅ CORRECT
export class User {
private constructor(
private readonly id: string,
private name: string
) {}
static create(data: CreateData): User { ... }
static reconstitute(data: PersistedData): User { ... }
}
Mutable Value Object:
// ❌ WRONG
export class Email {
private value: string; // Not readonly
}
// ✅ CORRECT
export class Email {
private readonly value: string;
}
Application Layer Issues
Wrong Injection Pattern:
// ❌ WRONG - Repository by class
constructor(
@inject(UserRepository)
private repo: IUserRepository
) {}
// ✅ CORRECT - Repository by token
constructor(
@inject('IUserRepository')
private repo: IUserRepository
) {}
HTTP Concerns:
// ❌ WRONG
async execute(input: Input): Promise<Output> {
throw new HttpException(404, 'Not found');
}
// ✅ CORRECT
async execute(input: Input): Promise<Output> {
throw new EntityNotFoundError(id);
}
Presentation Layer Issues
Controller Injecting Repository:
// ❌ WRONG
constructor(
@inject('IUserRepository')
private repo: IUserRepository
) {}
// ✅ CORRECT
constructor(
@inject(CreateUserUseCase)
private createUser: CreateUserUseCase
) {}
Not Binding Controller:
// ❌ WRONG
.post('/', controller.create)
// ✅ CORRECT
.post('/', controller.create.bind(controller))
Output Format
- •Summary: Scope of validation
- •Structure: Directory verification
- •Critical Issues: With file:line references and fixes
- •Warnings: With recommendations
- •Suggestions: With improvements
- •Compliance Score: Percentage of rules passed
Integration
The validator is read-only - it never modifies code. After review:
- •Fix critical issues first
- •Address warnings when possible
- •Consider suggestions for improvements
- •Re-run validator to verify fixes
Related Skills
- •api-validator: Validate API design standards
- •di-helper: Check dependency injection setup
- •ddd-context-generator: Generate compliant code