Modern Architecture
DDD + TDD + Clean Architecture + Event-Driven + API-First for TS/Python/Go.
Decision Tree
New feature or module?
|
+- Complex business rules?
| YES -> DDD Tactical Patterns (references/ddd-tactical.md)
| |
| +- Different stakeholders use different terms for same concept?
| | YES -> Bounded Contexts (references/ddd-strategic.md)
| |
| +- External system integration?
| | YES -> Anti-Corruption Layer (references/ddd-strategic.md)
| |
| +- Read/write patterns differ significantly?
| YES -> CQRS (references/event-driven.md)
|
+- Has API surface?
| YES -> Contract-First: schema before code (references/api-first.md)
|
+- Needs async/real-time communication?
| YES -> Event-Driven (references/event-driven.md)
|
+- Any of the above?
YES -> Clean Architecture layers (references/clean-architecture.md)
NO -> Simple module, skip this skill
1. Domain Discovery
Define ubiquitous language. List domain events in past tense.
Domain: Order Management
Events: OrderPlaced, OrderCancelled, PaymentReceived
Aggregates: Order, Payment, Shipment
2. Contract First (if API exists)
Define API schema before writing code. See references/api-first.md.
3. Outside-In TDD
Acceptance Test (RED) -> Domain Test (RED->GREEN) -> Use Case Test (RED->GREEN) -> Adapter (GREEN) -> Acceptance (GREEN) -> Refactor
Full workflow in references/tdd-ddd-workflow.md.
domain/ -> Entities, VOs, Events, Ports (zero dependencies)
application/ -> Use Cases, Commands, Queries (depends on domain only)
infrastructure/ -> DB adapters, API controllers (depends on all)
Dependency Rule: Inner layers NEVER import outer layers.
Directory Structure
src/modules/{context-name}/
domain/
model/ # Aggregate Root, Entities, Value Objects
events/ # Domain Events (past tense)
ports/ # Repository & Service interfaces
services/ # Domain Services (stateless)
application/
use-cases/ # One class per use case
dto/ # Commands & Queries
infrastructure/
persistence/ # Repository implementations + Mappers
api/ # HTTP Controllers / GraphQL Resolvers
messaging/ # Event publishers / subscribers
| Concept |
Pattern |
Example |
| Entity |
Domain noun |
Order, Customer |
| Value Object |
Immutable concept |
Money, Address, Email |
| Domain Event |
Past tense |
OrderPlaced, PaymentReceived |
| Use Case |
Verb phrase |
PlaceOrder, CancelOrder |
| Repository |
{Aggregate}Repository |
OrderRepository |
| Port |
Interface in domain |
PaymentGateway |
| Adapter |
{Tech}{Port} |
StripePaymentGateway |
| Command |
{Action}{Noun}Command |
PlaceOrderCommand |
| Query |
Get{Noun}Query |
GetOrderQuery |
|
|
|
All domain objects return new instances. Never mutate.
// CORRECT: return new instance
addItem(item: OrderItem): Order {
return new Order(this.id, [...this._items, item], this._status)
}
// WRONG: mutation
addItem(item: OrderItem): void {
this._items.push(item) // VIOLATION
}
| Layer |
Type |
Dependencies |
Target |
| Domain |
Unit |
None (pure) |
less than 1ms |
| Application |
Unit |
Mocked ports |
less than 10ms |
| Infrastructure |
Integration |
Real DB |
less than 500ms |
| E2E |
Acceptance |
Full stack |
less than 3s |
|
|
|
|
| Situation |
Action |
| Domain complexity unclear |
Start with simple module; extract domain layer when rules emerge |
| Bounded Context boundaries uncertain |
Map team/stakeholder language first; split where language diverges |
| Existing codebase has no layers |
Introduce layers incrementally; start with domain extraction |
| Over-engineering risk |
If entity has no business rules, use plain DTO -- skip DDD |
|
|
References
references/ddd-tactical.md -- Entity, VO, Aggregate, Repository, Domain Event, Factory (TS/Python/Go)
references/ddd-strategic.md -- Bounded Context, Context Map, Anti-Corruption Layer
references/clean-architecture.md -- Layers, Ports and Adapters, DI, testing per layer
references/event-driven.md -- Event Bus, CQRS, Event Sourcing, Pub/Sub
references/api-first.md -- OpenAPI, tRPC, GraphQL, versioning, error contracts
references/tdd-ddd-workflow.md -- Outside-In TDD phases, property-based testing
1---2name: modern-architecture3description: Design features using DDD + TDD + Clean Architecture + Event-Driven + API-First patterns for TypeScript, Python, and Go. Use when: designing features with domain complexity (Entities, Value Objects, Aggregates), structuring projects with layer separation, defining Bounded Contexts, applying Outside-In TDD, designing CQRS or Event Sourcing, creating API contracts before implementation, starting a new project architecture. Trigger phrases: DDD, TDD, clean architecture, hexagonal, ports and adapters, CQRS, event sourcing, API-first, domain model, bounded context. Do NOT use for: simple scripts, one-off utilities, UI-only components without domain logic, or CRUD-only endpoints with no business rules.4---56# Modern Architecture78DDD + TDD + Clean Architecture + Event-Driven + API-First for TS/Python/Go.910## Decision Tree1112```13New feature or module?14|15+- Complex business rules?16| YES -> DDD Tactical Patterns (references/ddd-tactical.md)17| |18| +- Different stakeholders use different terms for same concept?19| | YES -> Bounded Contexts (references/ddd-strategic.md)20| |21| +- External system integration?22| | YES -> Anti-Corruption Layer (references/ddd-strategic.md)23| |24| +- Read/write patterns differ significantly?25| YES -> CQRS (references/event-driven.md)26|27+- Has API surface?28| YES -> Contract-First: schema before code (references/api-first.md)29|30+- Needs async/real-time communication?31| YES -> Event-Driven (references/event-driven.md)32|33+- Any of the above?34 YES -> Clean Architecture layers (references/clean-architecture.md)35 NO -> Simple module, skip this skill36```3738<important if="applying Outside-In TDD with DDD or starting a new feature with domain discovery">39## Core Workflow: Outside-In Development4041### 1. Domain Discovery4243Define ubiquitous language. List domain events in past tense.4445```46Domain: Order Management47Events: OrderPlaced, OrderCancelled, PaymentReceived48Aggregates: Order, Payment, Shipment49```5051### 2. Contract First (if API exists)5253Define API schema before writing code. See `references/api-first.md`.5455### 3. Outside-In TDD5657```58Acceptance Test (RED) -> Domain Test (RED->GREEN) -> Use Case Test (RED->GREEN) -> Adapter (GREEN) -> Acceptance (GREEN) -> Refactor59```6061Full workflow in `references/tdd-ddd-workflow.md`.62</important>6364<important if="structuring a project with Clean Architecture layers or creating module directory layout">65### 4. Layer Implementation6667```68domain/ -> Entities, VOs, Events, Ports (zero dependencies)69application/ -> Use Cases, Commands, Queries (depends on domain only)70infrastructure/ -> DB adapters, API controllers (depends on all)71```7273**Dependency Rule**: Inner layers NEVER import outer layers.7475## Directory Structure7677```78src/modules/{context-name}/79 domain/80 model/ # Aggregate Root, Entities, Value Objects81 events/ # Domain Events (past tense)82 ports/ # Repository & Service interfaces83 services/ # Domain Services (stateless)84 application/85 use-cases/ # One class per use case86 dto/ # Commands & Queries87 infrastructure/88 persistence/ # Repository implementations + Mappers89 api/ # HTTP Controllers / GraphQL Resolvers90 messaging/ # Event publishers / subscribers91```92</important>9394<important if="naming DDD entities, value objects, events, repositories, or commands">95## Naming Conventions9697| Concept | Pattern | Example |98|---------|---------|---------|99| Entity | Domain noun | `Order`, `Customer` |100| Value Object | Immutable concept | `Money`, `Address`, `Email` |101| Domain Event | Past tense | `OrderPlaced`, `PaymentReceived` |102| Use Case | Verb phrase | `PlaceOrder`, `CancelOrder` |103| Repository | `{Aggregate}Repository` | `OrderRepository` |104| Port | Interface in domain | `PaymentGateway` |105| Adapter | `{Tech}{Port}` | `StripePaymentGateway` |106| Command | `{Action}{Noun}Command` | `PlaceOrderCommand` |107| Query | `Get{Noun}Query` | `GetOrderQuery` |108</important>109110<important if="implementing domain objects or reviewing domain model mutations">111## Immutability Rule112113All domain objects return new instances. Never mutate.114115```typescript116// CORRECT: return new instance117addItem(item: OrderItem): Order {118 return new Order(this.id, [...this._items, item], this._status)119}120121// WRONG: mutation122addItem(item: OrderItem): void {123 this._items.push(item) // VIOLATION124}125```126</important>127128<important if="planning test strategy for a Clean Architecture project">129## Test Pyramid130131| Layer | Type | Dependencies | Target |132|-------|------|-------------|--------|133| Domain | Unit | None (pure) | less than 1ms |134| Application | Unit | Mocked ports | less than 10ms |135| Infrastructure | Integration | Real DB | less than 500ms |136| E2E | Acceptance | Full stack | less than 3s |137</important>138139<important if="deciding whether to apply DDD or assessing over-engineering risk">140## Error Handling141142| Situation | Action |143|-----------|--------|144| Domain complexity unclear | Start with simple module; extract domain layer when rules emerge |145| Bounded Context boundaries uncertain | Map team/stakeholder language first; split where language diverges |146| Existing codebase has no layers | Introduce layers incrementally; start with domain extraction |147| Over-engineering risk | If entity has no business rules, use plain DTO -- skip DDD |148</important>149150## References151152- `references/ddd-tactical.md` -- Entity, VO, Aggregate, Repository, Domain Event, Factory (TS/Python/Go)153- `references/ddd-strategic.md` -- Bounded Context, Context Map, Anti-Corruption Layer154- `references/clean-architecture.md` -- Layers, Ports and Adapters, DI, testing per layer155- `references/event-driven.md` -- Event Bus, CQRS, Event Sourcing, Pub/Sub156- `references/api-first.md` -- OpenAPI, tRPC, GraphQL, versioning, error contracts157- `references/tdd-ddd-workflow.md` -- Outside-In TDD phases, property-based testing