M09 Domain

by actionbook5c40d3ad7851No license1.5K starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 6 weeks ago

CRITICAL: Use for domain modeling. Triggers: domain model, DDD, domain-driven design, entity, value object, aggregate, repository pattern, business rules, validation, invariant, 领域模型, 领域驱动设计, 业务规则

Instructions onlySoftware Development
AI-generated overview

Guides domain modeling in Rust using DDD concepts such as entities, value objects, and aggregates.

What it does
This skill provides design guidance for translating domain concepts into Rust patterns, mapping entities, value objects, aggregate roots, repositories, domain events, and services to concrete Rust constructs. It offers thinking prompts about identity, invariants, and ownership, plus pattern templates for value objects, entities, and aggregates. It also lists common modeling mistakes and points to related skills for type-driven design, ownership, and domain error handling.
When to use it
Use it when modeling a business domain in Rust and deciding whether a concept is an entity or value object, where aggregate boundaries lie, or how to enforce invariants. It is also useful when reviewing a domain model for primitive obsession, leaked internals, or unclear ownership.
Requirements
No scripts or special tooling; it is an instructions-only reference. The examples assume Rust and familiarity with DDD terminology.

Domain Modeling

Layer 2: Design Choices

Core Question

What is this concept's role in the domain?

Before modeling in code, understand:

  • Is it an Entity (identity matters) or Value Object (interchangeable)?
  • What invariants must be maintained?
  • Where are the aggregate boundaries?

Domain Concept → Rust Pattern

Domain ConceptRust PatternOwnership Implication
Entitystruct + IdOwned, unique identity
Value Objectstruct + Clone/CopyShareable, immutable
Aggregate Rootstruct owns childrenClear ownership tree
RepositorytraitAbstracts persistence
Domain EventenumCaptures state changes
Serviceimpl block / free fnStateless operations

Thinking Prompt

Before creating a domain type:

  1. What's the concept's identity?

    • Needs unique identity → Entity (Id field)
    • Interchangeable by value → Value Object (Clone/Copy)
  2. What invariants must hold?

    • Always valid → private fields + validated constructor
    • Transition rules → type state pattern
  3. Who owns this data?

    • Single owner (parent) → owned field
    • Shared reference → Arc/Rc
    • Weak reference → Weak

Trace Up ↑

To domain constraints (Layer 3):

"How should I model a Transaction?"    ↑ Ask: What domain rules govern transactions?    ↑ Check: domain-fintech (audit, precision requirements)    ↑ Check: Business stakeholders (what invariants?)
Design QuestionTrace ToAsk
Entity vs Value Objectdomain-*What makes two instances "the same"?
Aggregate boundariesdomain-*What must be consistent together?
Validation rulesdomain-*What business rules apply?

Trace Down ↓

To implementation (Layer 1):

"Model as Entity"    ↓ m01-ownership: Owned, unique    ↓ m05-type-driven: Newtype for Id
"Model as Value Object"    ↓ m01-ownership: Clone/Copy OK    ↓ m05-type-driven: Validate at construction
"Model as Aggregate"    ↓ m01-ownership: Parent owns children    ↓ m02-resource: Consider Rc for shared within aggregate

Quick Reference

DDD ConceptRust PatternExample
Value ObjectNewtypestruct Email(String);
EntityStruct + IDstruct User { id: UserId, ... }
AggregateModule boundarymod order { ... }
RepositoryTraittrait UserRepo { fn find(...) }
Domain EventEnumenum OrderEvent { Created, ... }

Pattern Templates

Value Object

rust
struct Email(String);
impl Email {    pub fn new(s: &str) -> Result<Self, ValidationError> {        validate_email(s)?;        Ok(Self(s.to_string()))    }}

Entity

rust
struct UserId(Uuid);
struct User {    id: UserId,    email: Email,    // ... other fields}
impl PartialEq for User {    fn eq(&self, other: &Self) -> bool {        self.id == other.id  // Identity equality    }}

Aggregate

rust
mod order {    pub struct Order {        id: OrderId,        items: Vec<OrderItem>,  // Owned children        // ...    }
    impl Order {        pub fn add_item(&mut self, item: OrderItem) {            // Enforce aggregate invariants        }    }}

Common Mistakes

MistakeWhy WrongBetter
Primitive obsessionNo type safetyNewtype wrappers
Public fields with invariantsInvariants violatedPrivate + accessor
Leaked aggregate internalsBroken encapsulationMethods on root
String for semantic typesNo validationValidated newtype

Related Skills

WhenSee
Type-driven implementationm05-type-driven
Ownership for aggregatesm01-ownership
Domain error handlingm13-domain-error
Specific domain rulesdomain-*

Source and attribution

Source:actionbook/rust-skillsinskills/m09-domainat commit5c40d3a

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal