在模型中重复数据以满足在集合中使用迪米特定律是否合适?
这是一个人为的例子,假设我想列出一个人有朋友的国家的人口,这里有下面两个设置。最好在模型中重复数据吗?
有人告诉我,遵循德墨忒尔定律很重要,例子是你告诉一个狗要走路,命令他的腿走路是愚蠢的。
以我的经验不足(新手)我发现,当模型重复数据 People.where(:country =>friend.country)
时,查询会更容易执行,而不是集合 where存在链式关联(迄今为止这是不可能的): People.where(:city => { :county => { :region => { :country =>; friend.city.county.region.country }}})
(如果你能想象出正确的人为 LoD 设置和语法,这将真正帮助这里的菜鸟理解这个概念,我真的希望我没有使用示例这与德米特定律无关)我尝试通过delegate
应用LoD,并被告知我仍在链接(我就是这样),我能想到的唯一解决方案是重复可以通过关联访问的数据。
但我讨厌重复数据!这是由于我们遵循 DHH 的 Rails 教程,我们重新创建了 twitter,他展示了创建关系与重复数据相比有多么出色。
重复数据是否适合减少关联的束缚?
模型、重复数据
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
This is a contrived example, say I want to list the population of a country that a person has a friend in, here are two setups below. Would it be best to repeat data in the models?
I've been told that the Law of Demeter is important to follow, the example is you tell a dog to walk, it is folly to command his legs to walk.
In my wealth of inexperience (noob) I have found that the query would be much easier to do when the models repeat data, People.where(:country => friend.country)
, vs collections where there are chained associations (which have been impossible thus far): People.where(:city => { :county => { :region => { :country => friend.city.county.region.country }}})
(It would really help this noob here understand the concept if you could imagine the correct contrived LoD setup and syntax, I really hope I didn't use an example that has nothing to do with the Law of Demeter) I've tried applying LoD via delegate
and was told I'm still chaining (which I am), the only solution I can think of is to repeat data that could be accessible via associations.
But I hate repeating data! This is due to following DHH's Rails tutuorial where we re-create twitter, he showed how great it is to create relationships vs repeating data.
Should repeating data be appropriate to get the associations less chained?
Models, repeating data
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
vs models with chained associations
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这似乎不是德米特定律的问题,而是数据库设计和数据完整性的问题。应排除第一个选项,因为它创建的数据库绝对违反第三范式(3NF):
在第一个示例中,如果一个国家 HM 城市,如果您将该城市更新为属于另一个区域,会发生什么情况不再属于国家? ->嘭!数据完整性消失了!当然,一个城市不太可能搬到不同的国家,但就像你说的,这是一个人为的例子,我说的是一般情况
你应该谷歌数据库规范化和第三范式了解更多。
另外,在这种情况下,您违反 3NF 只是因为您认为可以通过这样做来“提高性能”。这是一个预优化的案例,也是一个不好的做法。虽然在某些情况下,非规范化是一种可控风险,但如果您刚刚在 Rails 中启动应用程序,情况绝对不是这样。让您的数据库担心快速获取数据。您可以通过提供良好的索引来帮助它。
另外,我认为您正在寻找一种创建嵌套关系的方法。您希望的情况是:
通过地区的国家 HM 县
,以及
通过县的国家 HM 城市,
如果您使用的是 3.0,这将是 3.1 中的标准,那么您可以使用
https://github.com/ianwhite/nested_has_many_through
gem,我目前正在使用,并且非常满意。
This does not seem to be an issue of law of demeter as much as it is an issue of Database design and Data Integrity. The first option should be ruled out because it creates a database that definitely violates Third Normal-Form (3NF):
In your first example, if a Country HM cities, what happens if say, you update that city to belong to a different region that no longer belongs to the Country? -> Bam! Data Integrity Gone! Of course, it is unlikely that a city will move to a different country but like you said, this is a contrived example and i'm talking about the general case
You should google Database Normalization and Third Normal Form for more.
Also, in this case, you're violating 3NF only because you think you can 'improve performance' by doing so. This is a case of pre-optimization and a bad practice. While in some cases de-normalization is a managed risk, Here be dragons, and if you're just starting an app in rails, this is definitely not the case. Let your DB worry about fetching the data quickly. you can help it by providing good indexes.
Also, I think that what you're looking for is a way to create a nested has many through relationship. You want to it to be the case that:
a Country HM Counties THROUGH Regions
and that,
a Country HM Cities THROUGH Counties
this will be standard in 3.1 if you're on 3.0, then you can use the
https://github.com/ianwhite/nested_has_many_through
gem, which i am currently using, and am quite happy with.
啊,“Demeter 偶尔有用的建议”。 (马丁·福勒。)
我认为 DIE/DRY 和标准化是更基本的原则,但最终这将是相互冲突的准则之间的较量,您需要运用常识来应对。
该“法则”适用于一个特定项目中的对象类,并且作为类层次结构设计模型确实具有明显的价值。
但是对于 Demeter 特别针对 Rails 视图的应用存在争议。 根据定义,它们是一个报告,因此德米特的建议是否适用值得怀疑。
Ahh, the "occasionally useful suggestion of Demeter". (Martin Fowler.)
I think DIE/DRY and normalization are more fundamental principles, but it's ultimately going to be a contest between conflicting guidelines that you will need to apply common sense to.
The "law" applied to object classes in one specific project and does have obvious value as a class hierarchy design model.
But there is controversy over Demeter's application specifically with respect to Rails views. By definition they are a report, and so it is questionable whether the Suggestion of Demeter is applicable.
我认为您应该尽可能避免重复数据。但是,您可以创建聚合对象来组合数据。因此,您可以保持核心实体的清洁,但随后拥有聚合对象的其他支持实体。
如果使用 SQL 中的视图示例,则可以检索由许多实体组合而成的结果。该结果可能是聚合实体,并且是“重复”数据的完全合法的方式。
In my opinion you should avoid repition of data where you can. However, you can create aggregate objects which allow you to combine data. So you can keep your core entities clean but then have additional supporting entities which agreggate objects.
If you use the example of a View in SQL, you can retrieve a result which is the combination of many entities. This result could be the agreggate entity and is a perfectly legitimate means of 'repeating' data.