Hacker News new | ask | show | jobs
by taeric 844 days ago
A thing that so many enum solutions miss is that you have to have a path for a value outside of the current definition, or you lose a lot of flexibility in compatibility with any data that crosses wires or disks. Sounds fine for a lot of cases, of course, but in a world of mixed deployment fleets working on data, you pretty much have to have a way to allow a value that is not part of your current definition, or you are basically placing a "poison pill" on your system.
2 comments

I'm not bent out of shape about go enum's like the OP. However when it comes to writing and reading data over networks or disk io a naked enum was never going to work anyway, not really. Then you turn to protobuf etc so one has a cross os/arch/cpu interoperability
I don't disagree, I don't think. Just wanting to float a reason simpler enums are usually preferred. In particular, you likely want to use the enum to restrict what values you will introduce into a system. You often, sadly, cannot use them to restrict what values are actually there. Which is why the place you pass them will see the raw int.
Yeah, but then should structs ever have a bounded size? Someone might well have gone and done did added a couple of fields to a struct over the wire.
I think I touched on what I feel is the right answer here. The data is separate from the enum. That part is clear and I don't think anyone really disagrees.

What, then, is the enum for? It is specifically to restrict what your code will do. To that end, it is a good way to restrict data your code can introduce. It is not a restriction on what is happening outside of your code, though.

You can, of course, make similar arguments for structs. Or really any data in the code. How do you know your number won't go over some arbitrary size?

Enums are, largely, the most restrictive data in code. Which is why we discuss them more, I think. If folks did work with more big numbers, I'm sure we would be more curious on why things don't act like common lisp where big numbers basically work with no extra work.

>> Sounds fine for a lot of cases, of course, but in a world of mixed deployment fleets working on data, you pretty much have to have a way to allow a value that is not part of your current definition, or you are basically placing a "poison pill" on your system.

I had the joy of a numeric ID (an int) getting a B added to the end of it to distinguish the product as being the "same" but sourced from another vendor... (and vendor is part of the system so this is layers of silly, but useful on the floor if there is a problem).

This is the down side of "fleets" of applications with differing degrees of type safety working in concert.

Should an enum be fixed, and its change need to be reflected in every system? Cause current go out of the box isnt that. Should it be open ended as your suggesting ... because a "new int value" can flow through the system in an "Unsafe" way depending on the permissiveness or quality of your code.

I dont like any of the answers, but I candidly dont have a lot of problems with the current enum system in go. Is it great, no. But if your validating at your borders/boundries (storage, api, etc) and being responsible I dont really give it much thought.

I found this lesson out the hard way by finding that a new "status" had been added to our service and blew up some of our monitoring code. Since our monitoring code was still correct for the cases that they were checking for, and had default clauses to note things that were not relevant, we were crashing purely because I had coded it to convert the incoming value into a java enum. Oops...
well thank you for the example anyway :)