I’m not a very experienced programmer, but the first example immediately strikes me as weird. The consideration for choosing types is often to communicate intend to others (and your future self). I think that’s also why code is often broken up into functions, even if the logic does not need to be modular / repeatable: the function signature kind of “summarizes” that bit of code.

Making a boolean a datetime, just in case you ever want to use the data, is not the kind of pattern that makes your code clearer in my opinion. The fact that you only save a binary true/false value tells the person looking at the code a ton about what the program currently is meant to do.

I actually completely agree with both the article and your point that your code should directly communicate your intent.

The angle I'd approach it from is this: recording whether an email is verified as a boolean is actually misguided - that is, the intent is wrong.

The actual things of interest are the email entity and the verification event. If you record both, 'is_verified' is trivial to derive.

However, consider if you now must implement the rule that "emails are verified only if a verification took place within the last 6 months." Recording verifications as events handles this trivially, whilst this doesn't work with booleans.

Some other examples - what is the rate of verifications per unit of time? How many verification emails do we have to send out?

Flipping a boolean when the first of these events occurs without storing the event itself works in special cases, but not in general. Storing a boolean is overly rigid, throws away the underlying information of interest, and overloads the model with unrelated fields (imagine storing say 7 or 8 different kinds of events linked to some model).

> that is, the intent is wrong. The actual things of interest are the email entity and the verification event.

Or, your assumption about the intent is wrong. Many (most?) times, the intent is precisely whether an email is verified. That's all. And that's OK if that's all the project needs.

> Storing a boolean is overly rigid, throws away the underlying information of interest, and overloads the model with unrelated fields

Also, storing a boolean can most accurately reflect intent, avoid hoarding unnecessary and unneeded information, and maximize the model's conceptual clarity.

In the case of a database you often can't fix mistakes so overdesign just in case makes sense. Many have been burned.

Probably even more have been burned by overdesign.

If you decided to make your boolean a timestamp, and now realize you need a field with 3 states, now what?

If you'd kept your boolean, you could convert the field from BOOL to TINYINT without changing any data. [0, 1] becomes [0, 1, 2] easily.

While I agree on the over-design point, it doesn't follow that the BOOL is trivially convertible to a TINYINT. In some databases a BOOL is stored as a single bit.

[deleted]

See always having a synthetic primary key

Normally you'd name the field `created_at`, `updated_at`, or similar which I think makes it very clear.

> Making a boolean a datetime, just in case you ever want to use the data, is not the kind of pattern that makes your code clearer in my opinion.

I don't follow at all, if your field is named as when a thing happened (`_at` suffix) then that seems very clear. Also, even if you never expose this via UI it can be a godsend for debugging "Oh, it was updated on XXXX-XX-XX, that's when we had Y bug or that's why Z service was having an issue".

The author doesn't consider the nuanced trade-offs of where, what kind, and how much data to persist, compute, and where to store it, whether in the database or modeled in code. It's a quite superficial article bordering on meaninglessness that doesn't expound on the considerations of thoughtful engineering for the stakeholders: swe maintenance, operations, and business/user needs. It should lead into asking questions rather than present "the" answer.