name: code-designing description: | Domain type design and architectural planning for Go code. Use when planning new features, designing self-validating types, preventing primitive obsession, or when refactoring reveals need for new types. Focuses on vertical slice architecture and type safety. allowed-tools: - Skill(go-linter-driven-development:testing)
Reference: See reference.md for complete design principles and examples.
Ready to implement? Use @testing skill for test structure.
Scan codebase structure:
- Vertical slicing:
internal/feature/{handler,service,repository,models}.go - Horizontal layering:
internal/{handlers,services,domain}/feature.go
Always ask user approval with options:
- Option A: Vertical slice (recommended for cohesion/maintainability)
- Option B: Match existing pattern (if time-constrained)
- Acknowledge: Time pressure, team decisions, consistency needs are valid
If migration needed, create/update docs/architecture/vertical-slice-migration.md:
# Vertical Slice Migration Plan
## Current State: [horizontal/mixed]
## Target: Vertical slices in internal/[feature]/
## Strategy: New features vertical, migrate existing incrementally
## Progress: [x] [new-feature] (this PR), [ ] existing features
See reference.md section #3 for detailed patterns.
If yes to any → Consider creating a type
// Validating constructor func NewTypeName(input underlyingType) (TypeName, error) { // Validate input if /* validation fails */ { return zero, errors.New("why it failed") } return TypeName(input), nil }
// Methods on type (if behavior needed) func (t TypeName) SomeMethod() result { // Type-specific logic }
</design_self_validating_types>
<plan_package_structure>
- **Vertical slices**: Group by feature, not layer
- Each feature gets its own package
- Within package: separate by role (service, repository, handler)
Good structure:
user/ ├── user.go # Domain types ├── service.go # Business logic ├── repository.go # Persistence └── handler.go # HTTP/API
Bad structure:
domain/user.go services/user_service.go repository/user_repository.go
</plan_package_structure>
<design_orchestrating_types>
For types that coordinate others:
- Make fields private
- Validate dependencies in constructor
- No nil checks in methods (constructor guarantees validity)
```go
type Service struct {
repo Repository // private
notifier Notifier // private
}
func NewService(repo Repository, notifier Notifier) (*Service, error) {
if repo == nil {
return nil, errors.New("repo required")
}
if notifier == nil {
return nil, errors.New("notifier required")
}
return &Service{
repo: repo,
notifier: notifier,
}, nil
}
// Methods can trust fields are valid
func (s *Service) DoSomething() error {
// No nil checks needed
return s.repo.Save(...)
}
DESIGN PLAN
Feature: [Feature Name]
Core Domain Types:
- UserID (string) - Self-validating, prevents empty IDs
- Email (string) - Self-validating, RFC 5322 validation
- Age (int) - Self-validating, range 0-150
Orchestrating Types:
- UserService - Coordinates user operations
Dependencies: Repository, Notifier
Methods: CreateUser, GetUser, UpdateUser
Package Structure:
user/
├── user.go # UserID, Email, Age, User
├── service.go # UserService
├── repository.go # Repository interface + implementations
├── notifier.go # Notifier interface + implementations
└── handler.go # HTTP handlers
Design Decisions:
- UserID is custom type to prevent passing empty/invalid IDs
- Email validation centralized in NewEmail constructor
- Vertical slice keeps all user logic in one package
- Repository as interface allows multiple backends (Postgres, in-memory for tests)
Integration Points:
- Consumed by: HTTP API (/users endpoints)
- Depends on: Database, Email service
- Events: UserCreated event published after creation
Next Steps:
1. Create types with validating constructors
2. Write unit tests for each type
3. Implement UserService
4. Write integration tests
Ready to implement? Use @testing skill for test structure.
- Can logic be moved into smaller custom types?
- Is this type designed around intent and behavior?
- Have I avoided primitive obsession?
- Is validation in the right place (constructor)?
- Does this follow vertical slice architecture?
Only after satisfactory answers, proceed to implementation.
See reference.md for complete design principles and examples.
- Architecture pattern analyzed (vertical/horizontal/mixed)
- Core domain types identified with validation rules
- Self-validating type design documented
- Package structure follows vertical slice pattern
- Design decisions documented with rationale
- Pre-code review questions answered satisfactorily
- Design plan output presented to user