使用 STI 与类别相比有何优点?

发布于 2024-12-13 22:27:51 字数 655 浏览 0 评论 0原文

这来自 Rails 世界,但却是关于单表继承的一个非常普遍的问题。我问这个问题的唯一原因是,人们在没有明显原因的情况下不断向我推销性传播感染。也许我错过了一些要点?请考虑显示和显示这两种情况。存储网站上各个页面的页面内容:

场景1

class ContentItem < ActiveRecord::Base
  belongs_to category
end

这里所有可能的项目都存储在一张表中,仅通过类别来区分。然后,无论您何时需要显示所有新闻项目或常见问题解答项目,您只需调用类别即可。

场景2

class ContentItem < ActiveRecord::Base
  
end

class FaqItem < ContentItem
end

class NewsItem < ContentItem
end

这里不需要类别,但如果您需要添加另一种类型的ContentItem,则需要创建另一个模型,等等。

我对场景 #2 的问题是 FaqItem & NewsItems 完全相同。他们永远不会有所不同。唯一的区别是它们可以由不同的人修改(网站管理员与新闻公关人员)。

因此,虽然两种方法都可以,但为什么在这种特定情况下选择一种方案而不是另一种方案呢?

This comes from the Rails world, but is a pretty generic question about Single Table Inheritance. They only reason I'm asking this is that people keep pushing STI on me when there is no obvious reason for it. May be I'm missing some point? Please consider these two scenarios for displaying & storing page contents for various pages on the website:

Scenario 1

class ContentItem < ActiveRecord::Base
  belongs_to category
end

Here all the possible items are stored in one table, only distinguished by the category. Then wherever you need to display all news items or faq items , you just do a call to category.

Scenario 2

class ContentItem < ActiveRecord::Base
  
end

class FaqItem < ContentItem
end

class NewsItem < ContentItem
end

Here there is no need for category, but if you ever need to add another type of ContentItem, you need to create another model, and another and so on.

My problem with scenario #2 is that FaqItem & NewsItems are exactly the same. They are never going to be different. The only difference is that they can be modified by different people ( Site Admin vs PR person for news) .

So while both approaches are ok, why choose one scenario over the other in this particular instance?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

樱花细雨 2024-12-20 22:27:51

如果只有几个类别或类型,并且共享大量代码,则将其放在一个类中是非常易于管理的。但是一旦列表增长,您的代码将分散在 case 语句或 if 树中,这就是继承派上用场的地方。

例如:

def title
  case category_id
    when 'FaqItem'
      do_1_thing
    when 'NewsItem'
      do_another_thing
  end
end

相对于

class FaqItem < ContentItem
  def title
    do_1_thing
  end
end  

class NewsItem < ContentItem
  def title
    do_another_thing
  end
end  

第二种解决方案将更容易维护和理解。可能会有一些重复的代码,但这可以通过巧妙地使用父类来解决。

不过:您多久切换到使用 STI 还是一个品味问题,这取决于代码的复杂性。

If there are only a few categories or types, and a lot of code is shared, it is very manageable to put it in one class. But once the list grows, your code will be scattered with case statements or if-trees, and this is where inheritance comes in handy.

For instance:

def title
  case category_id
    when 'FaqItem'
      do_1_thing
    when 'NewsItem'
      do_another_thing
  end
end

as opposed to

class FaqItem < ContentItem
  def title
    do_1_thing
  end
end  

class NewsItem < ContentItem
  def title
    do_another_thing
  end
end  

The second solution will be more easily maintainable and understandable. There could be some duplication of code, but this could be solved by smartly using your parent class.

Still: it is a matter of taste how soon you switch to using STI, that will depend on the complexity of your code.

三生殊途 2024-12-20 22:27:51

我不熟悉术语“单表继承”,但它看起来像是关于子类化与类型代码的标准参数的一个实例。人们对此争论因为这两种选择都可能是正确的选择,具体取决于具体情况。我的务实建议是:考虑到更大的上下文,选择能够减少代码重复的策略。不仅要考虑您现在拥有的类别,还要考虑将来需要添加新类别的可能性。

I'm not familiar with the term "Single Table Inheritance", but it looks like an instance of the standard argument about subclassing versus type codes. People argue about this because both options can be the correct choice, depending on the circumstances. My pragmatic advice is: pick whichever tactic leads to less code duplication, given the larger context. Consider not only the categories you have now but also the possibility of needing to add new categories in the future.

蒗幽 2024-12-20 22:27:51

我喜欢在 Rails 中使用 STI,当 (a) 您需要在一个或多个子类中执行某些特定行为,以及 (b) 您将在应用程序的不同部分中查找父类和子类时。

在您给出的示例中,也许所有 ContentItems 都会有一个“title”属性。但也许 FaqItem 还需要一个“answer”属性,并且可能通过验证需要该属性。

另外,也许您的应用程序需要一个仅包含常见问题解答的常见问题解答页面 (FaqItem.all)。但也许它还需要一个包含所有内容项(或搜索功能)的完整索引页面。

诸如此类的事情正是性传播感染(STI)派上用场的地方。

(也不要忘记在类型列上创建索引)

I like to use STI in Rails when (a) you need some specific behavior in one or more subclasses and (b) you're going to be doing parent class and subclass finds in different parts of the app.

In the example you give, maybe all ContentItems will have a "title" attribute. But maybe the FaqItem also needs an "answer" attribute, and maybe the attribute is required via a validation.

Also, maybe your app will need an FAQ page with only the FAQs (FaqItem.all). But maybe it will also need a complete index page with all content items (or a search feature).

Stuff like that is where STI comes in handy.

(also don't forget to create an index on your type column)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文