Закон Деметры можно легко обойти?

Всегда ли можно обойти Закон Деметры, просто создав больше методов?

Некоторые отмечают, что это неверно (http://wiki.c2.com/?LawOfDemeterIsHardToUnderstand ), но кажется, что это должно быть правильно, так как Закон Деметры позволяет отправлять сообщения любому параметру.

Например, это нарушает закон Деметры (при условии, что m1 не возвращает a1), но его можно изменить:

class C1 {
    m1 (a1: C2) {
        a1.m1().m2() // not allowed
    }
}

Доступ к m2 можно преобразовать в другой метод:

class C1 {
    m1 (a1: C2) {
        m2(a1.m1()) // allowed
    }

    m2 (a1: C3) {
        a1.m2()
    }
}

person Victor    schedule 20.11.2019    source источник
comment
Я бы предпочел, чтобы это называлось «Иногда полезное предложение Деметры». Мартин Фаулер   -  person Ian Mercer    schedule 20.11.2019
comment
Я предпочитаю, чтобы это называли иногда полезным предложением Мартина Фаулера. :) Даже если Мартин Фаулер знает, когда нарушение LoD допустимо, вы, вероятно, этого не знаете. Так что прекратите это делать!   -  person Robert Bräutigam    schedule 23.03.2020


Ответы (1)


«Когда ваш метод принимает параметры, ваш метод может напрямую вызывать методы для этих параметров».

Я бы сказал, что то, как это написано, оставляет интерпретацию, следует ли учитывать весь стек выполнения метода или нет (для меня это подразумевает, что его следует учитывать). Если это так, то это нарушение независимо от добавленного уровня косвенности (m2), а если нет, то код не нарушает правило. Однако это рекомендация, и она не поможет разработчикам, которые не понимают цели, которой она служит: увеличить инкапсуляцию и ограничить связанность.

Конечно, существует множество творческих способов создания ужасных моделей, которые по-прежнему соответствуют правилам и определениям большинства принципов дизайна, но это, очевидно, не главное. Это все равно, что сказать, что частные модификаторы можно легко обойти с помощью отражения: это правда, но довольно сложно сделать это по ошибке.

С точки зрения инкапсуляции и связи между кодом, который вы разместили, и a1.m1().m2() нет различий: C1 связан с C2 И C3, который был получен через C2. Тот факт, что C2 клиентам (например, C1) нужно копаться во внутренностях, является хорошим показателем того, что его инкапсуляция может быть улучшена.

Другой принцип, который идет рука об руку с Законом Деметры, — это принцип Говори, не спрашивай. , в котором говорится, что объектам нужно говорить, что делать, а не спрашивать их состояние. Это также способствует лучшей инкапсуляции и, следовательно, уменьшает связанность.

Следует сделать одно важное замечание: существует два типа объектов: структуры данных и «реальные объекты» (данные и поведение). Структуры данных (например, DTO — мешки для получения/установки) не подчиняются большинству принципов проектирования, таких как Закон Деметры, поскольку их роль заключается исключительно в представлении и обмене данными. Однако такие структуры данных обычно находятся на границах системы (например, сервисы приложений, API-интерфейсы HTTP и т. д.), и наличие многих таких объектов в ядре модели является запахом объектно-ориентированного кода.

person plalx    schedule 20.11.2019