Согласно закону Деметры, разрешено ли классу возвращать одного из его членов?
Да, это, безусловно, так и есть.
Давайте посмотрим на основные моменты :
- Каждый юнит должен иметь только ограниченные знания о других юнитах: только юниты, «тесно» относящиеся к текущему юниту.
- Каждый юнит должен разговаривать только со своими друзьями; не разговаривай с незнакомцами
- Поговорите только со своими непосредственными друзьями.
Все три из них оставляют у вас один вопрос: кто друг?
Принимая решение о том, что возвращать, Закон Деметры или принцип наименьшего знания (LoD) не требует от вас защиты от кодировщиков, которые настаивают на его нарушении. Это диктует, что вы не заставляете кодеров нарушать его.
Смущение - вот почему многие считают, что сеттер всегда должен возвращать пустоту. Нет. Вы должны разрешить способ создания запросов (получателей), которые не изменяют состояние системы. Это базовое разделение командных запросов .
Означает ли это, что вы свободны вникать в кодовую базу, объединяющую все, что вы хотите? Нет. Соединяйте только то, что должно было быть вместе. В противном случае цепь может измениться, и вдруг ваши вещи сломаются. Это то, что подразумевается под друзьями.
Длинные цепи могут быть предназначены для. Свободные интерфейсы, iDSL, большая часть Java8 и старый добрый StringBuilder предназначены для создания длинных цепочек. Они не нарушают LoD, потому что все в цепочке предназначено для совместной работы и обещают продолжать работать вместе. Вы нарушаете деметру, когда цепляете вместе вещи, которые никогда не слышали друг о друге. Друзья - это те, кто обещал, что ваша сеть будет работать. Друзья друзей не сделали.
Помимо классов, которые были специально назначены для возврата объектов - таких как классы фабрики и компоновщика - нормально ли, чтобы метод возвращал объект, например, объект, удерживаемый одним из свойств класса, или будет нарушать закон Деметры (1) ?
Это только создает возможность нарушить деметру. Это не нарушение. Это даже не обязательно плохо.
И если он нарушает закон Деметры, имеет ли значение, если возвращаемый объект является неизменным объектом, который представляет собой часть данных и содержит только геттеры для этих данных (2)?
Неизменное это хорошо, но не имеет значения здесь. Пройдя сквозь длинную цепочку, не становится лучше. То, что делает это лучше, отделяет получение от использования. Если вы используете, спросите, что вам нужно в качестве параметра. Не иди на охоту, углубляясь в добытчиков незнакомцев.
В псевдокоде:
Я подозреваю, что закон Деметера запрещает такую модель, как приведенная выше. Что я могу сделать, чтобы функция doSomethingElse () могла быть вызвана без нарушения закона (3)?
Прежде чем говорить о том, x.doSomethingElse(a)
понимаю, что вы в основном написали
b.getA().doSomething()
Теперь LoD - это не упражнение по подсчету точек . Но когда вы создаете цепочку, вы говорите, что знаете, как получить A
(используя B
), и знаете, как использовать A
. Ну A
и B
лучше быть близкими друзьями , потому что вы только в сочетании их вместе.
Если вы только что попросил что - нибудь рукой для Вас , A
как вещь , которую вы могли бы использовать A
и не волновало , откуда она и B
могла прожить жизнь счастливой и свободной от вашей одержимости получать A
от B
.
Что касается x.doSomethingElse(a)
отсутствия подробностей о том, откуда x
взялось, LoD вообще нечего сказать по этому поводу.
LoD может способствовать отделению использования от строительства . Но я укажу, если вы неукоснительно относитесь к каждому объекту как к дружественному, вы застрянете при написании кода в статических методах. Таким образом, вы можете построить удивительно сложный граф объектов в основном таким образом, но в конечном итоге вам придется вызвать метод, чтобы начать работу. Вы просто должны решить, кто ваши друзья. От этого никуда не деться.
Так что да, классу разрешено возвращать одного из его членов в LoD. Когда вы это сделаете, вы должны уточнить, дружит ли этот член с вашим классом, потому что, если это не так, какой-то клиент может попытаться соединить вас с этим классом, используя вас, чтобы получить его, прежде чем использовать его. Это важно, потому что теперь то, что вы возвращаете, должно всегда поддерживать это использование.
Есть много случаев, когда это просто не проблема. Коллекции могут игнорировать это просто потому, что они предназначены дружить со всем, что их использует. Точно так же объекты ценности дружат со всеми. Но если вы написали утилиту проверки адреса, которая требовала от объекта сотрудника, из которого он извлек адрес, вместо того, чтобы просто запросить адрес, то лучше надеяться, что и сотрудник, и адрес получены из одной и той же библиотеки.