我陷入了一个奇怪的设计问题,
我正在开发两种类型的模型,
这两种类型的配置文件的典型OO行为是相同的,但只有重要的属性/属性是常见的(非常重要的属性5-6),其他属性如“兴趣等”(几乎10-15属性)不适用于bot配置文件
之前为此工作的编码人员为机器人配置文件/用户配置文件创建了单独的模型/控制器,这在任何地方创建了大量冗余,并且如预期的那样难以维护,编写测试等。我想干这个,至少要解决部分/全部冗余问题。
有人建议使用单表继承作为解决方案
有人建议使用多态关联。
什么是更好的方法。我们什么时候实际使用STI?
我自己的想法是,当模型的属性相同时,STI被最佳使用,并且它们的行为不同。
关于我能做些什么的想法?
答案 0 :(得分:35)
当属性相同但行为不同时,将STI描述为最有用,但“可能有点限制”。我喜欢使用STI,顾名思义,它是一种清晰的OO风格的继承关系,而不是不同类型的对象之间的数据库风格关系。
如果机器人和用户之间有共同的代码,我会说STI听起来像是赢家。如果只有一些共同的属性,它可能不太适用,但仍然值得一试。
我是一个很有实验性的人,所以我的建议就是试一试。分支您的代码并将模型重构为STI关系。看看它是否真的干涸了,或者只是为了解决其他一些问题而烦恼。
我认为你不会从控制器干涸中获得太多好处。根据我的经验,STI模型通常不会转换为类似的相关控制器。但那将是另一种尝试的东西。有时会有胜利,有时却没有。
答案 1 :(得分:29)
我写了一篇关于这个主题的文章,包括与STI合作的一些技巧:
Single Table Inheritance in Rails
简而言之:对象之间需要有一个明确的OO风格的继承关系(由womble雄辩地说明),而不仅仅是一些共享数据。如果没有自然而明显的类层次结构,随着应用程序的发展,STI设计可能难以维护。
其次,您应该考虑将所有数据放在一个表中是否很重要。使用多态关联,您的数据库查询将变得更加复杂,并且可能更慢。如果您计划在网站上列出所有对象(例如,在表格中),那么STI可能就是您的选择。
第三,确保您的子类没有太多的唯一属性。使用一个表中的所有数据,您不需要很多非全局列。这些不仅会占用空间(不是主要问题),而且会使数据结构混乱。如果您有“特殊”列,则应在代码中明确解释它们。
最后,如果您使用STI,我强烈建议您为所有子模型使用单个控制器。控制器的主要功能是提供对象的访问,如果需要以非常不同的方式访问对象,那么STI可能不是开始时的正确设计选择。
查看我的文章(上面的链接)以获取更多有用的提示。
答案 2 :(得分:5)
我可能会使用STI或根本没有特殊功能。您可以将所有内容称为“个人档案”,如果用户为零则您知道它是否为“机器人”。您也可以在不使用STI的情况下存储“类型”字段。
某些事情会影响我决定使用STI:
避免STI的原因有时会妨碍您。例如,将对象从一种类型更改为另一种类型(在这种情况下为Bot到配置文件)可能相当烦人。有时一个简单的“类型”字段更好。
值得注意的是,如果使用STI,您可能需要一个公共基类。因此,您可能需要Profile
,BotProfile
和UserProfile
。这些名字取决于你。 :)
答案 3 :(得分:4)
Rails STI的一个难题 - 大多数插件(等等)都不完全支持它。你会发现自己修补了许多常见的东西。