for me the app that I’m building, a very simple slot machine app where there is which users can deposit money to buy credits, and use those credits to play teh slot machine, and withdrawl their earnings. That’s it.
I get that event sourcing makes sense here since we need a proof of all transactions and must be auditable by a regulatory body.
The immutability as a single source of truth I’m thinking of using datomic. However, it is not clear to me where CQRS/DDD would be needed if at all. I have trouble justifying increasing complexity of the project by using DDD instead of a single User table with credit/money balance columns.
Am I getting too ahead of myself by applying DDD using CQRS pattern? I’m not sure what would be the benefit of separating commands from query for a very simple slot machine game where it seemingly has very limited features (exchange money for credits, play game, withdraw winnings).
Definitely down the road, there might be some more added constraints depending on where the app is deployed. Some countries might have additional regulatory processes that needs to be added…
Why can’t I just build a CRUD app and record a log of everything that is happening? Why must I use ES/CQRS/DDD? Do I even need Datomic at all?
Just need some second opinions here.
a very simple
That would probably take DDD off the table. If you aren’t anticipating a rich and subtle domain model, then you are likely past the point of diminishing returns.
Why can’t I just build a CRUD app
If you are asking this question, it’s another hint that DDD may not be the right horse.
But taking it straight — the problem with a CRUD app is a single question: where does the business intelligence live? Who gets to decide which events are legal?
For example: you mentioned users withdrawing earnings. Presumably, you don’t want to allow the user to withdraw more than they have earned (the alternative sounds like a lousy business model, but maybe you can make it up on volume). So who decides?
If you have a domain model for the earnings withdrawal process, it’s easy — you just send a command to an entity that maintains the integrity of the account, and that entity rejects commands that break the rules. In a CRUD implementation… where does that logic live?
Another way of phrasing this is — where is the book of record? Is your app producing the events, or just consuming them?
(Pure consumers are actually a fairly common case. Warehouse inventory systems are the canonical example.)
If your slot machine app is the book of record, then you should probably have a domain model to protect your business. Using a history of events to rehydrate the state of your model has some nice benefits, so that’s a good option.
If you are using event sourcing, then you are paying a small penalty on your reads (event histories are not optimized for reading current state, after all), but one interface is simpler than two, so adopting that pattern is optional.
If you are anticipating a lot of contention, then being able to break your domain model into isolated parts could help your scaling quite a bit. On the other hand, if each slot machine app is dedicated to a single account, then it will be simpler to treat the entire domain as a single entity for the purpose of writes.
Horses for courses.