crazygringo
2 days ago
No. All of this is breaking the primary rule of programming: KISS (keep it simple, stupid). Don't add unnecessary complexity. Avoid premature optimization. Tons of things are correctly booleans and should stay that way.
Turning boolean database values into timestamps is a weird hack that wastes space. Why do you want to record when an email was verified, but not when any other fields that happen to be strings or numbers or blobs were changed? Either implement proper event logging or not, but don't do some weird hack where only booleans get fake-logged but nothing else does.
Should booleans turn into enums when a third mutually-exclusive state gets added? Yes, of course, so go refactor, easy. But don't start with an enum before you need it. The same way we don't start with floats rather than ints "just in case" we need fractional values later on.
Booleans are a cornerstone of programming and logic. They're great. I don't know where this "booleans are bad" idea came from, but it's the opposite of communicating intention clearly in code. That boolean should probably stay a boolean unless there's an actual reason to change it.
operator-name
2 days ago
I strongly disagree. Making invalid state unrepresentable is important.
> wastes space > premature optimisation
A timestamp is a witness of when the email was verified. Since if they’ve verified can be calculated from it, having both is not only redundant but allow invalid states to be represented.
Cases like email verified are often followed by the need to know when. Say an expiry system. Going from bools, you are faced with the hard choice of how to migrate existing state.
Databases also warrant more care as a source of persistent state - accessed by multiple versions of your software. If you don’t have this persistency, then it matters less.
> any other fields that happen to be strings or numbers or blobs were changed > implement proper event logging
Event logging is orthogonal to your database state. If your business logic needs dirty flags or timestamps they should be stored in the database, not queried.
And if you do need it for other fields, adding the bool is the perfect time to ask yourself if what you need is a timestamp.
> way we don't start with floats rather than ints "just in case" we need fractional values later on
Floats are a subset of int, and a natural migration. A bool can be calculated from a timestamp, but not the other way.
crazygringo
a day ago
> Cases like email verified are often followed by the need to know when.
And often not. That's the point. Avoid premature optimization. (FWIW, I've never encountered a system in my life where a successful email verification then expired after a period of time.)
> having both is not only redundant but allow invalid states to be represented.
That's a different topic. That's about what to do when you know you need the timestamp. The article is about using a timestamp when you don't have a timestamp requirement.
> they should be stored in the database, not queried.
I don't know what that means. Everything in the database is queried. And you can store your events in the database, in one or more event log tables.
> Floats are a subset of int, and a natural migration.
I think you meant to say the opposite, but even that's not true because of precision. And so too are enums a natural migration from booleans. That's the point -- start simple and extend as needed.
lock1
2 days ago
Disagree. Given the current popularity of dynamic languages and the fact that many people don't understand the value of ADT, newtype pattern, C-like enum even in static languages, I'd argue booleans & primitives are way overused.
I think a lot of people misunderstand KISS, believing everything should be primitives or surface-level simplicity. Instead, I interpret "simple" not something like golang's surface-level readability, but infosec's "principle of least privilege". Pick the option that minimizes possible state and capture the requirement logic, rather than primitives just because they're "simple" or "familiar".
Even then, sometimes it's fine to violate it. In this case, (nullable) date time might be more preferable than boolean for future-proofing purposes. It's trivial to optimize space by mapping date time to boolean, while it's a total pain to migrate from boolean to date time.
Also, doesn't "... a weird hack that wastes space" contradict "Avoid premature optimization"?
estimator7292
5 hours ago
> booleans & primitives are way overused.
> I think a lot of people misunderstand KISS
I agree, people do misunderstand simplicity.
crazygringo
a day ago
> Pick the option that minimizes possible state and capture the requirement logic
Which is what booleans do when the requirement is two states.
> Also, doesn't "... a weird hack that wastes space" contradict "Avoid premature optimization"?
No, because including the timestamp "just in case" is the premature optimization.
glxxyz
2 days ago
Yes the advice in TFA was brought to you by the sort of people who never finish anything because they're always wasting time thinking about potential future use cases that will never happen. Make it simple and extensible and make it satisfy today's requirements.
breadwinner
2 days ago
Disagree. KISS is for bigger things like architecture. Exposing an enum instead of a simple bool is a good idea that will save you time later. The only time to not do this is if you're exposing internal info, i.e., breaking encapsulation.
nostrademons
2 days ago
It saves you time until you realize that those status flags are orthogonal. It's very common for a job to be both is_started and is_queued, for example. And a simple is_failed status enum is problematic once you add retries, and can have a failed job enter the queue to be started again.
KISS, YAGNI, and then actually analyze your requirements to understand what the mature schema looks like. A boolean is the simplest thing that can possibly work, usually. Do that first and see how your requirements evolve, then build the database schema that reflects your actual requirements.
msgodel
2 days ago
Yeah it might be better to think of booleans as "the smallest possible integer type" and use enums (or whatever your language has) to represent more meaningful data.
Although it always depends on what exactly you're really doing.
scuderiaseb
2 days ago
Depends, if you're absolutely sure whatever you have has just two states. Then by all means, use a boolean. But booleans are harder to read than enum values and you're skipping that because of saving a few bytes on the DB?
This is not premature optimization, sometimes booleans can be extremely hard to change so it's not as easy as "just refactor".