About ddd-factory
ddd-factory is a DDD skill for designing factories that create complete, valid aggregates or value objects when construction is complex or carries domain meaning. It helps developers choose between constructors, entity creation methods, dedicated factories, and builders while keeping persistence in repositories.
Key features
- 01Guidance on three factory forms
- 02Criteria for choosing a creation approach
- 03Domain-language naming guidance
- 04Validation of completed objects
- 05Separation of creation and persistence
Use cases
- 01Creating aggregates from multiple inputs
- 02Enforcing invariants during object creation
- 03Choosing whether to introduce a factory class
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-factoryAfter installing, type/ddd-factoryin Claude Code to confirm it loaded.
Details
From the project READMEOne-line summary
A factory encapsulates the knowledge needed to create a complete, valid aggregate or value object when construction itself is complex or has domain meaning.
When to use this skill
- Creation requires assembling multiple sub-objects (a new
Orderis born with line items, an initial status, a created-at timestamp). - Creation must enforce invariants beyond simple field validation (a new
Subscriptionmust reference a validPlanand a non-cancelledCustomer). - The act of creation has a domain-meaningful name in the ubiquitous language (
Order.placeFor(customer, items),Account.openFor(applicant)) — not justnew Order(...).
When NOT to use this skill
- Simple objects whose constructor fully captures the work.
- A static creation method on the entity itself is sufficient — promote to a separate factory class only when the creation logic doesn't belong on the resulting object, or when multiple aggregates collaborate during creation.
- The "factory" you are tempted to write would just call
new— that is ceremony, not encapsulation.
Core content
Three common shapes, from least to most ceremony:
Static creation method on the entity. Order.placeFor(customer, items). Preferred when the creation logic naturally belongs on the resulting type. Names itself in the ubiquitous language. Encapsulates whatever construction work is needed without inventing a new class.
Dedicated factory class. A SubscriptionFactory with a method createFor(applicant, plan, paymentMethod). Use when creation involves orchestration that doesn't belong on the resulting entity — for example, calling other aggregates, looking up reference data, or coordinating multiple inputs.
Builder. A fluent builder for incremental construction. Use sparingly; builders shine when an aggregate has many optional fields and validation must run at the final build() step. Make sure the builder cannot hand back an invalid intermediate state — build() returns a fully validated aggregate or fails.
A factory's responsibility ends at returning a valid aggregate. Persistence is the repository's job. Mixing creation and persistence inside one factory blurs the layers.
Decision heuristics
- Start with a constructor or a static method. Promote to a factory class only when the work is too complex for the entity to own or involves multiple collaborators.
- The factory's method names should belong to the ubiquitous language —
placeOrder,openAccount,issueRefund— notcreate,make,instantiate. - If a factory needs to read or persist data, you are mixing concerns — the factory probably belongs in the application layer, or it should accept already-loaded inputs.
Anti-patterns
- Factories that also persist — confuses creation with lifecycle ownership.
- A
FooFactoryclass per entity, reflexively, even when itscreate()does nothing the constructor couldn't. - "FactoryFactory" indirection — almost always a sign of an over-engineered codebase.
- Builders that ship intermediate state — callers can hold a half-built
Orderand call methods on it.
See also
ddd-entity— what the factory typically creates.ddd-aggregate— factories produce whole aggregates, not half-aggregates.ddd-repository— the boundary; factory creates, repository persists.
References
- Evans, Domain-Driven Design (2003), Ch. 6 (The Life Cycle of a Domain Object).