One could invent as many wrong mapping scenarios with enums too. The trap is not the boolean. The fact is that domain modeling is hard, and it becomes even harder if you want to avoid booleans.
Booleans get you an exponentially growing number of states. The failure mode of booleans is for some of those states to be nonsensical. The failure mode of enums [0] is having to enumerate out all of the valid states when that number of valid states is growing exponentially.
The real problem here is the same tension of typed vs untyped programs, applied to data constraints more specific than types. In an untyped language/database/etc, the expectation of isOpen could be updated to include an additional valid state of String("locked") as a third state - ugly but semantically correct (and of course now you have possible logic errors at every test of isLocked based on whether conditionals were properly created based on more than 2 boolean states (and possible how the language shortcuts "naked boolean" conditions)).
In an environment with the ability to express constraints on the data, the state (isOpen=true, isLocked=true) could be prohibited - a straightforward solution that requires some deliberate data modeling work.
[0] correctly used, as in the author's door example when pertaining to a door that automatically unlocks when going open->closed (which is actually relatively rare! so if this had been an instance of modeling the real world, I question whether it would have been actually correct!). Meanwhile the author's PremiumFeature example is really just using an enum to create a booleans in a different form, and doesn't actually support their thesis.
Yeah this feels like a “one way doors” problem. Designing your data models in a way that would cause a later refactor to be painful or impossible is probably the bigger trap.
The real problem here is the same tension of typed vs untyped programs, applied to data constraints more specific than types. In an untyped language/database/etc, the expectation of isOpen could be updated to include an additional valid state of String("locked") as a third state - ugly but semantically correct (and of course now you have possible logic errors at every test of isLocked based on whether conditionals were properly created based on more than 2 boolean states (and possible how the language shortcuts "naked boolean" conditions)).
In an environment with the ability to express constraints on the data, the state (isOpen=true, isLocked=true) could be prohibited - a straightforward solution that requires some deliberate data modeling work.
[0] correctly used, as in the author's door example when pertaining to a door that automatically unlocks when going open->closed (which is actually relatively rare! so if this had been an instance of modeling the real world, I question whether it would have been actually correct!). Meanwhile the author's PremiumFeature example is really just using an enum to create a booleans in a different form, and doesn't actually support their thesis.