Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to create a class vs setting a boolean flag?

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.

like image 483
Chris Johnston Avatar asked Dec 15 '10 21:12

Chris Johnston


1 Answers

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.

like image 141
molf Avatar answered Sep 22 '22 12:09

molf