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
