デメテルの法則
https://gyazo.com/4f04219f7b1d5f8ce5785bb0a705977f
オブジェクト指向プログラムにデメテルの法則を適用する場合には、この法則はより厳密に「関数/メソッドに関するデメテルの法則」(Law of Demeter for Functions/Methods, LoD-F) と言い表すことができる。この場合、あるオブジェクトAは別のオブジェクトBのサービスを要求してもよい(メソッドを呼び出してもよい)が、オブジェクトAがオブジェクトBを「経由して」さらに別のオブジェクトCのサービスを要求してはならない。 より形式的に言えば、関数に対するデメテルの法則に従った場合、オブジェクトO上のメソッドMが呼び出してもよいメソッドは以下のオブジェクトに属するメソッドのみに限定される。
Oそれ自身
Mの引数に渡されたオブジェクト
Mの内部でインスタンス化されたオブジェクト
Oを直接的に構成するオブジェクト(Oのインスタンス変数)
簡単な例として、犬を散歩に連れ出すことを考える。この際、犬の足に直接「歩け」と命じるのはおかしいだろう。この場合は、犬に対して命令し、自分の足の面倒は自分で見させるのが正しい方法だといえる。
getter/setterがアンチパターンになりやすいのは、このデメテルの法則を簡単に壊しまくるから
知りすぎるんじゃねーぞ というギャングのたとえは分かりやすい
法則だと従わないといけないような強制度を持ってしまう
凝集度とのトレードオフもあるので強制で従うものではない
個人的には集約(DDD)の中ですべてこれに従うと肥大化して扱いにくくなるので、文脈に応じて崩している ドメインの文脈で「集約Aの配下に集約Bを置いているが、隠蔽化の目的はない」という場合はA.B.GetXX()とメソッドチェーンで呼んで方が扱いやすいケースとか
「最小知識」の捉え方が人によって違うのが問題になる
最小知識は、別にクラス1個の知識というわけではない。クラスAとクラスBとクラスCの3つが最小知識だと言える場合は、A.B.C.XXX() という呼び出しは問題ない。
stringとか、自作ドメインクラスのMoneyとかNameクラスも最小知識に入れちゃっていいでしょ