Идеята е ако имаме „влакче“ от повече от 2 наследяващи се класа (А -> B -> C), трябва да можем директно от обект $а от клас A да използваме методи/пропъртита на обект $c от клас C без да имаме нужда от обект от клас B.
Защо да се стремим да махнем една брънка от веригата? Защото колкото повече брънки има, толкова „coupling“-ът на цялата система е по-голям.
Ако A зависи от B, и B зависи от C, то ако C например се промени, трябва да променим не само A но и B за да работи системата.
Да си представим примерът за обект Океан, който бива наследяван от обект Риба, който има например метод isHungry().
И да кажем, че търсим всички риби от океана, които са гладни. Логически мислим така – имаме океан, в океанът имаме риби, всяка риба е, или не е гладна.
Добре, но не може ли да прескочим океана, ако примерно искаме да намерим всички гладни риби и в морето, и в реката, и в езерото… нали ни интересуват само гладните риби незавсимо къде са, в океан или в море? Не може ли просто да извикаме isHungry() на обект Риба?
Целта на Законът на Деметра е, ако имаме „влакче“ от наследяващи се класове A -> B -> C, да предоврати необходимостта от А до C да минем през B.
Няма проблем обект $а да вика метод от B.
Няма проблем обект $b да вика метод от C.
Но има проблем $а да вика $b, който да вика метод от C.
От чисто логическа гледна точка, ситуации тип „влакче“ често са неизбежни. Но тогава трябва да добавим нов метод в B, който да вика нужната функционалност от C, а не директно C.
An object $a
can request a service (call a method) of an object instance $b
, but object $a
should not „reach through“ object $b
to access yet another object $c
to request its services. Doing so would mean that object $a
implicitly requires greater knowledge of object $b
‘s internal structure.
$
b should be modified if necessary so it can directly serve object $a request, propagating it to any relevant subcomponents. Alternatively, $a might have a direct reference to object $
c and make the request directly to that. If the law is followed, only object $b knows its own internal structure.
Идеята е най-малкото, ако използваш $b за посредник, и нещо го промениш, може да счупиш връзката с $c като се намалява т.н. coupling – взаимозависимостта между отделните класове.
Недостатък е, че LoD може да довете до „експлозия“ от wrapper методи.
Също, може да се наложи прекалено разбиване на класовете на твърде много и твърде малки такива.
Литература:
https://en.wikipedia.org/wiki/Law_of_Demeter
https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design
https://en.wikipedia.org/wiki/Aspect-oriented_programming
https://en.wikipedia.org/wiki/Principle_of_least_astonishment