Law of Demeter

Идеята е ако имаме „влакче“ от повече от 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

https://en.wikipedia.org/wiki/Information_hiding

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *