aggregate-patterns
13
总安装量
13
周安装量
#25368
全站排名
安装命令
npx skills add https://github.com/yonatangross/orchestkit --skill aggregate-patterns
Agent 安装分布
claude-code
9
antigravity
7
gemini-cli
7
github-copilot
6
opencode
6
Skill 文档
Aggregate Design Patterns
Design aggregates with clear boundaries, invariants, and consistency guarantees.
Overview
- Defining transactional consistency boundaries
- Enforcing business invariants across related entities
- Designing aggregate roots and their children
- Handling references between aggregates
- Optimizing aggregate size for performance
Core Concepts
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â ORDER AGGREGATE â
â âââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â Order (Aggregate Root) â â
â â ⢠id: UUID (UUIDv7) â â
â â ⢠customer_id: UUID (reference by ID!) â â
â â ⢠status: OrderStatus â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â â
â ââââââââââââââââââ ââââââââââââââââââ â
â â OrderItem â â OrderItem â â
â â (child) â â (child) â â
â ââââââââââââââââââ ââââââââââââââââââ â
â â
â INVARIANTS enforced by root: â
â ⢠Total = sum of items â
â ⢠Max 100 items per order â
â ⢠Cannot modify after shipped â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Four Rules
- Root controls access – External code only references aggregate root
- Transactional boundary – One aggregate per transaction
- Reference by ID – Never hold references to other aggregates
- Invariants enforced – Root ensures all business rules
Quick Reference
from dataclasses import dataclass, field
from uuid import UUID
from uuid_utils import uuid7
@dataclass
class OrderAggregate:
"""Aggregate root with invariant enforcement."""
id: UUID = field(default_factory=uuid7)
customer_id: UUID # Reference by ID, not Customer object!
_items: list["OrderItem"] = field(default_factory=list)
status: str = "draft"
MAX_ITEMS = 100
def add_item(self, product_id: UUID, quantity: int, price: Money) -> None:
"""Add item with invariant checks."""
self._ensure_modifiable()
if len(self._items) >= self.MAX_ITEMS:
raise DomainError("Max items exceeded")
self._items.append(OrderItem(product_id, quantity, price))
def _ensure_modifiable(self) -> None:
if self.status != "draft":
raise DomainError(f"Cannot modify {self.status} order")
See aggregate-root-template.py for complete implementation.
Key Decisions
| Decision | Recommendation |
|---|---|
| Aggregate size | Small (< 20 children), split if larger |
| Cross-aggregate refs | Always by ID, never by object |
| Consistency | Immediate within, eventual across |
| Events | Collect in root, publish after persist |
See aggregate-sizing.md for sizing guidelines.
Anti-Patterns (FORBIDDEN)
# NEVER reference aggregates by object
customer: Customer # WRONG â customer_id: UUID
# NEVER modify multiple aggregates in one transaction
order.submit()
inventory.reserve(items) # WRONG - use domain events
# NEVER expose mutable collections
def items(self) -> list:
return self._items # WRONG â return tuple(self._items)
# NEVER have unbounded collections
orders: list[Order] # WRONG - grows unbounded
Related Skills
domain-driven-design– DDD building blocks (entities, VOs)distributed-locks– Cross-aggregate coordinationidempotency-patterns– Safe retries
References
- Aggregate Sizing – When to split
- Invariant Enforcement – Business rules
- Eventual Consistency – Cross-aggregate
Capability Details
aggregate-root
Keywords: aggregate root, consistency boundary, transactional Solves: Design aggregate roots, control child access, enforce boundaries
invariants
Keywords: invariant, business rule, validation, specification Solves: Enforce business rules, validate state, specification pattern
aggregate-sizing
Keywords: aggregate size, small aggregate, performance Solves: Right-size aggregates, when to split, performance trade-offs
cross-aggregate
Keywords: reference by ID, eventual consistency, domain events Solves: Reference other aggregates, coordinate changes, eventual consistency