Enum constants: UPPERCASE or CameCase?

The Kotlin Coding Conventions state:

For enum constants, it’s OK to use either uppercase underscore-separated names ( enum class Color { RED, GREEN } ) or regular camel-humps names starting with an uppercase letter, depending on the usage.

Why should the “usage” be relevant in this case? And in what case should the one or the other convention be more appropriate?

What do you prefer and why?

  • Color { RED, GREEN } or
  • Color { Red, Green }

From my point of view using all uppercase letters is a form of redundancy since there is already all required information available to the compiler and the tools (an enum constant is constant by the language definition). Using all uppercase letters is something like IService instead of Service or sName for a string variable name.

Scala doesn’t use all uppcase enum constants. Same with Rust

I wasn’t even aware that the coding convention allows for all caps. I always use the camel case starting with an uppercase letter.
IMO this it’s more consistent with the rest of the language. Enum constants are similar to objects inheriting from sealed classes. You would never name those with all caps.
But then based on the java coding convention you should name them with all caps since the instances of an enum are considered a constant. So maybe there are argument for both. Still I prefer camel case.

1 Like

On the one hand they are similar to singleton object declarations. On the other hand they are similar to const val declarations.

Depending on which is the more similar one in a given case, we could indeed argue for both conventions.

2 Likes

The uppercase convention came from Java, but I personally have fought against it for 20 years particularly when Sun did not even define what a constant was when it said they use upper case (See https://groups.google.com/d/topic/comp.lang.java.programmer/CE0llV5Lalk/discussion).

I have not found any reason why we need to make constant names harder to read to indicate that they are constants, when there is actually no reason to differentiate constants from any other values. The answer I always get is so that we know that they are constants, but why do we need to know they are constants?

4 Likes

Why is intellij showing var variables differently to val variables?

Because constants are easier to reason about. I spend less brain activity for reasoning about constants than I do for mutable variables.

We use UPPER_SNAKE_CASE in our Kotlin backend project at work provided that the enum is deeply immutable (which we always strive for with enums).

This aligns with the Kotlin convention where the const keyword is used since those are also deeply immutable.

This is also aligned with Java naming conventions so it reduces confusion in mixed codebases.

What do you think about the following clarification in the Coding Conventions instead of the sentence cited above?

Use uppercase underscore-separated names such as enum class Color { RED, LIGHT_GREEN } if you are writing code for a mixed Kotlin/Java project and use regular camel-humps names starting with an uppercase letter such as enum class Color { Red, LightGreen }, if the usage is primarily Kotlin.

That would avoid the vague and hardly helpful term “depending on the usage”.

I don’t believe that is the primary reason for allowing both conventions.

Maybe, but your comment shows that some clarification would be helpful. It would be nice if any of the others would explain us the reasoning.

I’m in favor of CamelCase, why?
Because classes and enums are written in camel case and they are likewise constants.

classes and enums are written in camel case and they are likewise constants.

But classes and enums are not values (constant or otherwise); they’re types. (Or type constructors, if generic.)

So if anything, that’s an argument for making constants different from those.

The real question is whether there is any good argument for treating constants in a special way. Based on my limited understanding this comes from languages like C/C++ with macros, where macros would be written in uppercase. In C this is important since you need to know which functions are macro functions and which aren’t. Since macros are also used to define constants in C this is where that originated (could be another language was first, but that is as far back as my background goes :wink:). Java just kept this standard without thinking why it was done in the first place.
I don’t care about what field in my program is constant and which isn’t (in java/kotlin). Yes it tells me a value can never change, but the opposite is not true for lower case fields, the might never change so no real information gained in most cases.

My question, is there any good reason for kotlin to keep to this old standard, other than Java compatibility(which isn’t good enough IMO)? I can’t think of one.

2 Likes

Why does Intellij render var identifiers differently to val identifiers?

It takes less effort to understand code if constants and variables are easily distinguishable.

But I don’t see the value of a constant in kotlin. They are mainly introduced to hardcode a few strings/ints and mathmatical constants. No one cares if they come from a special const val or just a val. It doesn’t change the way we use those properties or the way we read code. All it changes is how the compiler treats them. So I don’t agree on that part.
As for enum constants. You can already tell that they are constants, since they start with an uppercase letter. That means they are either singleton objects or enum constants. Also I would argue that in kotlin they are closer to objects in sealed classes than constants (because kotlin doesn’t really use constants in it’s design philosophy).
Also I don’t see anyone arguing that we should use uppercase for objects.

Because you can write to one, but not the other. Both can change, so it’s not that they are constant or anything. It’s just an information that you are allowed to modify this property.

Another point against special treatment for constants is this: Is there any difference in the usage of

const val serverVersion: Int = 2

and

val serverVersion: Int = loadServerVersion()     // executed at startup

Both are set once in the beginning and then never changed. Do you in your program care about the fact that one is “const” and the other isn’t?

1 Like

Because intellij shows in both cases that a val or const val is not writeable, I’d be ok with writing both in lowercase or camelcasr. However if I didn’t have an IDE, I’d argue for both to be written in uppercase. In fact back in my Java days on eclipse, I have often written final local variables in uppercase.

My first language was FORTRAN 66. No macros, no constants, no IDE, everything was all uppercase, variable names were limited to six characters. A man’s worth was the number of lines of bug-free code he could write in a day. :crazy_face:

1 Like

Independently of language/runtime support my view of a constant is something that has a value that is defined (conceptually) at source writing / compile time. As such it is something that you use as reference and is mostly the JVM constants, but in various cases an immutable object reference can also be a constant. (This kind of coincides with Java’s static final).

If a value is determined at startup time (or otherwise dynamically determined) it is not a constant even if it is immutable. In many ways the way I look at is goes back to the intent of the author, not the capabilities/limitations of the language used to express that intent.

As to capitalisation, that is a tricky one. Conceptually an enum constant/value is constant (although the enum itself doesn’t have to be immutable). There is however a narrower classification that often fits even better and that is object. For most intents and purposes an enum constant functions like an object. As a result I would come to the following rule:

  • If the enum provides/implements an interface it is an object -> capitalise like an object
  • If the enum is merely a list of possible values -> capitalise like an int constant.

Repeating arguments that have been given already is a sign that a thread has reached its peak information value. :grinning:

But classes and enums are not values (constant or otherwise); they’re types . (Or type constructors, if generic.)

But types are immutable entities even though they are not first class.