デメテルの法則 is 何
- ソフトウェア設計の一つのプラクティス
- 英語では
Law of Demeter(LoD)
。最小知識の原則とも。
- 英語では
- 「尋ねるな、命じろ(Don't ask,tell)」と言い換えることができる
- 部品を使う側は、使われる側の細かい事情を知らなくても使えるようにする、ということ
デメテルの法則に反している例
- あえて使われる側(部品側)のコードは記載していません
- 使う側の気持ちになって処理を確認してみる
package main
func main() {
// ...省略
// 勇者パーティーを生成する
party := NewParty(members)
if len(party.members) > 0 {
// もしパーティーメンバーが一人以上いたら、画面表示用のメンバーを取得する
memberForShow := party.members[0]
// 上記で取得したメンバーを画面表示する
showFirstMember(memberForShow)
}
}
使う側が、使われる側の細かい事情を知った上で操作するのはしんどい
- メンバーが1人以上いたら、とか最初のメンバーを取得して関数に渡す、とか使う側があれこれ配慮しないといけない
- そういう配慮を忘れてしまったら(例えば1人以上のチェックをしなかったら)バグが発生するかもしれない
- なので、使う側は単純に「こうしろい!」と命令できるようにしたい。「これってできますか……? できなかったらどうすればいいですか……?」といちいち聞かなくては使えないような部品は提供してはいけない。
package main
func main() {
// ...省略
// 勇者パーティーを生成する
party := NewParty(members)
// パーティー最初のメンバーを画面表示する
party.showFirstMember()
}
- バチクソシンプルになった
- 細かい処理や配慮は、使われる側の責務として実装させる
- ただ、上記のコードだと、エラー処理はどうすんの、ってことになる
package main
func main() {
// ...省略
party,err := NewParty(members)
if err != nil{
// そもそも0人パーティーを作った時点でエラーを発生させる
return err
}
if err = party.showFirstMember() ; err != nil{
return err
}
デメテルの法則を適用させるときは、コンポーネントの責務を再確認するときでもある
- 構造体の状態が正しく保たれるか、メソッドが正常に実行できるか、これらを担保するのはコンポーネント(部品)側の責務である
- 使う側があれこれ面倒をみないといけない状況は、ドメイン知識が漏れていたり、コンポーネントの凝集度が低下していたりする可能性がある
- デメテルの法則に反しているコードは、部品を使う側で、if文やswitch文などの制御文が多く使われていたり、ドット繋ぎで構造体の中身へのアクセスが頻繁に行われていることが多い
- こういったコードは保守性を損なわせるので積極的にリファクタリングしていこう