little ruby blog

небольшой блог о ruby, rails и разной фигне

Закон Деметры или как избежать спагетти-ассоциаций

| Comments

Что такое закон Деметры?

Читая Rails antipatterns, я натолкнулся на упоминание одного принципа, о котором раньше не слышал (стыд мне!). Звучало его название как “Закон Деметры”.

Что же такое закон Деметры? Вкратце, это такое правило дизайна для ПО, в частности - для объектно-ориентированного. Был сформулирован в конце 1987 года в Бостоне и в наиболее краткой формулировке звучит так:

Не разговаривай с незнакомцами!

Если развернуть это определение, то объект A не должен иметь возможность получить непосредственный доступ к объекту C, если у объекта A есть доступ к объекту B и у объекта B есть доступ к объекту C.

Какое отношение это имеет Rails?

Очень простое. Мощнейший механизм ассоциаций в Rails почти провоцирует городить конструкции вида

1
<%= @order.user.address.city %>

Почему это плохо?

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

Как этого избежать?

Давайте посмотрим сначала на тот код, который мы имеем изначально. Он абсолютно типичный:

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

В результате мы получаем возможность сделать такой вызов:

1
<%= @order.user_city %>

Не правда ли, значительно изящнее?

Альтернативный вариант - использовать гем demeter, который делает то же самое, но отказаться от префиксов и использовать более одного уровня вложенности в нем, как я понял, невозможно.

Минусы

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

Comments