4 ms·
I have often found that multiple booleans are better than enums. processed: true confirmed: false in progress: false pending: false reserve
by ralusek 6y ago
I have often found that multiple booleans are better than enums.
processed: true
confirmed: false
in progress: false
pending: false
reserved: true
It lets you capture more complicated state, such as above where this was processed but never confirmed, but still resulted in a reservation. Maybe you have an admin portal that lets you create reservations without going through the confirmation process, and now the data can capture the difference.
But my actual preferred variant, if the tech stack can support it, is to have things like `confirmations` have their own tables, so you can have a `confirmedByUserId` as well as a confirmation timestamp.
That way you can instead have something like
computed_processed: boolean(has a related entry in processed table)
computed_confirmed: boolean(has a related entry in confirmation table)
etc
- tshaddox 6y agoThe most obvious problem with that is that it allows representing impossible states, like in_progress and processed both being true.
- machello13 6y agoYep. This is basic data model design.
- ralusek 6y agoCorrect, it is basic data model design in that it is only for handling basic data models. When you are dealing with complicated data models with many contingencies, you aren't always able to have a data model incapable of representing invalid states. Sometimes it's necessary to rely on application logic/stored procedures/index constraints, etc, in order to enforce valid state.
- ralusek 6y agoIt's a tradeoff. If you have an explicit finite state machine in which your model can only ever be in one state, then obviously an enum has its benefits. In order to avoid impossible states, I'll rely on something like hooks or triggers to make sure that setting one value also updates all dependent values. In other words, setting processed to true will trigger something which always sets in_progress and pending to false. It's not at all uncommon that I will have chosen an enum for a situation in which I thought I was dealing with a finite state machine, only to unearth new domain contingencies that made me realize that I actually need a more nuanced and flexible model. This is why I prefer booleans, particularly the computed/derived booleans when possible (as I mentioned in my original comment). I'd rather have a model capable of capturing the actual complexity of the state than trying to force a finite state machine that might result in a loss of information, even if that means that I'm forced to rely on declarative hooks/triggers to ensure data integrity.
- anaerobicover 6y agoThis is feasible if your program is the only one ever reading (let alone writing) the data. When you add a separate frontend and stringly-typed back-and-forth communication (JSON), it becomes a huge headache for whichever platform(s) are not the gatekeeper of the data. They have to a) depend on your rules being modelled in a translatable way, and b) find a rational user experience for handling the inevitable inconsistencies.
- dragonwriter 6y ago> stringly-typed back-and-forth communication (JSON) JSON, while it has a very limited set of built-in types and (outside of add-ons like JSON-schema) no type definition mechanism, isn’t “stringly-typed”.
- ralusek 6y agoIf you have multiple applications accessing a database, you can have data integrity maintained using something like triggers in the actual DB, as well as constraints.