Just append an update to an immutable data store, and program the logic to unfold from the latest records.
See Diatomic: https://docs.datomic.com/pro/getting-started/brief-overview....
Just append an update to an immutable data store, and program the logic to unfold from the latest records.
See Diatomic: https://docs.datomic.com/pro/getting-started/brief-overview....
Standard practice for accountancy is to record each transaction twice: once for the debited account and again for the credited account. You even create accounts for expenses and income; which are explicitly allowed to go negative (otherwise you couldn't record income). This is known as double-entry accounting, and it's equivalent to what you deride as "event sourcing".
To put it back into the language of databases, double-entry accounting is the third normal form of accounting. You wouldn't store a "sum total of blog posts on a website" row in your database schema now would you? Why would you have a "sum total of transactions" or single entries for your transactions that only show that money came in but not where it went?
The exact pedantry that you are making is kind of poorly chosen, in double-entry bookkeeping you would say that you record the transaction proper either once or n + 1 times, depending on how pedantic you are being. (Double-entry bookkeeping discovered the feature that in filesystems is called “journaling,” you always write first to the transaction log, which is the “1” if you answer 1, then you update the n account ledger pages involved in the transaction with their individual deltas plus the transaction log ID.) A real bank also allows accounts to go negative all the time, which is another criticism.
The “event sourcing” is actually just the transaction log, which is not double entry, which is why I say that the pedantry is poorly chosen. The ledger, in combination with “closing the books for the year,” actually instantiates a generic construction for persisting data structures, see lectures at [1], where you take periodic snapshots of a value to limit your worst-case reconstruction time while storing a tractable buffer of deltas. The point of the ledger thus is to denormalize the data to make it efficient to answer the question, “how did this client's balance change over time?” without seeking over the whole transaction log.
It can be as simple as a Postgres append only table keyed by an (id, version) tuple with a JSON column for the change event. You don’t need to pull in the whole enterprise pattern with aggregates, projections, etc to get the essence of event sourcing.
(P.s. personally I don’t believe in event sourcing at all. This is a great idea that just doesn’t seem to work in practice).
There’s a lot of machinery involved, and a subtle logic change or error could invalidate balances for your entire client base. The transactional approach, with event sourcing used as an audit utility used by humans to verify correctness, is often a better path.
Most of us are never going to work with a system with the scale and SLA to necessitate this approach, but it's an enjoyable interview nonetheless.
Edit: Ah, looks like I've struck a nerve with the event sourcing Datomic fanboys. Enjoy using your golden hammer and turning every problem into a nail!
By the way, if you ever make my way into my organization and waste my time with this nonsense, I WILL fire you. Nobody should tolerate your desire to solve already-solved problems with poorer quality solutions you have selected for their novelty. At that point, I'll kindly ask you to please explain to me what a write ahead log is and what it does, because if you don't, I'll happily explain it for you.