← Write specs by level guides

How to write a model spec

How-To Write specs by level Intermediate 1051004HOWTO-1051004

HOWTO-1051004Write specs by levelIntermediate

This guide shows you how to write a SpecDD model spec for a spec-driven development workflow.

A model spec describes domain state, entities, value objects, invariants, and local behavior around valid state. It should protect the domain contract without absorbing service, adapter, or UI responsibilities.

Short answer

Use a model spec for one domain entity, value object, or state model. Define the model’s purpose, owned files, accepted state, invariants in Must, non-responsibilities in Must not, exposed methods or values when useful, and examples or scenarios for important state transitions.

When to use this guide

Use this guide when:

Steps

1. Identify the domain subject

Examples:

itinerary-item.sdd
itinerary-item.model.sdd
TripDateRange.sdd

Suffixes are optional. Follow the project naming convention.

2. Define what the model owns

Owns:
  ./itinerary-item.ts
  ./itinerary-item.test.ts

If generated types or fixtures are writable, use Can modify deliberately.

3. Write invariants in Must

Must:
  A nonempty place name is stored.
  The trip day is tracked for each item.
  Display order remains stable within the day.

Model Must rules should describe valid state and model behavior.

4. Use contract sections for state shape

Accepts:
  place name
  trip day

Returns:
  itinerary item with stable display order

Use Raises when invalid state has named errors.

5. Block responsibilities that belong elsewhere

Must not:
  Persist itself to storage.
  Render UI.
  Purchase bookings or tickets.

This keeps the model focused.

6. Add examples for edge cases

Example: valid item
  place name: Louvre Museum
  trip day: 2026-06-12
  result: item is valid

Use Scenario when a state transition needs a behavior flow.

Complete example

Spec: Itinerary Item

Purpose:
  Represent one planned place or activity in an itinerary.

Owns:
  ./itinerary-item.ts
  ./itinerary-item.test.ts

Must:
  A nonempty place name is stored.
  The trip day is tracked for the item.
  Display order remains stable within the day.

Must not:
  Persist itself to storage.
  Render UI.
  Purchase bookings or tickets.

Accepts:
  place name
  trip day

Returns:
  itinerary item with stable display order

Raises:
  ItineraryPlaceRequired

Example: valid item
  place name: Louvre Museum
  trip day: 2026-06-12
  result: item is valid

Common mistakes

How to verify the result

The model spec is useful when:

← Write specs by level guides