m09-domain

Domain-driven design patterns for modeling entities, value objects, and aggregates in Rust. Distinguishes between Entities (unique identity required), Value Objects (interchangeable by value), and Aggregates (owned hierarchies), with clear Rust patterns for each Emphasizes invariant preservation through private fields, validated constructors, and type-state patterns Provides templates for common DDD structures: newtypes for value objects, structs with ID fields for entities, and module boundaries for aggregates Traces design decisions upward to domain constraints and downward to ownership and type-driven implementation patterns

INSTALLATION
npx skills add https://github.com/zhanghandong/rust-skills --skill m09-domain
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

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 Concept

Rust Pattern

Ownership Implication

Entity

struct + Id

Owned, unique identity

Value Object

struct + Clone/Copy

Shareable, immutable

Aggregate Root

struct owns children

Clear ownership tree

Repository

trait

Abstracts persistence

Domain Event

enum

Captures state changes

Service

impl block / free fn

Stateless operations

Thinking Prompt

Before creating a domain type:

-

What's the concept's identity?

  • Needs unique identity → Entity (Id field)
  • Interchangeable by value → Value Object (Clone/Copy)

-

What invariants must hold?

  • Always valid → private fields + validated constructor
  • Transition rules → type state pattern

-

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 Question

Trace To

Ask

Entity vs Value Object

domain-*

What makes two instances "the same"?

Aggregate boundaries

domain-*

What must be consistent together?

Validation rules

domain-*

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 Concept

Rust Pattern

Example

Value Object

Newtype

struct Email(String);

Entity

Struct + ID

struct User { id: UserId, ... }

Aggregate

Module boundary

mod order { ... }

Repository

Trait

trait UserRepo { fn find(...) }

Domain Event

Enum

enum OrderEvent { Created, ... }

Pattern Templates

Value Object

struct Email(String);

impl Email {

    pub fn new(s: &#x26;str) -> Result<Self, ValidationError> {

        validate_email(s)?;

        Ok(Self(s.to_string()))

    }

}

Entity

struct UserId(Uuid);

struct User {

    id: UserId,

    email: Email,

    // ... other fields

}

impl PartialEq for User {

    fn eq(&#x26;self, other: &#x26;Self) -> bool {

        self.id == other.id  // Identity equality

    }

}

Aggregate

mod order {

    pub struct Order {

        id: OrderId,

        items: Vec<OrderItem>,  // Owned children

        // ...

    }

    impl Order {

        pub fn add_item(&#x26;mut self, item: OrderItem) {

            // Enforce aggregate invariants

        }

    }

}

Common Mistakes

Mistake

Why Wrong

Better

Primitive obsession

No type safety

Newtype wrappers

Public fields with invariants

Invariants violated

Private + accessor

Leaked aggregate internals

Broken encapsulation

Methods on root

String for semantic types

No validation

Validated newtype

Related Skills

When

See

Type-driven implementation

m05-type-driven

Ownership for aggregates

m01-ownership

Domain error handling

m13-domain-error

Specific domain rules

domain-*

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card