chore: move agents and skills to old2 folder
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
272
old2/skills/ddd/SKILL.md
Normal file
272
old2/skills/ddd/SKILL.md
Normal file
@@ -0,0 +1,272 @@
|
||||
---
|
||||
name: ddd
|
||||
description: >
|
||||
Domain-Driven Design concepts: bounded contexts, aggregates, commands, events,
|
||||
and tactical patterns. Use when analyzing domain models, identifying bounded
|
||||
contexts, or mapping features to DDD patterns.
|
||||
user-invocable: false
|
||||
---
|
||||
|
||||
# Domain-Driven Design (DDD)
|
||||
|
||||
Strategic and tactical patterns for modeling complex domains.
|
||||
|
||||
## Strategic DDD: Bounded Contexts
|
||||
|
||||
### What is a Bounded Context?
|
||||
|
||||
A **bounded context** is a boundary within which a domain model is consistent. Same terms can mean different things in different contexts.
|
||||
|
||||
**Example:** "Order" means different things in different contexts:
|
||||
- **Sales Context**: Order = customer purchase with payment and shipping
|
||||
- **Fulfillment Context**: Order = pick list for warehouse
|
||||
- **Accounting Context**: Order = revenue transaction
|
||||
|
||||
### Identifying Bounded Contexts
|
||||
|
||||
Look for:
|
||||
1. **Different language**: Same term means different things
|
||||
2. **Different models**: Same concept has different attributes/behavior
|
||||
3. **Different teams**: Natural organizational boundaries
|
||||
4. **Different lifecycles**: Entities created/destroyed at different times
|
||||
5. **Different rate of change**: Some areas evolve faster than others
|
||||
|
||||
**From vision/manifesto:**
|
||||
- Identify personas → each persona likely interacts with different contexts
|
||||
- Identify core domain concepts → group related concepts into contexts
|
||||
- Identify capabilities → capabilities often align with contexts
|
||||
|
||||
**From existing code:**
|
||||
- Look for packages/modules that cluster related concepts
|
||||
- Identify seams where code is loosely coupled
|
||||
- Look for translation layers between subsystems
|
||||
- Identify areas where same terms mean different things
|
||||
|
||||
### Context Boundaries
|
||||
|
||||
**Good boundaries:**
|
||||
- Clear interfaces between contexts
|
||||
- Each context owns its data
|
||||
- Contexts communicate via events or APIs
|
||||
- Minimal coupling between contexts
|
||||
|
||||
**Bad boundaries:**
|
||||
- Shared database tables across contexts
|
||||
- Direct object references across contexts
|
||||
- Mixed concerns within a context
|
||||
|
||||
### Common Context Patterns
|
||||
|
||||
| Pattern | Description | Example |
|
||||
|---------|-------------|---------|
|
||||
| **Core Domain** | Your unique competitive advantage | Custom business logic |
|
||||
| **Supporting Subdomain** | Necessary but not differentiating | User management |
|
||||
| **Generic Subdomain** | Common problems, use off-the-shelf | Email sending, file storage |
|
||||
|
||||
## Tactical DDD: Building Blocks
|
||||
|
||||
### Aggregates
|
||||
|
||||
An **aggregate** is a cluster of entities and value objects treated as a unit for data changes.
|
||||
|
||||
**Rules:**
|
||||
- One entity is the **aggregate root** (only entity referenced from outside)
|
||||
- All changes go through the root
|
||||
- Enforce business invariants within the aggregate
|
||||
- Keep aggregates small (2-3 entities max when possible)
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Order (root)
|
||||
├── OrderLine
|
||||
├── ShippingAddress
|
||||
└── Payment
|
||||
```
|
||||
|
||||
External code only references `Order`, never `OrderLine` directly.
|
||||
|
||||
**Identifying aggregates:**
|
||||
- What entities always change together?
|
||||
- What invariants must be enforced?
|
||||
- What is the transactional boundary?
|
||||
|
||||
### Commands
|
||||
|
||||
**Commands** represent intent to change state. Named with imperative verbs.
|
||||
|
||||
**Format:** `[Verb][AggregateRoot]` or `[AggregateRoot][Verb]`
|
||||
|
||||
**Examples:**
|
||||
- `PlaceOrder` or `OrderPlace`
|
||||
- `CancelSubscription` or `SubscriptionCancel`
|
||||
- `ApproveInvoice` or `InvoiceApprove`
|
||||
|
||||
**Commands:**
|
||||
- Are handled by the aggregate root
|
||||
- Either succeed completely or fail
|
||||
- Can be rejected (return error)
|
||||
- Represent user intent or system action
|
||||
|
||||
### Events
|
||||
|
||||
**Events** represent facts that happened in the past. Named in past tense.
|
||||
|
||||
**Format:** `[AggregateRoot][PastVerb]` or `[Something]Happened`
|
||||
|
||||
**Examples:**
|
||||
- `OrderPlaced`
|
||||
- `SubscriptionCancelled`
|
||||
- `InvoiceApproved`
|
||||
- `PaymentFailed`
|
||||
|
||||
**Events:**
|
||||
- Are immutable (already happened)
|
||||
- Can be published to other contexts
|
||||
- Enable eventual consistency
|
||||
- Create audit trail
|
||||
|
||||
### Value Objects
|
||||
|
||||
**Value Objects** are immutable objects defined by their attributes, not identity.
|
||||
|
||||
**Examples:**
|
||||
- `Money` (amount + currency)
|
||||
- `EmailAddress`
|
||||
- `DateRange`
|
||||
- `Address`
|
||||
|
||||
**Characteristics:**
|
||||
- No identity (two with same values are equal)
|
||||
- Immutable (cannot change, create new instance)
|
||||
- Can contain validation logic
|
||||
- Can contain behavior
|
||||
|
||||
**When to use:**
|
||||
- Concept has no lifecycle (no create/update/delete)
|
||||
- Equality is based on attributes, not identity
|
||||
- Can be shared/reused
|
||||
|
||||
### Entities
|
||||
|
||||
**Entities** have identity that persists over time, even if attributes change.
|
||||
|
||||
**Examples:**
|
||||
- `User` (ID remains same even if name/email changes)
|
||||
- `Order` (ID remains same through lifecycle)
|
||||
- `Product` (ID remains same even if price changes)
|
||||
|
||||
**Characteristics:**
|
||||
- Has unique identifier
|
||||
- Can change over time
|
||||
- Identity matters more than attributes
|
||||
|
||||
## Mapping Features to DDD Patterns
|
||||
|
||||
### Process
|
||||
|
||||
For each feature from vision:
|
||||
|
||||
1. **Identify the bounded context**: Which context does this belong to?
|
||||
|
||||
2. **Identify the aggregate(s)**: What entities/value objects are involved?
|
||||
|
||||
3. **Identify commands**: What actions can users/systems take?
|
||||
|
||||
4. **Identify events**: What facts should be recorded when commands succeed?
|
||||
|
||||
5. **Identify value objects**: What concepts are attribute-defined, not identity-defined?
|
||||
|
||||
### Example: "User can place an order"
|
||||
|
||||
**Bounded Context:** Sales
|
||||
|
||||
**Aggregate:** `Order` (root)
|
||||
- `OrderLine` (entity)
|
||||
- `ShippingAddress` (value object)
|
||||
- `Money` (value object)
|
||||
|
||||
**Commands:**
|
||||
- `PlaceOrder`
|
||||
- `AddOrderLine`
|
||||
- `RemoveOrderLine`
|
||||
- `UpdateShippingAddress`
|
||||
|
||||
**Events:**
|
||||
- `OrderPlaced`
|
||||
- `OrderLineAdded`
|
||||
- `OrderLineRemoved`
|
||||
- `ShippingAddressUpdated`
|
||||
|
||||
**Value Objects:**
|
||||
- `Money` (amount, currency)
|
||||
- `Address` (street, city, zip, country)
|
||||
- `Quantity`
|
||||
|
||||
## Refactoring to DDD
|
||||
|
||||
When existing code doesn't follow DDD patterns:
|
||||
|
||||
### Identify Misalignments
|
||||
|
||||
**Anemic domain model:**
|
||||
- Entities with only getters/setters
|
||||
- Business logic in services, not entities
|
||||
- **Fix:** Move behavior into aggregates
|
||||
|
||||
**God objects:**
|
||||
- One entity doing too much
|
||||
- **Fix:** Split into multiple aggregates or value objects
|
||||
|
||||
**Context leakage:**
|
||||
- Same model shared across contexts
|
||||
- **Fix:** Create context-specific models with translation layers
|
||||
|
||||
**Missing boundaries:**
|
||||
- Everything in one module/package
|
||||
- **Fix:** Identify bounded contexts, separate into modules
|
||||
|
||||
### Refactoring Strategies
|
||||
|
||||
**Extract bounded context:**
|
||||
```markdown
|
||||
As a developer, I want to extract [Context] into a separate module,
|
||||
so that it has clear boundaries and can evolve independently
|
||||
```
|
||||
|
||||
**Extract aggregate:**
|
||||
```markdown
|
||||
As a developer, I want to extract [Aggregate] from [GodObject],
|
||||
so that it enforces its own invariants
|
||||
```
|
||||
|
||||
**Introduce value object:**
|
||||
```markdown
|
||||
As a developer, I want to replace [primitive] with [ValueObject],
|
||||
so that validation is centralized and the domain model is clearer
|
||||
```
|
||||
|
||||
**Introduce event:**
|
||||
```markdown
|
||||
As a developer, I want to publish [Event] when [Command] succeeds,
|
||||
so that other contexts can react to state changes
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
**Avoid:**
|
||||
- Aggregates spanning multiple bounded contexts
|
||||
- Shared mutable state across contexts
|
||||
- Direct database access across contexts
|
||||
- Aggregates with dozens of entities (too large)
|
||||
- Value objects with identity
|
||||
- Commands without clear aggregate ownership
|
||||
- Events that imply future actions (use commands)
|
||||
|
||||
## Tips
|
||||
|
||||
- Start with strategic DDD (bounded contexts) before tactical patterns
|
||||
- Bounded contexts align with team/organizational boundaries
|
||||
- Keep aggregates small (single entity when possible)
|
||||
- Use events for cross-context communication
|
||||
- Value objects make impossible states impossible
|
||||
- Refactor incrementally - don't rewrite everything at once
|
||||
Reference in New Issue
Block a user