Закон Деметры - проблема реального мира
Я пытаюсь лучше понять Закон Деметры в реальном мире (иначе как мое заявление), но у меня есть некоторые заблуждения по поводу причин и преимуществ, которые я получаю при уходе с цепи обязанностей.
У меня есть пример, где я рассматриваю использование. Есть классы с отношениями
Enquiry -> assignedTo -> Room
Rooms -> assignedTo -> Building
Building -> assignedTo -> Company
Теперь мне нужно получить доступ к некоторым данным компании, напр. название компании, и у меня есть доступ к запросу. Итак, мой текущий поток:enquiry.getManager().getRoom().getBuilding().getCompany().getName()
- довольно долго, не так ли?
Я думаю, что если я последую за LoD, его следует изменить на enquiry.getHostingCompanyName()
но мне кажется, что мне нужно создатьroom.getHostingCompanyName()
а также building.getHostingCompanyName()
заранее, и в результате он будет очень хрупким и потребует гораздо больше изменений, чем предыдущий подход, когда речь заходит о рефакторинге.
Можете ли вы дать какие-либо советы по этому поводу? Или, может быть, мои предположения совершенно неверны, и это должно быть сделано по-другому?
2 ответа
Вы используете не объекты, а только структуры данных. Вы пишете что-то вроде:
new Human().getStomach().getContent().insert(new Cake());
вместо
new Human().eat(new Cake());
Реальные объекты должны инкапсулировать / скрывать внутреннюю структуру и предоставлять API для конкретного домена. Также для меня немного странно, что Комната содержит Компанию.
По моему мнению, Комната должна не знать о компаниях, вместо этого вы должны получить ссылки на комнату от объекта Компании.
Мне кажется, что ваша структура объекта управляется базой данных, но это не хорошо.
Все вышеперечисленное имеет смысл, когда оно применяется к системе с богатым доменом, а не для некоторых тривиальных CRUD. В системах CRUD структуры данных работают лучше.
Реальная проблема Закона Деметры (или Принципа Наименьшего Знания) выглядит примерно так:
О, черт, только что реализованные здания не всегда присваиваются одной компании. Придется поменять интерфейс этого класса. Это серьезное изменение. Что ж, лучше собери друзей и поменяй их... Почему, черт возьми, это вызывает 101 ошибку? Сколько друзей нужно одному классу?
Закон Деметры действительно о капсулировании. Это своего рода инкапсуляция, о которой вы не много слышите. Обычно инкапсуляция - это то, что находится в объекте. Здесь речь идет о знании самого объекта.
Если у вашего объекта есть несколько друзей, которые имеют дело с остальным миром, и это не нужно, тогда объект фактически инкапсулируется, даже если он публичный. Это перестает быть правдой, если объекты из внешнего мира проникают в объект через этих друзей. Теперь ваш объект может быть известен любому объекту. Это много нужно исправить. Объекты прячутся за своими друзьями. Не хочу быть популярным. Они хотят сделать немного работы для нескольких близких друзей. Они хотят быть заключенными в капсулу.
Вот почему, если вам нужно попросить друга друга сделать что-то, вы нарушаете эту инкапсуляцию. Вы должны сказать своим друзьям сделать что-то для вас, а не беспокоиться о том, кто их друзья. У тебя достаточно друзей.
Смысл в том, что если вы обнаруживаете, что вам нужно пройти через классы, чтобы получить то, что вам нужно, это означает, что некоторая работа была оставлена невыполненной, что позволило бы вам даже не знать, к какому классу вы стремитесь. Делай работу и перестань так дружить со всем.
Если вам нужно больше, я уже писал об этом раньше.