I have a mail_queue table that is written to by web requests then worked on by a worker to send the mails. I've now had a moment of enlightenment re. what I was not comfortable with in the design.
Before: One database table called mail_queue, which the worker processes, & adds a sent_at field when sent. That means to get messages to send, it has to do a select from where sent_at is null. To be parsimonious about database tables I don't really need another table, because a null sent_at can entirely well indicate a message still needs to be sent.
Yet, there was something I was not comfortable about having a queue that was not purged. What if the sent_at field got nulled by accident? I can't likely see this happening, but even so, I was uneasy with this design.
Reading up on queues a bit more I encountered the idea that some queues may be worked on by multiple types of process. I can see that what my worker could do is take the record off mail_queue, process it, and if successful, delete it from the queue, plus add pretty much the same record back to a new table mail_sent, along with the new field sent_at.
What is the justification for having an extra table, when the first method outlined above seems entirely ok in terms of being parsimonious with database representations?
The answer I've come upon is that I can now see that, say, I wanted to listen for incoming webhooks such as delivered, the process which receives that webhook no longer needs access to the mail_queue, just the mail_sent.
Is that a kind of "decomposition"? It seems to me it is. It's not about splitting up operations; rather about splitting up data storage based on usage; "decomposition by role" "by usage", "by access". Are those a thing?
Just being a bit discursive here, it helps a lot to write things down and I really appreciate the opportunity to share here and discuss.
(I was just watching a video by Rich Hickey talking about Clojure which got me thinking about decomposition :))