1.1 KiB
1.1 KiB
Attempt is a separate aggregate holding a ledger
Playthrough and Attempt are separate aggregate roots rather than one root containing the other, and an
Attempt records a ledger — coins found, coins spent, skills bought — rather than just a purse of coins found.
Separate roots keeps each aggregate small and gives the Attempt its own lifecycle, since it is never persisted.
The ledger exists so that the rule "nothing survives an Attempt unless you complete the level" applies to
purchases too: under the previous model RemoveCoins drained session coins and then debited banked coins
immediately, so buying a skill mid-level and then dying lost both the coins and the skill.
Consequences
- Affordability is a cross-aggregate read (
attempt.CoinsFound + playthrough.Bank >= cost). Reads may cross scopes; writes may not. - Purchasing writes only the Attempt. The only operation touching both roots is Commit, which has exactly one call site.
- Discarding an Attempt undoes purchases rather than refunding them — under the ledger they never happened.