Live data from Hacker News

Ask HN: Do You Use Enum for Yes, No, Unset?

news.ycombinator.com

21–30 of 43 posts

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#21
TypeScript is nice because its null type is explicit. So if a type claims to be bool, it is really bool (either true or false, nothing else).

For a nullable variable of type T (including boolean), the type must be explicit about it:

    let choice: T | null;
Another nice alternative is an Option type, like Rust has. I think it would be something like Option.

But those (a null, or a None, respectively) would be only choices if internally, at the code level, the Unset case must be handled as some kind of extraordinary scenario. If it was possible for users to make a conscious decision to leave it unset, i.e. if Unset is part of the valid choices offered by the user-facing API, then I'd encode it as a proper possible state, in an enum.

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#23
I'd probably avoid using NULL in DB to convey a borderline-value for the simple reason that NULL has weird semantics in SQL and it can be pretty confusing.

If you're not using NULLs in DB, it's weird to translate an enum into a nullable Boolean.

In the end, there is very little downside to using enums in this case. It's by far the least confusing option.

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#24
post #7

I use integer surrogate keys everywhere. So 1 yes, 2 no, 3 unset, 4 yes but no every other Friday, 5 use this option for customer x, 6 no with notes, 7 zebra, 8...

With some 4.2 billion integers to choose from, you can pretty much put everything in one enum. Genius!

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#25
I use the convention that an 'null' value is a value that was not explicitly set by the user.

So in C#, I would always use a nullable boolean in this case (choices yes and no). If the field is a required value, I would annotate the field as such.

When using the field in an ORM, the required annotation would lead to a not-null field in the database.

When using the field in a dto, the required annotation could be used for validation of incoming input.

If the user should have the choice "yes", "no", "unknown", I would use a nullable enum to express this. An 'null' value means that the value was not explicitly set. The enum value "unknown" indicates that the user explicitly chose the "unknown" value.

So, in both cases the 'null' is not a separate state, it simply indicates that no explicit value was given to the field.

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#26
I work in a slightly different context but have dealt with a similar problem. I build Unity3D apps and I write a lot UI for the editor that affects how things are serialized. I've stopped serializing enums due to being burned too many times. When people:

-Add entries not at the bottom -Rename entries -Remove entries -Rearrange entries

So instead I made a kind of data-driven enum that you create through the editor. Each entry (called a key) in the "enum" is backed by a guid. You can associate a name with each key.

When you want to save info like on/off/unset. You create an enum. Then you declare a key in your data model. The UI will then show that key as a drop-down with the mapped names as the choices. But in the end, the associated guid is what is recorded.

Not only does this largely solve the, add, rename, re-arrange problems, it solves some other persistent issues as well. I've gotten designers to pickup this tool so they stop using ints and string to signal events. This way, they define their signal once as a data-driven enum and then they see it as a choice throughout the app rather than as something they have to type in matching.

It also causes engineers to write components which are more configurable for designers. Instead of checking a literal token like:

if (currentEvent.appState == MyAppStateEnum.Start) doSomething()

They declare the Key and check its value: public Key appPhaseToDoSomething;

if (currentEvent.appState == appPhaseToDoSomething) doSomething()

Since appPhaseToDoSomething is exposed as a dropdown in the editor, it means a designer can change the phase when something might happen without an engineer. And engineers basically have to write in this modular way because there's no token to check.

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#27
post #11

Yes, I'd have an enum with Yes, No and Unset. Many languages have a typed "no value" value that is composable with other types: Maybe , Option , Nullable . In other situations I might have an Option , i.e. when I want a non-null value to indicate that it isn't Yes or No. The reason why I don't want a null, in general, is that it's the billion dollar mistake: https://hackernoon.com/null-the-billion-dollar-mistake-8t5z…

When the final record should have either Yes or No, but the there is an intermediate state where the answer could be missing, you want something like a Maybe which you can map to a simple Bool as part of validation. Ideally you'd use a functor-style parameter for this, for example in Haskell:

  data Record f = Record { …, someField ∷ f Bool, … }
  type PartialRecord = Record Maybe
  type CompleteRecord = Record Identity

  getCompletedRecord ∷ PartialRecord → Maybe CompleteRecord
  getCompletedRecord (Record { …, someField, … }) =
    Record  …  (Identity  someField)  …
This way you can define your record type once and handle all the missing fields in a uniform way, and functions can easily indicate whether they expect a partial record full of Maybes or a complete record with no potentially missing fields. You can use the same type definition for other things, too, by substituting different functors in place of Maybe or Identity. For example, `Record ToString` where `ToString a` is a newtype over `(a → String)` could be a record of functions describing how to render each field as a string.

In the DB you would need to store incomplete records in a separate table, since they have different validation rules. Queries against the main table should be able to assume that all the records are complete.

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#28
post #21

TypeScript is nice because its null type is explicit. So if a type claims to be bool, it is really bool (either true or false, nothing else). For a nullable variable of type T (including boolean), the type must be explicit about it: let choice: T | null; Another nice alternative is an Option type, like Rust has. I think it would be something like Option . But those (a null, or a None, respectively) would be only choi…

And it's terrible because there's both `null` and `undefined` which have largely the same meaning but aren't equal. Depending on what you're interacting with, you may need to use one over the other or coerce. Especially common with developers from other languages who don't even know of the gotcha

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#29
In the code, it's considered something of a smell to use a bool at all. Look up "Boolean blindness". Basically instead of a bool field saying whether the person wants the deluxe upgrade, you'd have an enum whose values are Regular | Deluxe. How you would represent that in a db would depend on how your implementation works.

Re: Ask HN: Do You Use Enum for Yes, No, Unset?

#30

Earlier quoted context omitted.

You need a third state to know that user has not made a choice. If you don't want to make a choice for the user, for instance, you don't want to default to F or T, then third state tells exactly that user has to make a choice.

Agreed. Sorry if I wasn't clear, but I consider that to fall into the "value is really nullable and you are using the presence of null to decide anything..." scenario, in which case, this is important to the domain, so explicitly model it so the next dev doesn't trip over the special meaning of null in this case. Again, personal judgment and aesthetics, probably.

If it isn’t selected, the browser literally won’t send anything for that field (undefined in js parlance). Your code/language of choice has to make a decision on what to do with that state. If you specify true/false, the page will reload with that state instead of “undefined.”

For some languages it is exactly as you describe, for lower level languages (as in closer to the raw HTTP protocol) like PHP, you have to make an explicit choice before rendering the response.

Post reply on HN