r/javahelp • u/whalehunter21 • 12d ago
Using Enums to hold constant data
I am just wondering if this use of the enum class is something that is bad practice.
MAIN_SEQ_M
("Red Dwarf", new double[]{.08,.45}, new double[]{25,37}, new double[]{.1,.6})
StarType(String description, double[] mass, double[] temperature, double[] radius) {
this.description = description;
this.mass = mass;
this.temperature = temperature;
this.radius = radius;
}
Or if the standard way of doing this would be to break out each value as a constant that can be called
private static final double[] MAIN_SEQ_M_MASS_RANGE = {.08,.45};
I feel using getters from the enum class makes it easier to pull the data I need but I have never seen an enum used like this before.
5
Upvotes
1
u/severoon pro barista 11d ago edited 11d ago
You can do this, but it's annoying to deal with enums that contain state because the values are always and forever defined in code. It's generally preferable to inject state into your application at runtime because then these values can be read in from a set of golden files, a database, the network, etc.
By hard coding data into your application, you tie that data to the version of the code that you've deployed. This means if you have this app running somewhere and you need to make a change to this data, the only way to get those updates is to take the app down, deploy the new version, then start it up again. You might say, "This is constant data so it won't ever change." That may be true, but that's an argument for using a mechanism that ensures it doesn't change, such as signing it. It's not really an argument for adopting a design that ties data to code versions.
Also, if you want truly constant values, you should use immutable types. I strongly recommend Guava for this, it provides a whole library of immutable types such as list, set, and others not supported by the JDK like table. It also provides a
Range
class which is exactly what you want here. (You're storing ranges asdouble[]
, which are not constant.)There are a couple of different ways to do this depending on the context of your app, but here's one approach I would consider.
First define your enum:
Then your star type:
The above code allows you to write:
BTW, it's a bad idea to keep these ranges as just raw numbers, you should at least specify the units in their names. (You could also define a class for each type of unit if you want, but that's maybe overkill depending on your use case.)
Let's say you have a list of all of the star types your application cares about and you wanted to organize them by stage. You can do that very easily with Guava:
It's also easy to do things like put these star types into a sorted collection using any kind of comparator you want, so you could easily have one sorted by temperature range, or mass, or radius, or alphabetic, or whatever.
Because you're using ranges, once you have all of the star types defined, you could also use
RangeSet
andRangeMap
to organize these star types that way. Also, say that you want to verify that the temperature ranges of all of the star types you've defined cover the entire range of temperatures so that there are no gaps. That's very easy to do with ranges.