何时创建一个类vs设置一个布尔标志?

Chr*_*ton 7 oop ruby-on-rails object

我有一个有趣的问题要提出来; 应该何时创建模型类/对象而不是为存储在数据库中的数据设置布尔标志?

例如,假设我有一个Person类,它具有President,Guard和PartTime的布尔标志.根据标志的值,对此类/模型的处理方式不同.因此,总统从Guard和PartTime(r)获得系统中的不同权限.

什么时候使用单表继承来表示这个信息,什么时候会继续使用布尔标志?

我的直觉是使用STI将它们转换为不同的对象,因为这对我来说似乎更为OO.检查布尔值在某种程度上似乎是错误的,但我也可以看到它的位置.

更新澄清

让我使用另一个例子,因为上面的例子涉及太多案件.

我正在使用包含Pages的CMS应用程序,页面可以是公共页面,私有页面,共享页面,隐藏页面或默认页面(这意味着它是您在URL中未指定页面时获得的内容).现在,我们有一个Page模型,一切都是一个布尔标志 - Public,Default,Shared.

我不相信这是处理这个问题的最佳方法.特别是因为我们有规则来管理哪个页面可以是什么,即默认页面或共享页面必须是公共页面,而私有页面只是私有.

我同意下面的评论,Roles for the Person示例非常有意义.我不确定它的Page例子是什么.

而要使事情变得更复杂,只能有一个默认页面和一个共享页面.STI可能允许我验证这一点,但我不确定,因为表中可能有许多默认和共享页面(只是没有与特定站点相关联).

注意:问题的上下文是Ruby on Rails应用程序,但适用于任何面向对象的语言.

mol*_*olf 5

首先,让我们确定单表继承通常用于什么目的。这是一种将彼此相似的事物的存储和行为结合在一起的方法。坚持使用CMS,示例是带有的表posts,该表可以是CommentArticle。它们共享相似的数据和行为,但最终是不同的东西。某物是否为注释不是对象的状态,而是身份。

但是,在您的示例中,页面是公共页面还是私有页面,共享页面与否或隐藏页面似乎是页面状态的一部分。尽管从技术上讲单表继承可能起作用(假设所有子类都是互斥的),但这不是一个很好的选择。

状态应在一个或多个列中执行。可以将表示某种双重状态的属性指定为布尔值;。如果页面始终是私有页面或公共页面,则可以将其建模为单个布尔列private。如果不是私有的,那么它是公开的(或者相反)。

在某些情况下,您可能要存储三个或更多互斥的不同状态。例如,页面可以是私有页面,也可以是公共页面,也可以是共享页面(我不知道是否是这种情况,我们假装是这样)。在这种情况下,布尔值将无济于事。您可以使用多个布尔标志,但是正如您正确观察到的那样,这非常令人困惑。最简单的方法是将此模型建模为枚举。或者当你缺乏这方面的(如使用Rails的情况下),只需使用字符串值具有特殊的意义,并添加一个验证,以确保您使用的值只有一个privatepublicshared

有时,不同状态变量的某些组合无效。例如,页面可能是草稿已批准(由boolean列反映approved);它也可以是公共的私有的(也由布尔列反映)。我们可以决定在公开页面之前,必须先对其进行批准。在这种情况下,我们声明其中一种状态无效。这应该通过模型验证来反映。重要的是要意识到,根本上来说,草稿公共页面并不是不可能的,这只是不可能的,因为您决定不应该这样做。

在创建模型时,请仔细区分反映真实世界中主题的实际属性和状态属性,以及确定应该可行和不可行的业务规则。第一个应建模为列,第二个应建模为验证。


原始答案:

一个明显的区别是,布尔标志允许将a Person同时标记为总统后卫。如果您的模型应允许这些情况,则单表继承将对您不起作用。

另一方面,也许Person是总统的行为与普通人不同。一个人只能是总统警卫。在这种情况下,继承可能更合适。我不认为您应该将“兼职”建模为子类。无论如何,这是一个属性。

还有一个重要的第三种选择,您可以将人的工作角色与模型完全分开。一个有一份(或很多?)工作,这些工作是或不是兼职。这种模型的优势在于,您可以将一个人的属性与其工作属性分开。毕竟,人们会换工作,但这并不能使他们真正成为另一个人。最终,对我而言,这似乎是模拟您的情况的最现实的方法。


Don*_*oby 0

我不喜欢为此使用标志,但也不为此子类化 Person。相反,附加一个角色(或者如果您有一个既是总统又是警卫的人,则附加一组角色)以及管理权限的角色子类。

就我个人而言,我既不是总统也不是警卫,但我既是程序员又是音乐家,有时还担任其他一些角色(事实上,多年前我曾一度担任警卫,同时也是一名学生。) 。

一个人有一个角色。