Уместно ли повторять данные в моделях, чтобы удовлетворить закон деметры в коллекциях? - PullRequest
2 голосов
/ 19 июня 2011

Это надуманный пример, скажем, я хочу перечислить население страны, в которой у человека есть друг, вот две установки ниже. Будет ли лучше повторить данные в моделях?

Мне сказали, что Закон Деметры важен для подражания, например, вы говорите собаке ходить, глупо приказывать своим ногам ходить.

Из моего богатства неопытности (noob) я обнаружил, что запрос будет гораздо проще выполнить, когда модели повторяют данные, People.where(:country => friend.country) против коллекций, в которых есть цепочечные ассоциации (которые до сих пор были невозможны): People.where(:city => { :county => { :region => { :country => friend.city.county.region.country }}}) (Это действительно помогло бы этому новичку понять концепцию, если бы вы могли представить правильную придуманную настройку и синтаксис LoD, я действительно надеюсь, что не использовал пример, который не имеет ничего общего с Законом Деметры) Я попробовал применяя LoD через delegate и мне сказали, что я все еще в цепочке (что я и есть), единственное решение, о котором я могу подумать, - это повторить данные, которые могут быть доступны через ассоциации.

Но я ненавижу повторять данные! Это связано с тем, что после того, как мы заново создали твиттер в DHS, он показал, как здорово создавать отношения против повторяющихся данных.

Должны ли повторяющиеся данные быть уместными, чтобы ассоциации были менее скованы?

Модели, повторяющие данные

class Country < ActiveRecord::Base    
  has_many :regions    
  has_many :counties    
  has_many :cities    
  has_many :people
end

class Region < ActiveRecord::Base
  has_one :country
  has_many :counties
  has_many :cities    
  has_many :people
end

class County < ActiveRecord::Base
  has_one :country
  has_one :region
  has_many :cities    
  has_many :people
end

class City < ActiveRecord::Base
  has_one :country
  has_one :region
  has_one :county    
  has_many :people
end

class Person < ActiveRecord::Base
  has_one :country
  has_one :region
  has_one :county    
  has_one :city
  has_many :relationships
  has_many :friends, :through => :relationships
end

против моделей с цепными ассоциациями

class Country < ActiveRecord::Base    
  has_many :regions   
end

class Region < ActiveRecord::Base
  belongs_to :country
  has_many :counties
end

class County < ActiveRecord::Base
  belongs_to :region
  has_many :cities
end

class City < ActiveRecord::Base
  belongs_to :county
end

class Person < ActiveRecord::Base
  belongs_to :city
end

Ответы [ 3 ]

1 голос
/ 19 июня 2011

Кажется, это не проблема закона деметры, а проблема проектирования базы данных и целостности данных. Первый вариант следует исключить, поскольку он создает базу данных, которая определенно нарушает третью нормальную форму (3NF):

В вашем первом примере, если в городах страны HM, что произойдет, если, скажем, вы обновите этот город, чтобы он принадлежал другому региону, который больше не принадлежит стране? -> Бам! Целостность данных ушла! Конечно, маловероятно, что город переедет в другую страну , но, как вы сказали, это надуманный пример, и я говорю об общем случае

Для получения дополнительной информации вы должны воспользоваться Google Normalization и Third Normal Form.

Кроме того, в этом случае вы нарушаете 3NF только потому, что думаете, , что вы можете «повысить производительность», делая это. Это случай предварительной оптимизации и плохая практика. Хотя в некоторых случаях ненормализация является управляемым риском, вот, пожалуйста, драконы, и если вы только запускаете приложение в рельсах, это определенно не тот случай. Позвольте вашей БД беспокоиться о получении данных быстро. Вы можете помочь, предоставив хорошие индексы.

Кроме того, я думаю, что то, что вы ищете, - это способ создания вложенных отношений со многими. Вы хотите, чтобы это было так:

Страна HM Графства ЧЕРЕЗ Регионы

и то,

Страна HM Города ЧЕРЕЗ Графства

это будет стандарт в 3.1, если вы используете 3.0, тогда вы можете использовать

https://github.com/ianwhite/nested_has_many_through

самоцвет, которым я сейчас пользуюсь, и я вполне доволен.

1 голос
/ 19 июня 2011

Ааа, "иногда полезное предложение Деметры" .(Мартин Фаулер.)

Я думаю, что DIE / DRY и нормализация являются более фундаментальными принципами, но в конечном итоге это будет борьба между противоречивыми принципами, к которым вам нужно будет применить здравый смысл.

«Закон» применяется к классам объектов в одном конкретном проекте и имеет очевидную ценность в качестве модели проектирования иерархии классов.

Но существует спор по поводу приложения Деметра, особенно в отношении представлений Rails. По определению они являются отчетом, и поэтому сомнительно, применимо ли предложение Деметры.

0 голосов
/ 19 июня 2011

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

Если вы используете пример представления в SQL, вы можете получить результат, представляющий собой комбинацию множества сущностей. Этим результатом может быть совокупность и совершенно законный способ «повторения» данных.

...