Using enum vs Boolean?
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?
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.
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.
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.
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.
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?
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.
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.
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
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
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.
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
).
精彩评论