Посетитель шаблона нарушает закон Деметры?

Закон Деметры предполагает самую слабую связь между классами.

Это означает, что 90% всех геттеров / сеттеров, выставляемых в классе, должны быть «удалены» и заменены «поведенческими» методами. В самом деле, это соответствует философии «скажи, а не спрашивай», потому что от клиента не ожидается, что он будет обрабатывать свое поведение с помощью некачественных методов получения / установки. Это уменьшает дублирование кода также, если то же действие используется где-то еще.

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

С другой стороны, определение шаблона посетителя:

Посетитель позволяет вам определить новую операцию без изменения классов элементов, с которыми он работает.

Таким образом, на первый взгляд, это противоречит ожиданиям Закона Деметры:

  • Один (Посетитель) подразумевает структуру класса для предоставления получателя / установщика, чтобы Посетитель мог изменять состояния объекта, не касаясь самого класса.

  • Другой (Деметра) призывает заключать все поведенческие коды, непосредственно связанные с объектом, в один и тот же класс.

Итак, мой вопрос:

Когда мы можем считать, что класс закрыт для модификации и, таким образом, перестать добавлять к нему поведенческие методы и поэтому предпочли бы добавлять их во вновь созданный посетитель с большим риском того, что клиент использует геттеры / сеттеры вместо поведенческих методов, уже представленных ранее в начальном классе?

17
задан Roman C 20 March 2016 в 07:24
поделиться

1 ответ

Краткий ответ: нет .

Во-первых, я не думаю, что «говори, не спрашивай» говорит, что вы должны удалить все ваши геттеры и сеттеры, но вы должны удалить их, если они не добавляют никакого значения или выставить внутреннее состояние. Так, в качестве примера, получатели должны постараться как можно больше вернуть неизменные данные. Примером с сеттерами являются объекты настройки или политики , это объекты, которые не нужны для правильной работы экземпляра, но если они предоставляются, они изменяют поведение.

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

Что касается другого вопроса, я немного запутался в вашем последнем абзаце, так как не знаю, говорите ли вы о принципе открытия / закрытия или о том, как создать функцию с использованием шаблона посетителя.

В одном примечании, я думаю, ключом является понимание того, что SOLID, Закон Деметры и все другие практики являются передовыми методами , а не передовыми методами («передовые практики» являются маркетинговый термин). Если вы возьмете любую из этих практик до крайности, они, вероятно, в конечном итоге повредят удобочитаемости или удобству сопровождения кода.

(кстати, хороший вопрос: D)


Преимущество принципа открытого / закрытого типа в основном относится к коду, который будет использоваться другими людьми способами, которые мы не можем действительно предвидеть (рамки являются примером этого). Поэтому, если вы пишете фреймворк, вам нужно добавить точки расширения и использовать языковую функцию, чтобы предотвратить наследование класса (например, final в Java или запечатанный в C #) или просто позволив разработчику переопределить определенные методы. Идея состоит в том, чтобы предотвратить наивного пользователя от переопределения важного фрагмента объекта и неожиданного выхода из строя фреймворка. Некоторые языки / фреймворки смеются над этим (например, Ruby / Rails) и поощряют пользователя открывать классы для добавления или изменения функций (с некоторым успехом).

Если вы пишете приложение (и у вас есть код), я бы посоветовал вам не обращать слишком много внимания на принцип «открыто / закрыто» и сосредоточиться на применении закона Деметры (в разумной степени: D) .

11
ответ дан 30 November 2019 в 14:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: