DMD nel core iGaming
La piattaforma iGaming è un complesso sistema di dominio che si unisce alla finanza, all'intrattenimento e alla compliance. DDD aiuta a mantenere la complessità: evidenzia bounded contests, rileva ubiquitous language, protegge gli invarianti con aggregazioni, semplifica le integrazioni attraverso i livelli anticorruzione e rende trasparente il comportamento del sistema grazie agli eventi di dominio.
1) Mappa dei domini e bounded texts (design strategico)
Decomposizione consigliata:- Player/KYC Text - Registrazione, verifica, limiti di gioco responsabile, states KYC/AML.
- Wallet/Ledger Text - Bilanci, ridondanze, cavi, multivendita, corsi.
- Betting Text - Puntate/ticetti, coppia/esito, quotazioni, calcolo (settlement), annullamento.
- Casino/Game Round Text - sessioni, round, schiena, controllo RTP, limiti di puntata.
- Bonus/Promo Text - Le regole di bonus, vagare, equairing bonus, anti-abuse.
- Risk/Fraud Text è uno screening, segnali comportamentali, inneschi di blocco/timeout.
- Payments Text - Depositi/conclusioni, statuti delle passerelle di pagamento, aggregazione-eventi.
- Compliance/Reporting Text - Report ai regolatori, elenchi sanzionatori, verifiche.
- Content/Provider Integration Text - Integrazione con i provider di giochi, cataloghi, tecnologie. States.
- Analytics/Read Models - proiezioni e vetrine per le letture alimentari.
2) Ubiquitous language: un nucleo di termini
Player, Sessione, GameRound, Bet/Ticket,
Ledger Entry (Cablaggio), Hold/Reserve (Riserva), Settlement (Calcolo),
Bonus Credit / Bonus Balance, Wagering Requirement (Вейджер),
KYC Tier, Limit (deposito/sessione/perdita), Self-Execution,
Provider Game, RTP Window, Risk Flag, Compliance Case.
Questi nomi sono usati allo stesso modo in codice, database, documentazione, test e interfacce.
3) Unità e invarianti (design tattico)
3. 1 Wallet (Aggregate: `Wallet`)
Invarianti:- Il saldo non va meno.
- Riserva + saldo totale disponibile.
- Il cablaggio dell'atomanna e dell'idipotente ('operation _ id').
- `Wallet. Reserve(amount, reason, op_id)` → `WalletReserved`
- `Wallet. Commit(op_id)` → `WalletCommitted`
- `Wallet. Rollback(op_id)` → `WalletRolledBack`
Confine: Wallet non sa di Bet/Bonus; gestisce le operazioni di cablaggio e riserva.
3. 2 Bet/Ticket (Aggregate: `Bet`)
Invarianti:- La puntata può essere accettata solo nella finestra di quotazione attiva; l'importo del limite massimo del giocatore/sessione.
- Dopo «Settled» stato «finalizzato»; Il nuovo calcolo è consentito solo attraverso operazioni di compensazione (void/recalc) con un controllo chiaro.
- `Bet. Place(player_id, amount, price, op_id)` → `BetPlaced` (требует Wallet. Reserve)
- `Bet. Settle (outcome, payout) '→' BetSettled '(richiede Wallet. Commit/Release)
- `Bet. Void(reason)` → `BetVoided`
Confine: Bet non entra in Wallet - si rivolge attraverso i comandi di dominio/orchestra.
3. 3 GameRound (Aggregate: `Round`)
Invarianti:- Ogni spin/round ha un unico «round _ id» e un valore di puntata/vincita associato.
- La finestra RTP non supera le soglie specificate (livello provider + regole locali).
- `Round. Started`, `Round. Staked`, `Round. Resulted`, `Round. Closed`.
3. 4 Bonus (Aggregate: `BonusGrant`)
Invarianti:- Wager si riduce solo dal giro di valuta, il bonus non va in ritardo.
- Non è possibile cancellare il bonus e i fondi reali contemporaneamente non in base alla regola di priorità.
- `BonusGranted`, `BonusWagered`, `BonusExpired`, `BonusConverted`.
4) Orchestrazioni, saghe e coerenza
Sincronizzato (COP) - Accetta scommesse e riserva fondi - un unico percorso: 'Bet. Place` → `Wallet. Reserve (tramite comando di dominio/orchestratore con deadline).
Asincrono (CE) - Calcolo scommesse, bonus, analisi attraverso eventi + outbox.
La versione TCC è «TryReserve» (hold), «Confirm» (commit), «Cancel» (rollback) per gli effetti di cassa.
Idempotence: tutti i comandi portano «operation _ id», i concisters sono «inbox».
5) Livelli anti-corruzione (ACL) e integrazione
Provider ACL trasmette gli eventi di provider «SpinResult», «BonusWin» al Round interno. Resulted`, `BonusWagered`. Schemi e versioni sono all'interno dell'ACL.
PSP ACL: normalizzazione degli stati dei pagamenti, idemoticità per «psp _ tx _ id», traduzione in «LedgerEntry».
Compliance ACL - Integrazioni con elenchi di sanzioni/RER - in un contesto esterno; Solo i «ScreeningUpdated» normalizzati entrano nel dominio.
Regola: i dizionari/formati esterni non «filtrano» all'interno del nucleo.
6) Proiezioni e Read Models
Player Profile Read Model: stati KYC, limiti, bonus attivi, transazioni fresche.
Balances Read Model: letture veloci per UI/marketing; la sorgente è «Wallet» eventi.
Bet History Read Model: paginazione data/gioco la sorgente è «BetPlaced/Settled».
Compliance Reports - Rappresentazioni materializzate per tenante/regione.
Tutte le proiezioni sono upsert'idempotent'con versioning e 'as _ of/freshness'.
7) Multi-tenente e multi-regione
Tutte le entità chiave contengono «tenant _ id» e (se necessario) «region».
Limiti di dati: giocatore, portafoglio, scommesse - regione «domestica»; crocifissi solo aggregazioni/rapporti.
Fairness/quote - Limiti per comandi/s e redrave per tenanti.
Residency/compilation: i dati personali e i cavi non abbandonano la regione.
8) Selezione coerenza (PACELC) per contesto
Wallet/Ledger - Strong/COP - Cavi lineabili, quorum di record.
Bet acceptance - Conferma sincrona (COP) + Read Models veloci per l'UI.
Settlement/Bonus/Analytics - CE con determinati merge/compensi.
KYC/Compliance - Può essere un CE per gli stati, ma le regole «bloccanti» vengono applicate sincronicamente.
9) Eventi di dominio: contratti e versione
Set di campi minimo:json
{
"event_id": "uuid",
"event_type": "BetPlaced",
"occurred_at": "timestamp",
"tenant_id": "T123",
"aggregate_id": "BET-...-UUID",
"version": 7,
"payload": { "...domain fields..." },
"schema_version": "v3"
}
Regole:
- Diagrammi Back/forward-compat evoluzione attraverso «schema _ variante».
- outbox in una transazione con modifiche di dominio pubblicazione di batch con backoff.
10) Esempio di flusso Puntata con bonus (sequenza verbale)
1. `Bet. Il team controlla i limiti del giocatore e le regole del bonus «Wallet». Reserve(real+bonus_equiv, op_id)`
2. 'BetPlaced' (evento) → Read Model aggiorna «Aperture aperte»
3. Il provider pubblica il risultato dell'ACL Round. Resulted`
4. L'orchestratore conta: 'Bet. Settle(outcome,payout)` → `Wallet. Commit (op _ id) 'e, se vinta,' 'la possibile conversione del bonus in reale.
5. ' ', proiezioni di storia e bilanci, rapporti.
11) Invarianti e criteri di test
Invarianti chiave:- La somma di tutti i «LedgerEntry» del portafoglio è uguale al saldo; nessun residuo negativo.
- Non è possibile accettare una puntata se self-exclusion/stato KYC congelato attivo.
- Vager può solo diminuire e non andare in svantaggio.
- Settlement non cambia lo stato della puntata già finalizzata - solo tramite «Void/Recalc» + cablaggio compensativo.
- Test property-based invarianti portafoglio e scommesse.
- Tracciati di caos: ritardo del provider, guasti PSP, readbow outbox/DLQ.
- Controllo diagrammi: migrazione eventi, backfill proiezioni.
12) Telemetria e controllo
Metriche: p95/p99 per PlaceBet/Reserve/Commit, percentuale di guasti per limiti/CUS, DLQ rate, redrive success, lag proiezioni.
Tracing: span «komanda→agregat→outbox→konsyumer→proyektsiya», tag «tenant _ id», «operation _ id», «saga _ id».
Controllo: registro delle attività di dominio invariato, compatibile con i requisiti di regolazione.
13) Schema di storage (semplificato)
Wallet:
wallet(id, tenant_id, currency, balance, reserved, version)
ledger(id, wallet_id, amount, type, operation_id, occurred_at)
holds(id, wallet_id, amount, operation_id, expires_at, status)
Bet:
bet(id, tenant_id, player_id, amount, price, status, placed_at, settled_at, operation_id)
Bonus:
bonus_grant(id, tenant_id, player_id, amount, wager_left, status, expires_at)
La versioning su unità ('variante') protegge da lost update in caso di scrittura competitiva.
14) Esempio di comandi API (pseudo)
http
POST /bets. place
{
"tenant_id":"T1",
"player_id":"P42",
"amount":"10. 00",
"price":"2. 1",
"operation_id":"op-uuid",
"context":{"game_id":"g777","channel":"web"}
}
→ 202 Accepted + BetPlaced
POST /wallets. reserve
{ "wallet_id":"W1", "amount":"10. 00", "operation_id":"op-uuid", "reason":"bet" }
→ 200 { "reserved_balance":"..." }
Tutti i comandi sono «operation _ id» per l'idempotenza, le risposte sono «as _ of »/« variante».
15) Sicurezza e conformità
RLS/ACL: tutte le richieste sono nel contesto «tenant _ id», accesso ai ruoli.
Riduzioni PII: separazione degli eventi di dominio dai dati personali; maschera in DLQ/login.
Report regolatori: proiezioni con hash immutabili per le finestre del tempo.
16) Errori tipici
Connettività forte tra contesti (Wallet conosce direttamente Bet/Bonus).
Dual-write in contesti diversi senza saghe/outbox si allinea a bilanci e stati.
La mancanza di idampotenza dei comandi e dei concistream consente di recuperare i fili e i calcoli.
Utilizzo dei contratti di fornitore nel modello di dominio (più difficile da migrare).
Un aggregato «gigante» (Player include tutto) → di blocco, un throughput basso.
Non ci sono invarianti evidenti, non possono essere controllati o monitorati.
17) Ricette veloci
Avvia: fissa Ubiquitous Language e i bordi contestuali; Documentate gli invarianti.
Denaro: Wallet/Ledger - COP, registrazioni quorum, TCC per effetti esterni.
Scommesse: ricezione sincrona + calcolo asincrono, tutto attraverso eventi e outbox; Idipotenza ovunque.
Bonus: unità separata con una chiara priorità di prelievi e vager.
Integrazioni: sempre tramite ACL + schemi/versioni; niente «materie prime» payload nel nucleo.
Letture: proiezioni/vetrine sulle esigenze del prodotto; SLA freschezza + 'as _ of'.
Operazione: metriche di invarianti, DLQ/readbove playbook, rebuild vetrine.
18) Foglio di assegno prima della vendita
- Definiti bounded texts e i relativi contratti (comandi/eventi).
- Gli aggregati hanno espliciti invarianti, versioning e comandi idropotenti.
- Transazioni in denaro - tramite TSS/transazione rigorosa; controllo attivato.
- Integrazioni - tramite ACL con la versioning dei circuiti e test di evoluzione.
- Implementato outbox/inbox, DLQ e redrave sicuro.
- Le proiezioni realizzano SLA freschezza, ci sono metriche di lag/staleness.
- Quote/limiti multi-tenanti e data residency sono stati rispettati.
- Osservazione: tracking «komanda→sobytiye→proyektsiya», alert per invarianti.
- Documentazione: linguaggio di dominio, diagrammi di contesto, playbook di incidenti.
Conclusione
Il DDD del core iGaming è una disciplina di separazione della complessità: limiti chiari dei contesti, aggregazioni con invarianti, eventi come fonte di verità, ACL per le integrazioni esterne e scelte consapevoli di coerenza. Questo approccio rende la piattaforma scalabile, affidabile e regolamentata, accelera lo sviluppo di Fic e riduce i rischi operativi, anche con un rapido aumento del traffico, della geografia e della linea alimentare.