何时创建类与设置布尔标志? [英] When to create a class vs setting a boolean flag?

查看:67
本文介绍了何时创建类与设置布尔标志?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如,假设我有一个Person类,该类具有用于President,Guard和PartTime的布尔标志.根据标志的值,对此类/模型进行不同的处理.因此,总统从警卫队和PartTime(r)中获得了系统中的不同特权.

何时将使用单表继承"来表示此信息,何时将仅继续使用布尔标志?

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

更新以进行澄清

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

我正在使用一个包含Pages的CMS应用程序,一个Page可以是Public,Private,Shared,Hidden或Default(这就是您未在url中指定页面时得到的页面).现在,我们有一个Page模型,所有内容都是一个布尔型标志-Public,Default,Shared.

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

我同意下面的评论,即角色为人"示例很有意义.我不确定页面示例是否确实如此.

为了使事情变得更复杂,只能有一个默认"页面和一个共享"页面. STI可能使我对此进行验证,但是我不确定,因为表中可以有很多默认页面和共享页面(只是与特定站点没有关联).

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

解决方案

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

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

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

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

有时候,不同状态变量的某些组合无效.例如,页面可能是草稿批准的(由布尔列approved反映);并且它也是 public private (也由布尔列反映).我们可以决定在公开页面之前,必须先 批准该页面.在这种情况下,我们声明其中一种状态无效.这应该通过模型验证反映出来.重要的是要认识到,草稿公开页面并不是根本不可能的,它只是不可能的,因为您决定不应该发生这种情况.

在创建模型时,请仔细区分反映现实世界中主题的实际属性和状态的属性,以及确定哪些内容的业务规则应该是可能的,而不应该是什么.第一个应该建模为列,第二个应该建模为验证.


原始答案:

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

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

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

I have an interesting question to pose; when should one create a model class/object as opposed to setting a boolean flag for data stored in a database?

For example, say I have a Person class that has boolean flags for President, Guard, and PartTime. This class/model is treated differently depending on the value of the flags. So the President gets different privileges in the system from the Guard and from the PartTime(r).

When would one use Single Table Inheritance to represent this information and when would one just continue to use the boolean flag?

My instinct is to convert these to different Objects using STI since this seems more OO to me. Checking booleans seems wrong in some way, but I can also see a place for it.

Update for clarification

Let me use another example because the one above has too many cases involved with it.

I am working on a CMS application that contains Pages, a Page can be Public, Private, Shared, Hidden, or Default (meaning it is what you get when you don't specify a page in the url). Right now, we have a Page model and everything is a boolean flag - Public, Default, Shared.

I am not convinced this is the best method of handling this. Especially since we have rules governing what page can be what, i.e., the Default page or a Shared page must be a Public page whereas a Private page is just Private.

I agree with the comment below that Roles for the Person example makes a lot of sense. I am not sure that for the Page example it does.

And to make things more complicated, there can only be one Default page and one Shared page. STI may allow me to validate this, but I am not sure since there can be many default and shared pages in the table (just not associated with a particular site).

Note: The context for the question is a Ruby on Rails application, but is applicable for any object-oriented language.

解决方案

First of all, let's establish what single-table inheritance typically is used for. It is a way to combine the storage and behaviour of multiple things that resemble each other. Sticking to a CMS, an example would be a table with posts, which could be either a Comment or an Article. They share similar data and behavior, but are ultimately different things. Whether or not something is a comment is not the state of the object, it's an identity.

In your example, however, whether or not a page is public or private, shared or not, or hidden, appears to be a part of the state of the page. Although single-table inheritance might technically work (provided all subclasses are mutually exclusive), it's not a good fit.

State should be implemented in one or more columns. An attribute that represents a certain dual state can be specified as a boolean; yes or no. If a page always is either private or public, you can model this as a single boolean column, private. If it's not private it's public (or the other way around).

In some cases you may want to store three or more different states that are mutually exclusive. For example, a page could be either private, or public, or shared (I don't know if this is the case -- let's pretend that it is). In this case a boolean will not help. You could use multiple boolean flags, but as you correctly observe that is very confusing. The easiest way is to model this as an enumeration. Or when you lack this (as is the case with Rails), simply use string values with a special meaning and add a validation that ensures the only values you use are one of private, public or shared.

Sometimes certain combinations of different state variables are invalid. For example, a page might be a draft or approved (reflected by a boolean column approved); and it is also either public or private (also reflected by a boolean column). We could decide that a page should must be approved before it is made public. In this case we declare one of the states invalid. This should be reflected by the validation of your model. It is important to realise that a draft, public page is not fundamentally impossible, it's only impossible because you decide it should not happen.

When creating your model, make a careful distinction between the attributes that reflect actual properties and states of the subjects in the real world, and the business rules that determine what should be possible and what shouldn't be. The first should be modelled as columns, the second as validations.


Original answer:

One obvious difference is that boolean flags allow a Person to be marked as president and guard at the same time. If your model should allow these situations, single-table inheritance will not work for you.

On the other hand, maybe a Person that is a president behaves differently from a regular person; and a single person can only be president or guard. In this case inheritance may be a better fit. I don't think you should model "part time" as a subclass, though. That is an attribute in any case.

There is also an important third option, one where you completely separate the job or role of a person from the model. One person has one (or many?) jobs, which are or are not part-time. The advantage of this model is that you separate attributes of a person from the attributes of their job. After all, people change jobs, but that does not make them literally a different person. Ultimately this seems to me the most realistic way to model your situation.

这篇关于何时创建类与设置布尔标志?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