Skip to main content
ClaudeWave
Skill542 estrellas del repoactualizado 2d ago

nw-fp-domain-modeling

nw-fp-domain-modeling is a Claude Code skill for building type-safe domain models using functional programming patterns. It teaches algebraic data types (AND for records, OR for choice types), domain-specific wrappers around primitives, smart constructors with validation, and structural type design that makes invalid states impossible to construct. Use this skill when designing domain models where compile-time type safety prevents runtime errors and invalid business states.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/nWave-ai/nWave /tmp/nw-fp-domain-modeling && cp -r /tmp/nw-fp-domain-modeling/nWave/skills/nw-fp-domain-modeling ~/.claude/skills/nw-fp-domain-modeling
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# FP Domain Modeling

Domain modeling with types. Make illegal states unrepresentable, workflows as pipelines, error handling at the type level.

Cross-references: [fp-principles](../nw-fp-principles/SKILL.md) | [fp-hexagonal-architecture](../nw-fp-hexagonal-architecture/SKILL.md) | [fp-algebra-driven-design](../nw-fp-algebra-driven-design/SKILL.md)

---

## 1. The Two Building Blocks

[STARTER]

All domain types compose from two operations:

- **AND (Record Types)**: Value has ALL of these fields. Order requires CustomerInfo AND ShippingAddress AND OrderLines.
- **OR (Choice Types)**: Value is ONE OF these alternatives. ProductCode is either WidgetCode OR GizmoCode.

Combined recursively, these express virtually any domain structure.

---

## 2. Domain Wrappers for Primitives

[STARTER]

Never use primitives directly in the domain model. Each domain concept gets its own wrapper type.

**What**: Wrap primitives so the compiler distinguishes CustomerId from OrderId.
**When**: Every primitive with domain meaning.
**Why**: Prevents accidental mixing (compiler rejects comparing CustomerId with OrderId). Each wrapper carries its own validation rules. The type name IS the documentation.

---

## 3. Validated Construction (Smart Constructors)

[STARTER]

Raw constructor is private. A `create` function validates input and returns a Result type, making validation failure explicit.

**Pattern**: UnitQuantity must be between 1 and 1000. Its `create` function rejects values outside that range. A companion `value` function provides read access to the inner primitive.

**When**: Every domain wrapper with validation rules.
**Why**: Once constructed, a value is guaranteed valid. No defensive checks deeper in the code.

---

## 4. Making Illegal States Unrepresentable

[STARTER]

The central design guideline. Instead of flags and runtime checks, model the domain so invalid states cannot be constructed.

### Replace Flags with Distinct Types

Instead of `{ EmailAddress; IsVerified: bool }`, create separate `VerifiedEmailAddress` and `UnverifiedEmailAddress` types. Functions requiring verification take `VerifiedEmailAddress`, making misuse a compile error.

### Replace Optional Fields with Choice Types

Instead of `{ Email: option; Address: option }` (where both could be None), create: `EmailOnly | AddressOnly | EmailAndAddress`. The "at least one required" rule becomes structurally enforced.

### NonEmptyList for "At Least One" Rules

Define a type guaranteeing at least one element. Order with `OrderLines: NonEmptyList<OrderLine>` cannot have zero lines.

---

## 5. Workflows as Functions

[STARTER]

Every business workflow is a single function: Command in, Events out.

```
PlaceOrderWorkflow : PlaceOrderCommand -> AsyncResult<PlaceOrderEvent list>
```

### Pipeline Composition

Workflows decompose into steps, each transforming one document type into the next:

```
UnvalidatedOrder -> ValidatedOrder -> PricedOrder -> Events
```

Each step is stateless, pure, has single input/output type, and is independently testable. The workflow assembles by piping steps together.

**Why**: Pipeline makes the business process visible. Each step name is a domain concept.

---

## 6. Document Lifecycle as State Types

[INTERMEDIATE]

