Supponiamo di avere un deposito stupido che memorizza numeri (per ragioni di questo esempio). È stupido perché può solo creare un nuovo record, aggiornare il record specificato ed elencare tutti i record esistenti - nessun'altra logica inclusa.
Ma voglio implementare una logica di business che mi consenta di memorizzare nuovi record in modo sicuro, sapendo che non memorizzerò un record duplicato. Inoltre voglio aggiornare i record esistenti sapendo che non porterà a duplicati.
Iniziamo con la creazione di nuovi record. L'approccio ingenuo mi dice che ho bisogno di due passaggi per aggiungere un record:
- (A) legge i record esistenti dal repository
- (B) controlla se i record esistenti contengono già lo stesso record di cui ho bisogno per memorizzare
- (C) se i record esistenti sono privi di duplicati - store record.
Funziona bene finché tutto viene eseguito in un singolo thread. Che ne dici di multi-threading?
Un altro approccio ingenuo mi dice che posso introdurre il blocco attorno ai passi A, B, C. Sono di nuovo al sicuro (ignoriamo tutte le considerazioni sulle prestazioni).
Ora consideriamo l'aggiornamento dei record. I passaggi sono simili alla creazione:
- (A) leggi tutti i record
- (B) controlla se si verificano duplicati dopo l'aggiornamento
- (C) se il controllo è a nostro favore - aggiorna il record.
Problemi con multi-threading di nuovo? Usa nuovamente il blocco.
Ma per quanto riguarda la situazione in cui un thread crea un record 200 mentre un altro thread aggiorna il record 100 a un valore di 200. Entrambi passano i loro controlli sui passaggi (B), entrambi eseguono i passaggi (C) ... e terminiamo con un duplicato.
Ci porta a concludere che l'intero design è sbagliato.
Ma qual è il design giusto?