33

I was reading some code here and saw that an enum is used to store names of html tags. Why do we ever need to do this? What benefit do I get using this strategy?

I know that how useful enums are in compiled or statically typed languages but when I see enums in dynamically typed languages I get curious, like the example code I showed above. So, the question basically boils down to why do we need enums in dynamically typed language or do we need them at all?

Alex
  • 1,213
  • 8
  • 22
CodeYogi
  • 2,156
  • 1
  • 18
  • 34
  • 38
    This question is basically _"Why do we need types"_. – user11153 May 09 '16 at 19:22
  • 1
    Did you search the repo to see how it's called? That would likely give you a better understanding of the answers you received. – RubberDuck May 09 '16 at 22:28
  • if you have: `enum People { YOU, NPC, FOO, BAR }` and a function that wants a (People)`int`, you can plug whatever, instead of using a number. – Evan Carslake May 09 '16 at 22:58
  • 3
    Are you asking about the purpose of this particular "enum" or about the purpose of enums in general, in any language? I'd assume the former, but all current answers seem to think the latter ... – meriton May 09 '16 at 23:06

5 Answers5

57

A benefit is that the compiler can let you know if you accidentally type "ADRESS" or "FEILDSET", and letting you fix it immediately instead of behaving in a nonsensical way at runtime.

While the benefit is much more useful in statically typed languages than dynamic, it is still useful even if it is a runtime error as you will get message indicating a problem with your case statement rather than your data.

