Live data from Hacker News

YAGRI: You are gonna read it

scottantipa.com

71–80 of 161 posts

Re: YAGRI: You are gonna read it

#71

These are not decisions that should be taken solely by whoever is programming the backend. They need to be surfaced to the product owner to decide. There may very well be reasons pieces of data should not be stored. And all of this adds complexity, more things to go wrong. If the product owner wants to start tracking every change and by who, that can completely change your database requirements. So have that conversa…

Some things are trivial and nearly free - created_at, updated_at. I don't think engineers need to bring trivialities like this to a "product owner". Own your craft.

Re: YAGRI: You are gonna read it

#72

These are not decisions that should be taken solely by whoever is programming the backend. They need to be surfaced to the product owner to decide. There may very well be reasons pieces of data should not be stored. And all of this adds complexity, more things to go wrong. If the product owner wants to start tracking every change and by who, that can completely change your database requirements. So have that conversa…

> And all of this adds complexity, more things to go wrong

That's a little vague given this specific example, which appears to be about maintaining some form of informative logging; though I don't think it necessarily needs to be in the form of an DB table.

Re: YAGRI: You are gonna read it

#73
post #41
post #4

One thing I do quite frequently which is related to this (and possibly is a pattern in rails) is to use times in place of Booleans. So is_deleted would contain a timestamp to represent the deleted_at time for example. This means you can store more information for a small marginal cost. It helps that rails will automatically let you use it as a Boolean and will interpret a timestamp as true.

I consider booleans a code smell. It's not a bug, but it's a suggestion that I'm considering something wrong. I will probably want to replace it with something more meaningful in the future. It might be an enum, a subclass, a timestamp, refactoring, or millions of other things, but the Boolean was probably the wrong thing to do even if I don't know it yet.

Tangential: I was recently wishing that bitwise flags had better support in Postgres. For now, bools are just easier to work with

Re: YAGRI: You are gonna read it

#74

Additionally, mutable fields will quite often benefit from having a separate edit table which records the old value, the new value, who changed it, and when. Your main table’s created and updated times can be a function of (or a complement to) the edit table. It is tempting to supernormalize everything into the relations object(id, type) and edit(time, actor_id, object_id, key, value) . This is getting dangerously an…

> This is getting dangerously and excitingly close to a graph database implemented in a relational database!

This feels like a great unresolved tension in database / backend design - or maybe I'm just not sophisticated enough to notice the solutions?

Is the solution event sourcing and using the relational database as a "read model" only? Is that where the truly sophisticated application developers are at? Is it really overkill for everybody not working in finance? Or is there just not a framework that's made it super easy yet?

Users demand flexible schemas - should we tell them no?

Re: YAGRI: You are gonna read it

#75
post #41
post #4

One thing I do quite frequently which is related to this (and possibly is a pattern in rails) is to use times in place of Booleans. So is_deleted would contain a timestamp to represent the deleted_at time for example. This means you can store more information for a small marginal cost. It helps that rails will automatically let you use it as a Boolean and will interpret a timestamp as true.

I consider booleans a code smell. It's not a bug, but it's a suggestion that I'm considering something wrong. I will probably want to replace it with something more meaningful in the future. It might be an enum, a subclass, a timestamp, refactoring, or millions of other things, but the Boolean was probably the wrong thing to do even if I don't know it yet.

The way I think about it: a boolean is usually an answer to a question about the state, not the state itself.

A light switch doesn't have an atomic state, it has a range of motion. The answer to the question "is the switch on?" is a boolean answer to a question whose input state is a range (e.g. is distance between contacts <= epsilon).

Re: YAGRI: You are gonna read it

#76
post #41

Earlier quoted context omitted.

I consider booleans a code smell. It's not a bug, but it's a suggestion that I'm considering something wrong. I will probably want to replace it with something more meaningful in the future. It might be an enum, a subclass, a timestamp, refactoring, or millions of other things, but the Boolean was probably the wrong thing to do even if I don't know it yet.

Booleans also force the true/false framing. E.g. a field called userCannotLoginWithoutOTP. Then in code "if not userCannotLoginWithoutOTP or otpPresent then..." Thus may seem easy until you have a few flags to combine and check. An enum called LoginRequirements with values Password, PasswordAndOTP is one less negation and easier to read.

For me enums win especially when you consider that you can get help from your environment every time you add/remove stuff. Some languages force you to deal with the changes (i.e. rust) or you could add linter rules for other languages. But you're more likely to catch a problem before it arises, rather than deal with ever increasing bool checks. Makes reasoning about states a lot easier.

Re: YAGRI: You are gonna read it

#77
While I like the YAGRI principle very much, I find that adding

- updated_at

- deleted_at (soft deletes)

- created_by etc

- permission used during CRUD

to every table is a solution weaker than having a separate audit log table.

I feel that mixing audit fields with transactional data in the same table is a violation of the separation of concerns principle.

In the proposed solution, updated_at only captures the last change only. A problem that a separate audit log table is not affected to.

Re: YAGRI: You are gonna read it

#78

Additionally, mutable fields will quite often benefit from having a separate edit table which records the old value, the new value, who changed it, and when. Your main table’s created and updated times can be a function of (or a complement to) the edit table. It is tempting to supernormalize everything into the relations object(id, type) and edit(time, actor_id, object_id, key, value) . This is getting dangerously an…

> supernormalize everything into the relations object(id, type) and edit(time, actor_id, object_id, key, value)

I frankly hate this sort of thing whenever I see it. Software engineers have a tendency to optimize for the wrong things.

Generic relations reduce the number of tables in the database. But who cares about the number of tables in the database? Are we paying per table? Optimize for the data model actually being understandable and consistently enforced (+ bonus points for ease of querying).

Re: YAGRI: You are gonna read it

#79

While I like the YAGRI principle very much, I find that adding - updated_at - deleted_at (soft deletes) - created_by etc - permission used during CRUD to every table is a solution weaker than having a separate audit log table. I feel that mixing audit fields with transactional data in the same table is a violation of the separation of concerns principle. In the proposed solution, updated_at only captures the last cha…

Event sourcing also works great. You don't need an audit log per se if you already track a history of all commands that introduced changes to your system.

Re: YAGRI: You are gonna read it

#80

Additionally, mutable fields will quite often benefit from having a separate edit table which records the old value, the new value, who changed it, and when. Your main table’s created and updated times can be a function of (or a complement to) the edit table. It is tempting to supernormalize everything into the relations object(id, type) and edit(time, actor_id, object_id, key, value) . This is getting dangerously an…

> Additionally, mutable fields will quite often benefit from having a separate edit table which records the old value, the new value, who changed it, and when.

Aren't you describing a non-functional approach to event sourcing? I mean, if the whole point of your system is to track events that caused changes, why isn't your system built around handling events that cause changes?

Post reply on HN