Contents
A class must: 1. Explicitly receive all dependencies (via DI) — it should not secretly rely on any helper. 2. Maintain a consistent responsibility. (クラスは次を満たす必要がある:1. すべての依存関係を明示的に受け取る(DI経由)— ヘルパーに密かに依存してはいけない。2. 一貫した責任を維持する)
解説
依存関係が暗黙的だと、テストやデバッグが困難になり、コードの理解に時間がかかります。すべての依存関係をコンストラクタで明示的に注入することで、クラスが必要とするものが一目でわかり、モックやスタブを使ったテストが容易になります。また、一貫した責任を維持することで、クラスの目的が明確になり、変更の影響範囲が限定されます。これは保守性の高いコード設計の基本原則です。
具体例
// 悪い例(暗黙的な依存)
type OrderService struct {
// 依存関係が明示されていない
}
func (s *OrderService) CreateOrder(items []Item) error {
// 内部でグローバルなhelperを使用
db := GetGlobalDB() // 暗黙的な依存
logger := GetGlobalLogger() // 暗黙的な依存
total := calculateTotal(items)
if err := db.Insert(total); err != nil {
logger.Error(err)
return err
}
return nil
}
// 良い例(明示的な依存注入)
type OrderService struct {
db Database
logger Logger
pricer PriceCalculator
}
func NewOrderService(db Database, logger Logger, pricer PriceCalculator) *OrderService {
return &OrderService{
db: db,
logger: logger,
pricer: pricer,
}
}
func (s *OrderService) CreateOrder(items []Item) error {
total := s.pricer.CalculateTotal(items)
if err := s.db.Insert(total); err != nil {
s.logger.Error(err)
return err
}
return nil
}