whatsisname
  • 27,463
  • 14
  • 73
  • 93
  • 1
    Wouldn't typo-detection also be provided if we just use named constants? We don't have to use enums for that. – amon May 09 '16 at 16:38
  • 1
    Perfect makes sense, I was just thinking in terms of programming style only. Hopefully this is another benefit of using enums. – CodeYogi May 09 '16 at 16:39
  • @amon can you provide some example? – CodeYogi May 09 '16 at 16:39
  • 4
    @amon: you could, but enums gives you a handy mechanism to ensure you don't have collisions. – whatsisname May 09 '16 at 16:40
  • 76
    A place I used to work for once spent a month chasing a bug caused by someone's bright idea to use string constants instead of enums, poor editor fonts, and a field accidentally named `"PROF1LE_"` – Gort the Robot May 09 '16 at 17:03
  • 8
    @amon Go does exactly this. One nice thing about enums, however, is that the compiler can check that your switch statement has a case for every possible enum value. – weberc2 May 09 '16 at 20:00
  • 2
    @StevenBurnap - "Accidentally"? I don't buy it. The '1' key and the 'I' key are nowhere near each other on any keyboard layout I know of. That sounds like intentional sabotage to me. Had anyone recently been let go under less-than-favorable circumstances at the time? – Darrel Hoffman May 09 '16 at 20:28
  • 15
    This code was written in the 80s. You may not realize this, but this was in an era when some developers learned to develop on physical typewriters, which may not have had a [one key](http://www.daskeyboard.com/blog/why-did-old-typewriters-not-have-a-number-one-key/). Though actually I realize that the string in question was "Profi1e"...it's been twenty-five years, so my memory is obviously not perfect. – Gort the Robot May 09 '16 at 22:21
  • @amon: In some languages (for example, C#) enums also give you additional advantages like being able to iterate over the possible values. – GrandOpener May 09 '16 at 23:30
  • 4
    @DarrelHoffman: I'm surprised that you're surprised. In Perl, I frequently find myself typing `$1` when I mean `$i`. (Granted, I never type `f1le` instead of `file` -- the `$1` mistake is primed by the fact that `$1` is very common in Perl -- but still, mistakes of all sorts are common. Maybe the dev had a password with `prof1le` in it, thereby priming them to mistype `profile` in non-password contexts.) – ruakh May 09 '16 at 23:45
  • @StevenBurnap interesting that the problem didn't show up earlier if the code (and the name) is that old. – JDługosz May 10 '16 at 08:33
  • 3
    @JDługosz Code that works fine in the status quo can be [fragile](https://en.wikipedia.org/wiki/Software_brittleness) despite appearances. – Seldom 'Where's Monica' Needy May 10 '16 at 09:12
  • @JDługosz Also, he never stated when he found out about the bug, maybe it was a few days after someone caused it, who knows... – Kevin May 10 '16 at 14:19
  • @JDługosz Sorry, I didn't explain well. This was something that happened to me around 1990. – Gort the Robot May 13 '16 at 20:54
  • Another benefit is Refactoring. You can change the enum value name and it will be changed everywhere is used. If you use a String and you do a "Replace All ocurrences" you may cause errors. – GabrielBB Oct 08 '18 at 16:33
22

Enums are useful for situations where you have a fixed set of values/entities that are sensible. They are self-documenting and allow the compiler validate things that would otherwise be left to run-time. They should never be used if the set of meaningful values is not known or not strictly limited.

A more useful example would be something like HTTP response codes. Instead of having a method that takes a number and provides the name and/or description of the error, you can have a set of enums with meaningful names, a code and a description etc. in one clean package that is authoritative in what values are allowed and need to be handled.

JimmyJames
  • 24,682
  • 2
  • 50
  • 92
  • 1
    "Self-documenting" is the most important part. I'd much rather check if `status === GEOLOCATION_ACQUIRED` than `status === 3`, so that the person who maintains that software understands what's going on. As you said, it also prevents invalid values. – nicbou May 18 '16 at 08:55
11

Enums have nothing to do with OOP, and JavaScript doesn't have enums. Instead, enums are used whenever there is a choice between a fixed set of values. For example, a boolean is a choice between true and false, which could be implemented as enum Bool { False, True }. In a GUI library, we might have an enum for alignments: enum HAlignment { LEFT = -1, CENTER = 0, RIGHT = 1 }.

It is usually irrelevant how the enum is implemented, the important part is that each possible value is distinct. Many languages use integers for enums, though some like Java support arbitrary objects.

Until now, we could just as well have used constants, e.g. const int LEFT = -1, CENTER = 0, RIGHT = 1. However, a compiler knows that the enum values belong together. So when I switch over the enum values switch(value) {case LEFT: ...; case RIGHT: ...;}, the compiler can warn me that I have forgotten the CENTER case. This can be a substantial time saver. In languages without enums or without a switch-case construct, this can be simulated with the Visitor Pattern, though that is more helpful in the presence of static typing.

The other advantage is that enums can be treated as a separate type. E.g. I can declare that a method takes an HAlignment parameter, rather than any integer. The code will then fail to compile if I provide anything but one of the three possible HAlignment values. However, C's enums aren't well encapsulated and the enum constants can be used interchangeably with integers. Other languages are stricter here.

In JavaScript, we get none of these benefits. The given example declares an object that is treated as an enum. This does have some advantages for the programmer, e.g. it makes documentation easier, groups all the “constants” into a single object, …. However, it is just a convention that such an object is enum-like.

The point here is that HTML only has a finite and known set of tags. You can look at the HTML5 specification and put those element names as an enum into your code, and therefore make it more difficult to sneak a <blink> tag into your program. It is better to encode this knowledge in one place that to litter your code with special string literals (or worse, magic numbers).

amon
  • 132,749
  • 27
  • 279
  • 375
  • In that case if I pass `` to some method in javascript nothing could stop me right? but in `java` hello breaks loose :) – CodeYogi May 09 '16 at 17:13
  • @CodeYogi yes, because JS does not have a static type system, and in particular has no concept of enum types. However, I can document a method parameter as “takes a TagName”, which would lead a programmer to invoke it as `foo(TagName.STRONG)` which is a bit better. It would be even better if JS would complain if the field does not exist, but here we only get an `undefined` if I try `TagName.BLINK`. It's not worth much in JS, but it's a start. – amon May 09 '16 at 17:18
  • Hmm, the code link I mentioned above uses closure compiler hence makes sense there. – CodeYogi May 09 '16 at 17:24
  • Clojure is a functional language so I'm not sure how OOP is relevant to the question but that aside, it's important to distinguish between enums which are generally just a set of integers (not OO) and the 'Typesafe enum' pattern which is OO and what Java supports. – JimmyJames May 09 '16 at 17:31
  • @JimmyJames I'm talking about JS, not about Clo**j**ure (which, running on the Java platform, also supports OOP to some degree). The question was tagged with [tag:oop], which is why I mention it in the beginning. I don't really see how typesafe enums are connected to OOP, that's just a type system feature (many non-OOP languages have type systems :-) ) – amon May 09 '16 at 17:36
  • @amon I didn't notice this was tagged OOP. I don't think that is correct. I'm a little unsure about Clojure implementing OOP since it's a LISP but I haven't used it much so I'll not press the issue. The typesafe enum pattern existed prior to Java's support for enums: http://www.javacamp.org/designPattern/enum.html. Java enums are based on this pattern but add other enum features. Java enums are OO because they can be defined as fully-fledged objects with custom methods. Enums in many languages are simply values and all functionality needs to be defined elsewhere. – JimmyJames May 09 '16 at 17:55
  • @JimmyJames I am talking about `Closure`! I think you were in hurry to comment :) – CodeYogi May 10 '16 at 02:25
  • @JimmyJames What does Clojure being a Lisp have to do with implementing OOP or not? Common Lisp has the [Common Lisp Object System](https://en.wikipedia.org/wiki/Common_Lisp_Object_System)... – 8bittree May 10 '16 at 13:52
  • @8bittree From your link "CLOS is a powerful dynamic object system which **differs radically** from the OOP facilities found in more static languages such as C++ or Java." [emphasis mine] I concede that OO has many definitions but most people do not mean CLOS when they discuss OOP. – JimmyJames May 10 '16 at 14:07
  • @JimmyJames So is JavaScript not OO, then, since it's based on prototypes instead of classes like Java and C++? – 8bittree May 10 '16 at 14:20
  • @8bittree Again, there are many valid and distinct definitions of object-orientation. This imprecision goes all the way back to the origins of the term. It's unfortunate really as it can create a lot of confusion when parties from different backgrounds come together. In any event, Clojure doesn't support CLOS or any object system so it's a bit of a moot point. I apologize if I offended you. – JimmyJames May 10 '16 at 14:33
  • @JimmyJames No offense taken. I just was hoping to avoid spreading the false notion that Lisps in general are somehow inherently incompatible or poorly compatible with OOP. – 8bittree May 10 '16 at 15:39
3

Even if your language doesn't require compilation, you'll probably use some kind of IDE or development tools, that can give much better support for something like an enum than just for strings.

If you use an enum like object literal in javascript for example, your editor will give you code completion and your code checker like JSHint or JSLint will warn you, if you accidentally use the wrong value.

hansmaad
  • 221
  • 1
  • 3
  • I think a lot of the other responses either miss or beat around this point. Using an 'emum' in a dynamic language may not do anything for a compiler, but it can really help certain IDEs, documentation tools, and also don't forget humans who are attempting to understand the code. – Robert May 10 '16 at 18:19
2

The point of such enum might be to provide Js Api (goog) a set/bundle of allowed tags. Which ones? The ones defined by W3C HTML 4.01 (check out enum's documentation). So it's settings boundaries.

Might or might not be this the real goal, however it would works fine for such purpose.

If you know how Javascript works, what code is doing is defining an array indexed by strings :-). Which value is a string, but it could be any other component with attributes, functions, etc... Let your imagination run free and you will see benefits everywhere.

Javascript aside, I use enums a lot for modeling and managing state machines.

START > IN_PROGRESS > CONFIRMED > FINISHED > ...

In java switch allows enums so is quite easy to validate states into a state machine, to loop all over the enum, to define priorities by doing complexed enums, ...

I also use them to define typed and unmodoficable constants:

  • Yes, No

Also complex enums (which allows to do secure transforms/parsers)

  • Yes(1,true), No(0,false)

Due to enums often belongs to my model layer (core), its features are accessible to all over the system, so it becomes a functional model and I keep a low coupling.

What enums gives (among other things) is boundaries and typification

Laiv
  • 14,283
  • 1
  • 31
  • 69