Есть ли причина (дизайн кода) не встраивать классы при разработке моделей MongoMapper?

Этот вопрос относится к использованию Ruby on Rails 3 с MongoMapper и EmbeddedDocument. Кроме того, ManyAssociation.

http://mongomapper.com/documentation/embedded-document.html

Примеры MongoMapper (по ссылке выше) показывают два отдельных класса:

class Order
  include MongoMapper::Document

  many :line_items
  timestamps!
end

class LineItem
  include MongoMapper::EmbeddedDocument

  key :name, String
  key :quantity, Integer
end

Но это загрязняет глобальное пространство имен LineItem. Вне контекста, LineItem для чего? А что, если я хочу, чтобы другая модель, например WishList, также имела набор LineItem?

Таким образом, можно встроить класс LineItem внутрь Order следующим образом:

class Order
  include MongoMapper::Document

  many :line_items, :class_name => "Order::LineItem"
  timestamps!

  class LineItem
    include MongoMapper::EmbeddedDocument

    key :name, String
    key :quantity, Integer
  end
end

Хотя технически это может быть нормально (да?), не столкнусь ли я позже с проблемами дизайна? Это просто делает код слишком уродливым? Слишком сложно?

Предположительно, наличие this в языке Ruby означает, что кто-то считает это хорошей идеей?

Что мне всегда нравилось в Django, так это то, как он использует «приложения» для группировки связанных классов моделей (и разделения пространств имен). Таким образом, мой код выше также достигает этого в Rails.


person multipolygon    schedule 26.08.2011    source источник


Ответы (1)


Я не вижу никаких технических проблем ни для одного из подходов. Проблема, с которой я столкнулся, заключается в том, что когда класс встроен в его родителя, а также находится в том же файле, я забуду, что он там. Поэтому, если ваше пространство имен указано как Order::LineItem, вы можете создать папку «order» в папке «models» и поместить туда «line_item.rb».

Другая проблема в том, что если вы хотите иметь контроллер для Order::LineItem, вы также должны создать пространство имен и поместить его в папку, а в маршрутизаторе это будет выглядеть так:

resource :orders do
  resources :line_items,         :controller => "order/line_items"
end

Если вы знаете, что ваше приложение будет иметь несколько типов line_items, я бы рекомендовал не использовать пространство имен — иначе вы можете перекодировать. Например, если позже вам понадобятся два типа line_items, вы можете даже обнаружить, что часть вашего кода может быть повторно использована между моделями, и если вы создали пространство имен для своего первого элемента line_item, вы можете обнаружить, что убрали его.

В Python пространства имен считаются отличной вещью, и их должно быть больше. Но когда вы думаете о глобальном пространстве имен вашего приложения Rails, оно не так загромождено. Авторы Gem довольно хорошо сохраняют пространство имен всех своих классов в одном модуле gem, поэтому в вашем приложении Rails у вас будет одно пространство имен для каждого используемого вами gem (сам Rails состоит из 5 gem, не уверен, сколько глобальных константы), плюс куча файлов, включаемых Rails (например, SecureRandom). Оказывается, очень приятно иметь эти файлы «прямо там», и на практике я обнаружил, что конфликты пространств имен случаются редко, и их можно легко обойти. Я столкнулся с проблемой пространства имен только один раз, но несколько раз я случайно определял метод «отправить» в модели — гораздо более распространенная проблема с аналогичными последствиями.

person Brian Hempel    schedule 29.08.2011