🖼️

デメテルの法則とは?深堀してみた

2023/01/19に公開

デメテルの法則とは

「知らない人とは話さないで、親しい人とだけ話して🥰?」ということ。

要は「親クラス.子クラス.子クラスのメソッド/プロパティ」の様な形で、メソッド/プロパティを呼び出すのはNGということです。

wikipediaにはここ書かれていますが、結構掴みにくいです。

デメテルの法則 (Law of Demeter, LoD) または最小知識の原則 (Principle of Least Knowledge) とは、ソフトウェアの設計、特にオブジェクト指向プログラムの設計におけるガイドラインである。 このガイドラインは1987年の末にかけてノースイースタン大学で作成された。簡潔に言うと「直接の友達とだけ話すこと」と要約できる。基本的な考え方は、任意のオブジェクトが自分以外(サブコンポーネント含む)の構造やプロパティに対して持っている仮定を最小限にすべきであるという点にある。

英名

Law of Demeter

簡単な例

user.profile.address.country;
  // = "Japan"

userオブジェクトはprofileを呼び出し、
profileはaddressを呼び出し、
addressがcountryプロパティを呼んでいる状態です。

userからしたらaddressは友人の友人くらいの関係でしょう。
だって直接呼んでないし...
しかし、そんな親しくもないaddressのcountryというプロパティをuserが呼んでいる状態です。

「知らない人とは話さないで、親しい人とだけ話して🥰?」に反してそうじゃないですか?

親しい人とは、知らない人とは

objA.objB.objC

objBは、objAからしたら直接呼ぶ関係なので親しい人
objCは、objAからしたら直接呼ばない関係なのでよく知らない人

これくらいの認識で一旦大丈夫です。

なぜダメなのか

結合度が高くなるし影響が予測しにくい からです。

自分に親しい友人だけを招いてパーティに呼ぶとすると、誰が来るかは管理しやすそうです。
一方、友人の友人も許可した日には、どうでしょう?管理が大変なのは想像がつきますね。

親しくない人と関わると、管理が大変になってしまうものなのです。
なので、親しい人だけにしましょうねという話。

どうすればいいのか

プロパティ/メソッドを直接参照せずにアクセッサ(getter/setter)経由で呼び出す

user.profile.getAddressCountry()

userオブジェクトはprofileを呼び出し、
profileはgetAddressCountryメソッドを呼んでいる状態です。

userからしたら近い関係のprofileのメソッドを呼んでいるだけになりますね。
「知らない人とは話さないで、知っている人とだけ話して🥰?」をとりあえず守れていそうです。

※「tell, don't ask(尋ねるな命じよ)」を適用する対応方法もありますが、話が長くなってしまうのでここでは割愛させてもらいます。

まとめ

「親クラス.子クラス.子クラスのメソッド」みたいな形になっていたら要注意。
とにかく知らない人とは話さないで、親しい人とだけ話してください。
そうすれば結合度が低くなり、保守性の向上が期待できます。

参照

https://anupamchugh.medium.com/stop-violating-the-law-of-demeter-keep-your-code-loosely-coupled-4c86a2f2cf70

https://levelup.gitconnected.com/the-law-of-demeter-4bd40aa21cbe?gi=bdc42b1132c3

https://mi.codes/programming-principles-the-law-of-demeter-lod/

Discussion