https://github.com/winpooh32/spec
Golang Composite Specification pattern implementation
https://github.com/winpooh32/spec
ddd specification-pattern
Last synced: 13 days ago
JSON representation
Golang Composite Specification pattern implementation
- Host: GitHub
- URL: https://github.com/winpooh32/spec
- Owner: WinPooh32
- License: mit
- Created: 2025-05-25T02:47:56.000Z (10 months ago)
- Default Branch: master
- Last Pushed: 2025-05-25T06:16:17.000Z (10 months ago)
- Last Synced: 2025-05-25T06:29:53.736Z (10 months ago)
- Topics: ddd, specification-pattern
- Language: Go
- Homepage:
- Size: 1000 Bytes
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# spec
[](https://pkg.go.dev/github.com/WinPooh32/spec)
Simple implementation of the [Composite Specification pattern](https://martinfowler.com/apsupp/spec.pdf) ([archive](https://web.archive.org/web/20250428234628/https://martinfowler.com/apsupp/spec.pdf)). Only conjunction operation (and) is implemented for simplicity and better performance.
Also it can provide textual description what specification rule is not satisfied by using an error interface instead of a bool predicate.
## Example
Define class:
```go
type Man struct {
Age int
Mortal bool
Diet []string
}
```
Define specifications:
```go
type ImmortalSpec struct{}
func (ImmortalSpec) SatisfiedBy(man Man) error {
if !man.Mortal {
return nil
}
return fmt.Errorf("expected to be immortal")
}
type AncientSpec struct{}
func (AncientSpec) SatisfiedBy(man Man) error {
const n = 500
if man.Age >= n {
return nil
}
return fmt.Errorf("expected to be older than %d years", n)
}
type DietSpec struct {
Meals map[string]struct{}
}
func (diet DietSpec) SatisfiedBy(man Man) error {
for _, meal := range man.Diet {
if _, ok := diet.Meals[meal]; !ok {
return fmt.Errorf("expected diet: %v", diet.Meals)
}
}
return nil
}
```
Test specification is satisfied:
```go
// Define composite specification.
vampireSpec := spec.And(
ImmortalSpec{},
AncientSpec{},
DietSpec{map[string]struct{}{"blood": {}}},
)
// Define man instance.
man := Man{
Age: 200,
Mortal: true,
Diet: []string{"meat", "apple"},
}
// Test the man is a vampire.
fmt.Println(vampireSpec.SatisfiedBy(man))
// Output:
// expected to be immortal
// expected to be older than 500 years
// expected diet: map[blood:{}]
```