Это мини-серия статей по написанию поддерживаемого объектно-ориентированного кода без лишней нервотрепки.
Предыдущие части: Часть 1
Единственный закон в программировании — это отсутствие законов. А закон Деметры — это, скорее, рекомендации, а не свод правил по работе с кодом. Он позволяет уменьшить связанность между компонентами.
Train Wrecks в функциях
Всем нам знакомы длинные цепочки функций, которые выглядят примерно так:
obj.getX() .getY() .getZ() .doSomething();
Мы спрашиваем, спрашиваем, спрашиваем, а лишь затем что-то говорим. Ведь так намного лучше?
obj.doSomething();
ВызовdoSomething()
распространяется до достижения Z
. Эти длинные цепочки запросов называются «train wrecks» и нарушают принципы так называемого закона Деметры.
Закон Деметры
Закон Деметры говорит о том, что плохо, когда простые функции знают всю навигационную структуру системы.
Представьте себе, сколько информации сокрыто в строке obj.getX().getY().getZ().doSomething()
. Она знает, что в obj
есть X
, в X
есть Y
, в Y
есть Z
, и Z
может что-то делать. Это колоссальный объем данных для одной строки. А сама строка связана с функцией, которая содержит слишком много информации обо всей системе.
«Каждый модуль должен обладать ограниченным знанием о других модулях: знать о модулях, которые имеют «непосредственное» отношение к этому модулю. Каждый модуль должен взаимодействовать только с известными ему модулями «друзьями», не взаимодействовать с незнакомцами».
В объектно-ориентированных приложениях закон Деметры формализует принцип «Говори — не спрашивай» (Tell Don’t Ask) со следующим набором правил:
Вы можете вызывать методы объектов, которые:
1. передаются как аргументы;
2. были созданы локально;
3. являются экземплярами переменных;
4. являются глобальными переменными.
Пример
Здесь account.getPlan().getPrice()
нарушает закон Деметры. Самое очевидное решение — делегировать/сказать:
Заключение
Мы не хотим, чтобы функции знали обо всей системной карте объектов. Отдельные функции должны обладать ограниченным объемом знаний. Мы хотим говорить объектам по соседству, что именно требуется сделать, и делегировать им передачу этого сообщения наружу.
Придерживаться данного правила довольно сложно. Поэтому иногда его называют предложением Деметры — из-за того, с какой легкостью его можно нарушить. Но плюсы очевидны: любая функция, которая следует данному правилу и «говорит» вместо того, чтобы «спрашивать», отделяется от своих «соседей».
Биологические системы являются отличной иллюстрацией подобных систем. Клетки не задают друг другу вопросов. Они говорят, что именно нужно делать. Мы — примеры системы «Говори — Не спрашивай». И внутри нас преобладает закон Деметры.
Перевод статьи Arun Sasidharan: Object Oriented Tricks: #2 Law of Demeter