Hacker News new | ask | show | jobs
by DubiousPusher 1464 days ago
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.

2 comments

It also means that there is no way to guarantee that you have covered all possible values for the enum, whereas if an enum value was removed in your older example, you would get a compile error.
Covered in what sense? As in tested? I can easily open the data driven enum amd push all values through some switching code if desired.

To alert the user about removed values I have code which checks key values against the definition and errors on deleted values. Using tokenized enum values is convenient for the programmer but again I want to discourage it as it often blocks the non-coding designers on my team when they need to extend a component to handle more app states.

Compiler token checking is nice but IMO data driven behavior is nicer. We dont avoid the use of strings and ints or any other kind of data because they don't have a compile time tokenized representation.

Do you load this entire table into memory or do a db/cache lookup every time?
I load all the names at once. If this ever became a problem I'd segment them with bloom filters or something like that.

Note that in my applications the names are not known at runtime because comparing the guids is sufficient and these drop downs are not shown to the user but only the designer.

Were I employing this system in a more distributed fashion I might reconsider packing the names with guids understanding of them to be frozen after build.

I'm also considering a method to allow an engineer to limit the scope of key so that the designer is presented with a subset and not aall of the key options when setting the value.