Rather than one Order type with flags, create separate types for each lifecycle stage:

- `UnvalidatedOrder` (raw input, all fields strings)
- `ValidatedOrder` (all fields checked)
- `PricedOrder` (prices calculated)

A top-level Order choice type unifies all states. New states (e.g., `Refunded`) added without breaking existing code.

**When**: Domain entities with distinct lifecycle stages where different data is available at each stage.

---

## 7. State Machines with Types

[INTERMEDIATE]

When an entity has distinct states with different data and different allowed operations, model each state as a separate type.

```
ShoppingCart = EmptyCart | ActiveCart of ActiveCartData | PaidCart of PaidCartData
```

Transition functions take the choice type, pattern-match on current state, return new state.

**Benefits**: All states explicit | each state has own data | invalid transitions prevented by types | pattern matching warnings reveal unhandled edge cases.

---

## 8. Error-Track Pipelines (Railway Pattern)

[INTERMEDIATE]

Each function returns a Result type. Pipeline short-circuits on first failure.

```
rawInput
  |> validateOrder           -- Result<ValidOrder, Error>
  |> bind calculateTotal     -- Result<PricedOrder, Error>
  |> bind checkInventory     -- Result<ConfirmedOrder, Error>
  |> bind chargePayment      -- Result<PaidOrder, Error>
  |> map generateReceipt     -- Result<Receipt, Error>
```

**Key combinators**:
- **map**: Transform success value (one-track into two-track)
- **bind**: Chain a function that itself returns Result
- **mapError**: Transform error value
- **tee**: Perform side effect without changing value (logging)

### Error Classification

| Category | Examples | Strategy |
|---|---|---|
| Domain Errors | Validation failure, out of stock | Model as types, return via Result |
| Panics | Out of memory, null reference | Throw exceptions, catch at top level |
| Infrastructure Errors | Network timeout, auth failure | Case-by-case |

### Unifying Error Types

Each step may have its own error type. Define a common error choice type and use `mapError` to lift step errors before composing.

### Collecting All Errors (Applicative Validation)

[ADVANCED]

Standard bind short-circuits on first error. For validation where you want ALL errors, use Applicative style -- runs all validations and accumulates errors into a list. See [fp-principles](../nw-fp-principles/SKILL.md) section 5.

**When**: Form validation | batch input checking | any place user needs all errors at once.

---

## 9. Modeling Dependencies

[INTERMEDIATE]

Each workflow step declares exactly the functions it needs as parameters:

```
CheckProductCodeExists : ProductCode -> bool
GetProductPrice        : Product
nw-ab-critique-dimensionsSkill

Review dimensions for validating agent quality - template compliance, safety, testing, and priority validation

nw-abr-critique-dimensionsSkill

Review dimensions for validating agent quality - template compliance, safety, testing, and priority validation

nw-ad-critique-dimensionsSkill

Review dimensions for acceptance test quality - happy path bias, GWT compliance, business language purity, coverage completeness, walking skeleton user-centricity, priority validation, observable behavior assertions, traceability coverage, and walking skeleton boundary proof

nw-agent-creation-workflowSkill

Detailed 5-phase workflow for creating agents - from requirements analysis through validation and iterative refinement

nw-agent-testingSkill

5-layer testing approach for agent validation including adversarial testing, security validation, and prompt injection resistance

nw-architectural-styles-tradeoffsSkill

Architectural style selection decision matrices, trade-off analysis, structural enforcement rules, and combination patterns. Load when choosing or evaluating architecture styles.

nw-architecture-patternsSkill

Comprehensive architecture patterns, methodologies, quality frameworks, and evaluation methods for solution architects. Load when designing system architecture or selecting patterns.

nw-at-completeness-checkSkill

Canonical AT completeness gate — research-anchored 7-category taxonomy (C1-C7) + 15-item mechanical checklist. Paradigm-neutral. Drives acceptance-designer reviewer verdict deterministically.