2013-04-29 2 views
2

Скажите, что у вас есть класс, Car, который имеет Driver. Если вы хотите получить доступ к возрасту водителя, вы могли бы сделать:Действует ли закон Деметры на стандартные методы объекта ActiveRecord?

@car.driver_age 

Вместо

@car.driver.age 

Если вы делегировали атрибут возраст водителя в Car модели (с префиксом равным TRUE).

Однако, если вы имели Passenger класс, и вы хотите получить доступ количество пассажиров в автомобиле, следующий не нарушая закон Деметры, или мое мышление слишком рьяных:

@car.passengers.count 
+1

более усердный термин: – apneadiving

+0

LoD не строго о количестве точек. –

ответ

5

Я думаю, что count настолько общий, что я не счел бы необходимым проксировать вызов. Я хотел бы задать себе вопрос:

Возможно ли, что будет реализация passengers в будущем, что не будет реагировать на count?

Поскольку passengers весьма вероятно, что контейнер типа навсегда, и все типы контейнеров в Ruby (Array, Hash ...) реагировать на count так, как и следовало ожидать, я бы ответить на этот вопрос «нет» и поэтому придерживайтесь @car.passengers.count.

EDIT

Но если вы быть строгим, вы на самом деле нарушение закона Деметры. Рассмотрим, например, класс RobotCar < Car, который не имеет пассажиров. Теперь, после LoD, вы можете просто вернуть 0 из метода car.passenger_count, тогда как если не следовать LoD, вам нужно будет вернуть пустой контейнер из passengers, чтобы не сломать другой код.

В конце концов, вам придется решить для себя, насколько вероятно, что интерфейс будет когда-либо изменяться. Если вы очень уверены в том, что это никогда не изменится, я думаю, это нормально, чтобы не подчиняться LoD.

+0

Отличный ответ. – Fuser97381

+0

Пустой список пассажиров может быть уместным, так как у робота-авто могут быть пассажиры. Есть еще один слой абстракции, например, это автомобиль *, способный * переносить пассажиров и просто пуст, или вообще лишен сидения, что и подразумевает этот класс класса RobotCar. Dunno, я нахожусь на заборе - вы все равно хотите вернуть что-то разумное или выбросить исключение, если вы попросите пассажиров робота, иначе ваш интерфейс потребует специальных проверок на всем протяжении. –

1

Если ваш класс/метод должен знать возраст водителя, он должен иметь прямую ссылку на драйвер:

@driver.age 

Или массив пассажиров:

@passengers.count 

Доступ к этому пути @car делает много предположений. Представьте себе автоматический автомобиль без водителя или игрушечной машины без пассажиров. @car.driver_age или @car.passengers_count не имеет смысла.

+0

meh, 'driver_age' будет nil,' passengers_count' будет всегда равным нулю. – kch

+2

@kch Я бы не ожидал, что автомобиль узнает возраст водителя в первую очередь. – Stefan

+0

ярмарка. (Дорогой СО, это полная длина моего комментария, спасибо за его nannying.) – kch

1

LoD - это не просто «подсчет точек», а торговля подчеркиванием точки не помогает.

Автомобили имеют драйвера, которые имеют возраст; в этом нет ничего неоправданного.

(ну, не совсем, потому что мы собираемся ввести возраст машинистов машин и эта модель не может объяснить, что, но это отдельный вопрос.)

Закон Деметры для функций требует, чтобы метод М объекта O может вызывать только методы следующих видов объектов:

  1. O себе
  2. параметров M,
  3. какие-либо объекты, созданные/экземпляры в пределах М компонент прямого
  4. Выходов объекты

В частности, объект следует избегать вызова методы объекта-члена, возвращенного другим способом.

+0

Замечания о пониженных оценках. Я не нахожу много недостатка в ответе, и его претензии подкреплены. –

Смежные вопросы