4.6 KiB
4.6 KiB
Package Modernization Instructions
Goal
Transform legacy packages to use generic MasterList pattern with simplified database operations.
Steps
1. Implement Generic MasterList Base
Create internal/common/master_list.go
with generic collection management:
type MasterList[K comparable, V Identifiable[K]] struct {
items map[K]V
mutex sync.RWMutex
}
2. Consolidate Package Structure
Remove:
- Legacy wrapper functions (LoadAll, SaveAll, etc.)
- Duplicate database files (database.go, database_legacy.go)
- README.md (use doc.go instead)
- Separate "active_record.go" files
Consolidate into:
{type}.go
- Main type with embedded database operationstypes.go
- Supporting types only (no main type)master.go
- MasterList using generic baseplayer.go
- Player-specific logic (if applicable)doc.go
- Primary documentation{type}_test.go
- Focused tests
3. Refactor Main Type
Transform the main type to include database operations:
// Before: Separate type and database operations
type Achievement struct {
ID uint32
Title string
}
func LoadAchievement(db *database.Database, id uint32) (*Achievement, error)
func SaveAchievement(db *database.Database, a *Achievement) error
// After: Embedded database operations
type Achievement struct {
ID uint32
Title string
db *database.Database
isNew bool
}
func New(db *database.Database) *Achievement
func Load(db *database.Database, id uint32) (*Achievement, error)
func (a *Achievement) Save() error
func (a *Achievement) Delete() error
func (a *Achievement) Reload() error
4. Update MasterList
Replace manual implementation with generic base:
// Before: Manual thread-safety
type MasterList struct {
items map[uint32]*Achievement
mutex sync.RWMutex
}
func (m *MasterList) AddAchievement(a *Achievement) bool {
m.mutex.Lock()
defer m.mutex.Unlock()
// manual implementation
}
// After: Generic base
type MasterList struct {
*common.MasterList[uint32, *Achievement]
}
func NewMasterList() *MasterList {
return &MasterList{
MasterList: common.NewMasterList[uint32, *Achievement](),
}
}
func (m *MasterList) AddAchievement(a *Achievement) bool {
return m.MasterList.Add(a)
}
5. Implement Identifiable Interface
Ensure main type implements GetID()
:
func (a *Achievement) GetID() uint32 {
return a.AchievementID // or appropriate ID field
}
6. Simplify API
Remove:
- Legacy type variants (Achievement vs AchievementRecord)
- Conversion methods (ToLegacy, FromLegacy)
- Duplicate CRUD operations
- Complex wrapper functions
Keep:
- Single type definition
- Direct database methods on type
- Domain-specific extensions only
7. Update Documentation
Create concise doc.go
:
// Package achievements provides [brief description].
//
// Basic Usage:
//
// achievement := achievements.New(db)
// achievement.Title = "Dragon Slayer"
// achievement.Save()
//
// loaded, _ := achievements.Load(db, 1001)
// loaded.Delete()
//
// Master List:
//
// masterList := achievements.NewMasterList()
// masterList.Add(achievement)
package achievements
8. Testing
Create focused tests:
- Test core type operations (New, Save, Load, Delete)
- Test MasterList basic operations
- Remove legacy compatibility tests
- Keep tests simple and direct
Key Principles
- Single Source of Truth: One type definition, not multiple variants
- Embedded Operations: Database methods on the type itself
- Generic Base: Use common.MasterList for thread-safety
- No Legacy Baggage: Remove all "Legacy" types and converters
- Documentation in Code: Use doc.go, not README.md
Migration Checklist
- Create/verify generic MasterList in common package
- Identify main type and supporting types
- Consolidate database operations into main type
- Add db field and methods to main type
- Replace manual MasterList with generic base
- Implement GetID() for Identifiable interface
- Remove all legacy types and converters
- Update doc.go with concise examples
- Simplify tests to cover core functionality
- Run
go fmt
andgo test
Expected Results
- 80% less code in most packages
- Single type instead of multiple variants
- Thread-safe operations via generic base
- Consistent API across all packages
- Better maintainability with less duplication
Example Commands
# Remove legacy files
rm README.md database_legacy.go active_record.go
# Rename if needed
mv active_record.go achievement.go
# Test the changes
go fmt ./...
go test ./...
go build ./...