2013-06-01 3 views
7

Закон Деметры кажется очень мощным понятием. Я могу понять, как он помогает писать хороший и поддерживаемый объектно-ориентированный код.Закон Деметры для Views: создать делегатов для доступа к атрибутам на связанных объектах или нет?

Some people suggest написать метод делегата каждый раз, когда вам нужно получить доступ к атрибуту связанного объекта в представлении. Вместо того, чтобы писать что-то вроде этого в представлении

@order.customer.name 

можно было бы написать этот код:

# model 
class Order < ActiveRecord::Base 
    belongs_to :customer 
    delegate :name, :to => :customer, :prefix => true 
end 

#view 
@order.customer_name 

С другой стороны, people argue that you views should not dictate models and you should not add methods such as delegate to a model only for the sake of trading a dot for an underscore in a view.

При нарушении Закона Деметры в представлении считается ли наилучшей практикой писать методы делегатов в моделях или нет?

ответ

7

Я вижу ваш customer_name автогенерированный метод делегатов как Простейшая вещь, которая работает прямо сейчас. Поскольку это один вызов метода (а не серия цепочек методов), его легко реорганизовать позже (или, проще рефакторировать, чем некоторые прикованные методы)

Представьте, что вы добавляете много клиентов в заказ, один из которых является основным клиентом, для любой причины. Теперь ваш класс заказа может выглядеть так:

class Order < ActiveRecord::Base 

    has_many :customers 

    def customer_name 
    if customers.first.primary? 
     customers.first.name 
    else 
     customers.last.name 
    end 
end 

Было легко заменить этот удобный метод делегата с помощью одного из наших собственных.

(Это также очень легко написать в первый раз, так как delegate позаботится обо всем шаблоне. Возможно, вы будете использовать customer_name в этой форме навсегда в своем приложении. Это трудно понять, но код, автоматическая запись в первый раз дешево, чтобы выбросить :))

Конечно, вам нужно избегать ситуаций, когда вы пишете имена методов, такие как customer_streetaddress_is_united_states? (где да, вместо кодирования графа объекта в точках, которые вы его кодируете in underscores.)

Если вашему взгляду действительно нужно знать, находится ли пользователь в США, возможно, такой способ может работать:

class Order < ActiveRecord::Base 

    belongs_to :customer 

    def shipping_to_us? 
     customer.shipping_country == "USA" 
     # Law of Demeter violation would be: 
     # customer.addresses.first.country == "USA" 
    end 
    end 

    class Customer < ActiveRecord::Base 
    has_many :addresses 

    def shipping_country 
     addresses.first.country 
    end 
    end 

Обратите внимание, здесь, как Orderспрашивает в Customer объект адрес доставки, против говоря клиента, чтобы получить его страна первый адрес заказчика в. Как босс, который говорит вам что-то сделать, и оставляет вас в покое против босса, который микроуровнеет точно, как вы делаете свой день за днем. (Для дополнительного назидания, прочитайте запрос, не говорите о подходе к разработке Ruby :))

Есть что сказать об использовании презентаторов, методов декоратора или помощников, чтобы избежать потенциально простое отображение логического кода засоряя ваши модели. Я оставлю это как упражнение для читателя :)

+1

Спасибо, очень хорошо объяснил. – migu