31

This may initially seem generic, but in fact, I am actually making the decision on which I need to use.

What I am currently working on involves Employment Applications, those in which will need to be marked at some point Active or Inactive. When an application is submitted, it will default to Active. For certain reasons, it might later be set to Inactive. It can only be one of these and never null(In case this changes anything).

I am using this with Java + Hibernate + PostgresSQL, in case this also makes any difference. My first instinct is to use Boolean as my solution so that it truly acts as a flag, but I have coworkers who have suggested using enums or ints as more of a status rather then a flag.

I have solved problems such as this using all of the above solutions, and they all seem somewhat transparent to eachother.

Is there one way that is better for this situation?

TheJediCowboy
  • 8,924
  • 28
  • 136
  • 208
  • 1
    Related: [Are booleans as method arguments unacceptable?](http://stackoverflow.com/questions/135845/are-booleans-as-method-arguments-unacceptable) – John Kugelman Sep 28 '14 at 03:40

11 Answers11

25

Even ignoring the possibility of adding more status types in the future (which is certainly one good argument for an enum), I think an enum is absolutely the right way to go. You are not modelling a boolean condition, you are modelling the status of an application. Think about it: the application's status is not true or false, it's active or inactive! A status enum will represent this in the most natural way.

You also get a lot of built in advantages from using an enum, such as having a text description of each status tied directly to it, so you don't have to do things like

String text = application.isActive() ? "Active" : "Inactive";

You can just do

String text = application.getStatus().toString();

Additionally, you can tie specific behavior directly to each status with abstract methods that each enum implements differently, associate specific data with each status, etc.

You can also easily allow a boolean isActive check that is based on the status... you can't easily do that the other way around if you just store a boolean.

public boolean isActive() {
  return status == Status.ACTIVE;
}

And the fact that null shouldn't be a valid status is irrelevant... just ensure that any classes that store the status (say, your EmploymentApplication class or whatever) throw a NullPointerException if anyone tries to set a null status on it.

ColinD
  • 108,630
  • 30
  • 201
  • 202
  • ColinD, a `null` status is certainly relevant for Hibernate and PostgreSQL. There's really no need for the application to throw a `NullPointerException` because if the status column in the database table cannot be null, then the JDBC driver will throw an exception. If the Hibernate mapping for the attribute disallows null values and the application attempts to persist a null value for this attribute, then Hibernate will throw `org.hibernate.PropertyValueException: not-null property references a null or transient value`. – Derek Mahar Dec 02 '10 at 18:18
  • @Derek: Of course... I didn't mention the database side, but what I'm saying is that if `null` isn't a valid status you just need to ensure that the application fails quickly if a `null` status enters the system somehow. The sooner it fails, the easier it is to determine where that `null` came from and correct that... then just assume the status is not `null` everywhere in your code that _uses_ the status. – ColinD Dec 02 '10 at 18:27
  • 1
    +1, and im so close to make myself another account, just to upvote it again. – whiskeysierra Dec 02 '10 at 19:20
  • We had the same discussion today: When we have only two states (agreed and rejected), shouldn't we prefer a boolean for this duality, like `boolean agreed = false` to express "rejected" ? An **enum with self-explaining values** convinced on the storage-side because this way the column named "decision" can have either "AGREED" or "REJECTED" .. or nothing yet. – hc_dev Nov 28 '22 at 22:22
19

It totally depends on your requirement/specification. If you only want to record the status as active or inactive, the best way is to use boolean.

But if in the future, you will have a status such as,

  • ACTIVE
  • INACTIVE
  • SUSPENDED
  • BLOCKED

Enums is perfect for you. In your case, for now, a boolean is sufficient. Don't try overcomplicate things too early, you'll lose focus in your design & development of your system.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • 27
    I strongly disagree that using an enum is "overcomplicating" things. An enum is a more natural representation of "active" and "inactive" than "true" and "false" are, and has a lot of advantages that allow code related to those statuses (including just getting a name for each) to be centralized with their definition rather than scattered elsewhere in code. – ColinD Dec 02 '10 at 18:00
  • 5
    @ColinD, what I'm suggesting is that if a status is basically active/inactive, a simple `private boolean active` suffices. Until the OP knows the exact specifcation of the status, it's not necessary creating enums of values you don't know. Besides, representing a boolean field in PostGres is simpler than always changing the table field adding new values when additional value are added in the system. For now, the OP should start with what's provided. – Buhake Sindi Dec 02 '10 at 18:06
  • 2
    The advantage of using multiple boolean fields (e.g. `active`, `suspended` and `blocked`) is that adding a new status in the future does not affect existing code and queries, and those conditional expressions are usually going to be simpler. That is, a condition might be `active==false`, not caring why it happens to be inactive (suspended or blocked or some other future status) ... the downside of course is more fields and more data to maintain - and the risk of invalid/conflicting state, such as `active=false` and `suspended=true` at the same time, which your design/code needs to prevent. – mindplay.dk Nov 21 '12 at 21:18
13

Definitely don't use an int. Using an enum is future-proofing; you have to decide for yourself what's more readable, and whether YAGNI applies. Be aware that boolean is not the same thing as Boolean; Boolean is a class name, and as such, variables of type Boolean can be null; whereas boolean is a primitive.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
11

Booleans are rare in business & industry

In my experience building custom apps for business, an apparent duality such as "Female/Male" or "On/Off" nearly always evolve or morph into multiple values.

  • "Female/Male" becomes "Unknown/Female/Male"
  • "On/Off" becomes "On/WarmingUp/CoolingDown/Off"
  • "Incomplete/Completed" becomes "Incomplete/Processing/Completed"

Business rules are often not fully known early-on, or change over time.

Like many of my colleagues, I learned the hard way to never define such values as booleans. Changing from boolean to multiple values later is quite expensive and risky.

Java enums

Enums have other benefits over a boolean.

Java enums are flexible & powerful

The Enum facility in Java is much more flexible, powerful, and useful than enums in most other languages. See Oracle Tutorial.

Within your enum definition you can house representations of the values for presentation to the user and for storage in databases or files. This makes a handy one-stop-shop for a programmer to read all about this enum and how it used in your app.

Here is a complete example. This one class shows what values we use in the user-interface and what values we persist.

package com.basilbourque.example;

public enum Status {
    ACTIVE( "Active" , "active" ),
    INACTIVE( "Inactive" , "inactive" ),
    UNKNOWN( "Unknown" , "unknown" );

    private String displayName, codeName;

    Status ( String displayName , String codeName ) {
        this.displayName = displayName;
        this.codeName = codeName;
    }

    public String getDisplayName () { return this.displayName; }  // Or even add a `Locale` argument to support localization.

    public String getCodeName () { return this.codeName; }

    // To find a `Status` enum object matching input retrieved from a database.
    static public Status ofCodeName ( String codeName ) {
        // Loop each of the enum objects to find a match.
        for ( Status s : Status.values() ) {
            if ( s.getCodeName().equals( codeName ) ) { return s; }
        }
        throw new IllegalArgumentException( "No such Status code name as: " + codeName );
    }

    @Override
    public String toString() { return "app-status-" + this.getCodeName() ; }

}

Translating persisted values back to enum object

Notice the static method that can return a Status object matching a persisted value retrieved from a database:

Status s = Status.ofCodeName( myResultSet.getString( "code" ) ) ;

Flexible sets/maps

In Java, enums have their own implementation of Set and Map that are highly optimized both in terms of very little memory used and very fast execution.

Set< Status > auditApprovedStatuses = EnumSet.of( Status.ACTIVE , Status.INACTIVE ) ;  
Set< Status > auditAlertStatuses = EnumSet.of( Status.UNKNOWN ) ;

…

if( auditAlertStatuses.contains( application.getStatus() ) ) {
    this.alertAuditor( application ) ;
}

Notice how easy to update these set definitions if your definition of application-status changes.

Informative toString value

Whereas a boolean appears as true or false as a string, in your enum you can override toString to generate a much more informative value such as app-status-inactive.

Such values may be quite useful when logging, tracing, or debugging.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    Great to list other practical examples of duality used in business-contexts. Viewing the duality in relation to actions like `switchOn()` or `turnOff()` might help to express intent and state more precisely like `powerState = Power.ON` and results in self-explaining values that can even be persisted/represented without having a label - consider a simple print like "HAL9000 => OFF". In UI or data-science boolean flags require more effort when localizing or mapping because the interpretation of a simple true/false is now heavily depending on the field-name (maybe hard to translate or ambiguous). – hc_dev Nov 28 '22 at 22:53
5

Is it not possible to do both?

enum Status {
    ACTIVE(true), INACTIVE(false);
    private final boolean value;
    Status(boolean value) {
        this.value = value;
    }
    boolean getValue() {
        return this.value;
    }
}

Does this not get you the best of both worlds? It lets you use a boolean with the names ACTIVE and INACTIVE, rather than true and false?

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
3

If true/false are the only possibilities, boolean makes more sense than enum (less overhead). Recommendation: Use the Boolean class instead of the boolean primitive, so you can detect the "unknown/undefined" state as well as true/false.

aksarben
  • 41
  • 4
  • 3
    In this case, because the status cannot be null, `boolean` is preferable to `Boolean` since a `Boolean` accepts a null value which maps to a NULL column value in the table, but a `boolean` can never be null. – Derek Mahar Dec 02 '10 at 17:52
3

If you might ever have a need for more statuses other than Active and Inactive then you would want to use and enum or int status flag? That makes your code more flexible for future statuses.

Patrick Kafka
  • 9,795
  • 3
  • 29
  • 44
2

In your case having a boolean value should suffice. Since the requirement is 'IsActive' and the immediate answer can be either true or false. Having an enum is ok but IMO, a boolean is right suited

AlwaysAProgrammer
  • 2,927
  • 2
  • 31
  • 40
1

I think it is better to use Enum instead of Boolean.

The book

  • Joshua Bloch (2008): Effective Java: Still Effective After All These Years, Second Edition, Chapter 6: Enums and Annotations

lists following advantages of two-element enums over booleans:

  • Code is easier to read
  • Code is easier to write (especially with IDE)
  • Less need to consult documentation
  • Smaller probability of error
  • Much better for API evolution

Sourced from slides (PDF) - might be restricted: https://www.cs.umd.edu/class/fall2009/cmsc132H/slides/still-effective.pdf

alternatively archived but accessible at: https://web.archive.org/web/20120404070225/http://www.cs.umd.edu/class/fall2009/cmsc132H/slides/still-effective.pdf

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • 1
    **Enums have comprehension-advantages** - not only in natural language but also for automation - from the inner to the outside: like code readability, API documentation and discoverability (whether in IDE's suggestion during writing or web-client code generation). Furthermore to see where _boolean VS enum_ can evolve in REST API usage and design, see the examples given in [Why you shouldn’t use booleans in REST APIs | by Hany Elemary | Geek Culture | Medium](https://medium.com/geekculture/why-you-shouldnt-use-booleans-in-rest-apis-2747b187876c). – hc_dev Nov 29 '22 at 00:21
0

I prefer enumerators as I collaborate with remote team comprehending their code and then writing test cases at the dead of night containing boilerplate code I believe use of enum are way and way better than boolean not only it aids in good designs but also reduces cogitative load and increases readability.

Zahid Khan
  • 2,130
  • 2
  • 18
  • 31
0

If it seems arbitrary to choose between isX/hasX and isY/hasY for your boolean property, use an enum.

In your case a boolean should suffice (preferably isActive over isInactive).

Ronald C
  • 171
  • 6