From agent-skills
This skill should be used when implementing DDD tactical design patterns in Go, including Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications.
npx claudepluginhub baotoq/agent-skills --plugin agent-skillsThis skill uses the workspace's default tool permissions.
To guide implementation of Domain-Driven Design tactical patterns in idiomatic Go. This skill covers Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications using Go-native idioms (composition over inheritance, interfaces, unexported fields, functional options).
Implements Domain-Driven Design tactical patterns for .NET: aggregates, roots, value objects, domain events, services, typed IDs, repositories. For DDD aggregates, events, bounded contexts.
Applies DDD tactical patterns—entities, value objects, aggregates, repositories, domain events—to enforce invariants when modeling domain logic or refactoring anemic models.
Provides Domain-Driven Design tactical patterns for modeling entities, value objects, domain services, repositories, aggregates, and bounded contexts in complex business domains.
Share bugs, ideas, or general feedback.
To guide implementation of Domain-Driven Design tactical patterns in idiomatic Go. This skill covers Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events, Factories, and Specifications using Go-native idioms (composition over inheritance, interfaces, unexported fields, functional options).
*T receiversT receiversNewX() constructors to enforce invariants at creationinternal/domain/context.Context as first parameter in repository and service methodsinternal/
├── domain/ # Domain layer (no external deps)
│ ├── customer/ # One package per aggregate
│ │ ├── customer.go # Aggregate root entity
│ │ ├── repository.go # Repository interface
│ │ ├── email.go # Value objects
│ │ ├── events.go # Domain events
│ │ └── errors.go # Domain errors
│ ├── order/
│ │ ├── order.go
│ │ ├── repository.go
│ │ ├── item.go # Child entity
│ │ └── money.go # Value object
│ └── shared/ # Shared kernel
│ ├── events.go # Event interface
│ └── specification.go # Generic specification
│
├── application/ # Application services (orchestration)
│ ├── command/
│ │ └── place_order.go
│ └── query/
│ └── get_customer.go
│
└── infrastructure/ # Technical implementations
├── postgres/
│ ├── customer_repo.go
│ └── order_repo.go
└── eventbus/
└── in_memory.go
Dependency rule: Domain has zero imports from application or infrastructure. Dependencies point inward.
| Pattern | Go Idiom | Receiver | Identity |
|---|---|---|---|
| Entity | Struct + pointer receiver | *T | By ID |
| Value Object | Type alias or struct + value receiver | T | By value |
| Aggregate Root | Entity + unexported children | *T | By ID |
| Repository | Interface in domain package | N/A | N/A |
| Domain Service | Stateless struct with deps | *T or func | N/A |
| Domain Event | Immutable struct | T (value) | By name+time |
| Factory | NewX() function | N/A | N/A |
| Specification | Generic interface IsSatisfiedBy(T) bool | T or *T | N/A |
When implementing a new aggregate or domain concept:
Email, Money, Address)infrastructure/ packageFor detailed implementation guides with full code examples, see:
references/entities-and-value-objects.md - Entities, Value Objects, and Factoriesreferences/aggregates-and-repositories.md - Aggregates, Repositories, and Domain Servicesreferences/events-and-specifications.md - Domain Events and Specificationsreferences/anti-patterns.md - Common mistakes and how to avoid themEntities have unique identity and mutable state. Use unexported fields, pointer receivers, and factory functions.
type Order struct {
id uuid.UUID
status Status
items []Item
createdAt time.Time
}
func NewOrder(customerID uuid.UUID) (*Order, error) {
return &Order{
id: uuid.New(),
status: StatusDraft,
items: make([]Item, 0),
createdAt: time.Now(),
}, nil
}
func (o *Order) AddItem(product ProductID, qty int, price Money) error {
if o.status != StatusDraft {
return ErrOrderNotDraft
}
o.items = append(o.items, NewItem(product, qty, price))
return nil
}
Immutable types validated at creation. Use value receivers. Return new instances for operations.
type Money struct {
amount int64
currency string
}
func NewMoney(amount int64, currency string) (Money, error) {
if currency == "" {
return Money{}, ErrInvalidCurrency
}
return Money{amount: amount, currency: currency}, nil
}
func (m Money) Add(other Money) (Money, error) {
if m.currency != other.currency {
return Money{}, ErrCurrencyMismatch
}
return Money{amount: m.amount + other.amount, currency: m.currency}, nil
}
Aggregate roots enforce invariants across child entities. All mutations go through the root.
func (o *Order) Place() error {
if len(o.items) == 0 {
return ErrEmptyOrder
}
if o.status != StatusDraft {
return ErrOrderNotDraft
}
o.status = StatusPlaced
o.events = append(o.events, NewOrderPlacedEvent(o.id, o.Total()))
return nil
}
Interface in domain, implementation in infrastructure. One repository per aggregate root.
// domain/order/repository.go
type Repository interface {
Find(ctx context.Context, id uuid.UUID) (*Order, error)
Save(ctx context.Context, order *Order) error
Update(ctx context.Context, id uuid.UUID, fn func(*Order) error) error
}
Immutable structs collected by aggregates, published by application layer.
type OrderPlaced struct {
orderID uuid.UUID
total Money
occurredAt time.Time
}
func (o *Order) PullEvents() []Event {
events := o.events
o.events = nil
return events
}
Stateless operations spanning multiple aggregates. Domain logic only, no orchestration.
type TransferService struct {
accountRepo account.Repository
}
func (s *TransferService) Transfer(ctx context.Context, from, to uuid.UUID, amount Money) error {
// Load aggregates, validate domain rules, coordinate changes
}
Composable business rules using Go generics.
type Specification[T any] interface {
IsSatisfiedBy(T) bool
}
func And[T any](specs ...Specification[T]) Specification[T] { /* ... */ }
func Or[T any](specs ...Specification[T]) Specification[T] { /* ... */ }
func Not[T any](spec Specification[T]) Specification[T] { /* ... */ }
SetStatus() with domain methods like Place(), Cancel(), Ship()Reconstruct() functions for loading from DB (bypass validation)var ErrNotFound = errors.New(...)) per aggregate packageDetailed guides with full code examples are in the references/ directory.