90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
package domain
|
|
|
|
import (
|
|
"time"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// ExampleID is a strongly-typed identifier for examples.
|
|
type ExampleID string
|
|
|
|
// String returns the string representation of the ID.
|
|
func (id ExampleID) String() string {
|
|
return string(id)
|
|
}
|
|
|
|
// IsZero returns true if the ID is empty.
|
|
func (id ExampleID) IsZero() bool {
|
|
return id == ""
|
|
}
|
|
|
|
// Example name constraints.
|
|
const (
|
|
MinExampleNameLen = 1
|
|
MaxExampleNameLen = 100
|
|
MaxDescriptionLen = 500
|
|
)
|
|
|
|
// Example represents an example domain entity.
|
|
// This is a pure domain model with no external dependencies.
|
|
type Example struct {
|
|
ID ExampleID
|
|
Name string
|
|
Description string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// NewExample creates a new Example with validation.
|
|
// Returns ErrInvalidExampleName if the name is invalid.
|
|
func NewExample(id ExampleID, name, description string) (*Example, error) {
|
|
if err := validateExampleName(name); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := validateDescription(description); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
now := time.Now().UTC()
|
|
return &Example{
|
|
ID: id,
|
|
Name: name,
|
|
Description: description,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}, nil
|
|
}
|
|
|
|
// Update modifies the example's mutable fields with validation.
|
|
// Returns ErrInvalidExampleName if the name is invalid.
|
|
func (e *Example) Update(name, description string) error {
|
|
if err := validateExampleName(name); err != nil {
|
|
return err
|
|
}
|
|
if err := validateDescription(description); err != nil {
|
|
return err
|
|
}
|
|
|
|
e.Name = name
|
|
e.Description = description
|
|
e.UpdatedAt = time.Now().UTC()
|
|
return nil
|
|
}
|
|
|
|
// validateExampleName validates an example name.
|
|
func validateExampleName(name string) error {
|
|
length := utf8.RuneCountInString(name)
|
|
if length < MinExampleNameLen || length > MaxExampleNameLen {
|
|
return ErrInvalidExampleName
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateDescription validates a description.
|
|
func validateDescription(desc string) error {
|
|
if utf8.RuneCountInString(desc) > MaxDescriptionLen {
|
|
return ErrInvalidExampleName
|
|
}
|
|
return nil
|
|
}
|