ddd-when-to-wrap-primitives

Evaluates whether primitive types should be wrapped in domain-specific types using cost-benefit criteria.

Updated Jun 23, 2026
One-click install
npx skills add https://github.com/j5ik2o/marp-ai-base --skill ddd-when-to-wrap-primitives-j5ik2o
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: ddd-when-to-wrap-primitives
Source: https://github.com/j5ik2o/marp-ai-base/tree/main/.agents/skills/ddd-when-to-wrap-primitives
Command: npx skills add https://github.com/j5ik2o/marp-ai-base --skill ddd-when-to-wrap-primitives-j5ik2o

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Deciding whether to wrap primitive types (String, int, float) in domain-specific types is a recurring design dilemma. Wrapping everything leads to Value Object Obsession with boilerplate-heavy wrapper classes, while wrapping nothing causes Primitive Obsession where domain constraints are invisible in code. This Skill provides a rational, cost-benefit-based decision framework to avoid both extremes. ## Core Features & Use Cases - Five-Criteria Decision Framework: Evaluates domain invariants, mix-up risk, domain operations, inseparable value pairs, and usage frequency to determine if wrapping is justified. - Three Wrapping Levels: Guides selection between lightweight type aliases (newtype/Branded Types), constructor-validated types (Smart Constructor), and full behavioral domain types. - Terminology Clarification: Disambiguates Value Object definitions across PofEAA (Fowler), DDD (Evans), and general usage to prevent team confusion during reviews. - Use Case: During a code review, you notice fn transfer(from: String, to: String, amount: f64) where arguments can be swapped silently. Use this Skill to determine that UserId/OrderId-style newtypes and a Money type are warranted, while a simple display name string should stay primitive. ## Quick Start Ask the AI whether a specific primitive value in your code should be wrapped in a domain type, for example by requesting an evaluation of whether an email address string field should become a dedicated type.

Frequently Asked Questions about ddd-when-to-wrap-primitives

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I decide whether to wrap a primitive type in a domain type?

Evaluate five criteria: domain invariants, argument mix-up risk, domain operations, inseparable value pairs, and usage across multiple modules. One strong yes suggests wrapping; multiple yeses strongly recommend it; all no means keep the primitive.

What is the difference between Primitive Obsession and Value Object Obsession?

Primitive Obsession represents everything as String or int so domain constraints never appear in code. Value Object Obsession mechanically wraps every primitive, creating boilerplate wrappers with no invariants or behavior. Both are design failures.

What is the difference between PofEAA and DDD Value Objects?

PofEAA Value Objects (Fowler) are objects compared by value with immutability recommended. DDD Value Objects (Evans) extend that definition by requiring domain invariants and domain behavior. Every DDD VO is a PofEAA VO, but not vice versa.

Should I use a newtype or a full class when wrapping primitives in Rust or TypeScript?

Use the lightest option matching your need: newtype or Branded Types for mix-up prevention only, Smart Constructors when invariants must be validated at construction, and full behavioral types when domain operations like Money addition belong on the type.

When should I not wrap a primitive type?

Skip wrapping when the value has no invariants, no mix-up risk, no domain operations, and is used in only one place. Log messages, loop counters, and single-use strings are typical examples where wrapping adds cost without benefit.