Track
/
Roc
Roc
/
Esercizi
/
Conto bancario
Conto bancario

Conto bancario

Facile

Introduzione

Dopo anni passati a compilare moduli e ad aspettare, hai finalmente ottenuto la licenza bancaria. Questo significa che ora puoi aprire ufficialmente la tua banca, evviva!

La tua prima priorità è far funzionare i sistemi informatici. Dopo una giornata di duro lavoro, sai già aprire e chiudere conti, oltre a gestire prelievi e versamenti.

Siccome non avevi voglia di scrivere i test, inviti alcuni amici a dare una mano a collaudare il sistema. Però, dopo appena cinque minuti, uno dei tuoi amici sostiene di aver perso dei soldi! Anche se sei sicuro che il tuo codice sia privo di bug, inizi a spulciare i log per indagare.

Ah, già, proprio come sospettavi: la colpa è del tuo amico! Ha condiviso le sue credenziali di test con un altro amico, e insieme hanno cospirato per fare versamenti e prelievi dallo stesso conto in parallelo. Chi mai farebbe una cosa del genere?

Mentre sostieni che sia fisicamente impossibile accedere al proprio conto in parallelo, il tuo amico ti fa notare con aria di sufficienza che le regole bancarie ti impongono di supportarlo. Quindi niente supporto bancario in parallelo, niente via libera per il lancio. Sospirando, ti riprometti mentalmente di occupartene domani. Questo sposterà la data di lancio di almeno un altro giorno, ma vabbè...

Istruzioni

Il tuo compito è implementare conti bancari che supportino l'apertura e la chiusura, i prelievi e i depositi di denaro.

Poiché è possibile accedere ai conti bancari in molti modi diversi (internet, telefoni cellulari, addebiti automatici), il software bancario deve permettere di accedere ai conti in modo sicuro da più thread/processi (la terminologia dipende dal linguaggio di programmazione che usi) in parallelo. Ad esempio, possono verificarsi molti depositi e prelievi in parallelo; devi assicurarti che non ci siano race condition tra il momento in cui leggi il saldo del conto e quello in cui imposti il nuovo saldo.

Dovrebbe essere possibile chiudere un conto; le operazioni su un conto chiuso devono fallire.

Responsabilità di Roc e dell'host

Nel codice Roc di solito ci concentriamo sulla logica di business, mentre la piattaforma gestisce la concorrenza e lo stato condiviso. Quindi, in questo esercizio devi solo implementare le operazioni sul conto in BankAccount.roc, senza doverti preoccupare della concorrenza. I conti partono chiusi, una nuova apertura azzera il saldo, e i depositi e i prelievi devono essere positivi.

Demo opzionale del server

Il file bank-account-demo.roc incluso mostra come si può usare l'implementazione in un piccolo servizio web. Puoi leggerlo nell'editor, ma è indipendente dai test e non fa parte della soluzione.

Per eseguire la demo, devi installare Roc sulla tua macchina, installare l'Exercism CLI, e poi eseguire questo comando in un terminale:

exercism download --exercise=bank-account --track=roc

Poi implementa BankAccount.roc e provalo con il seguente comando (cambia il percorso di download stampato dalla CLI se è diverso dal percorso qui sotto):

cd ~/Exercism/roc/bank-account
roc test bank-account-test.roc

Quando tutti i test passano, puoi avviare il server della demo con il seguente comando:

roc bank-account-demo.roc

Il server usa la piattaforma basic-webserver e il suo supporto SQLite integrato (Roc scarica la piattaforma alla prima esecuzione). Non serve un server di database separato. Il server ascolta su http://127.0.0.1:8000 e crea bank-account-demo.db nella directory corrente (imposta DB_PATH per usare un file di database diverso). Ferma il server con Ctrl-C. I dati sopravvivono ai riavvii.

In un altro terminale, puoi chiamare il servizio web usando curl (su Windows, usa sempre curl.exe per evitare l'alias curl di PowerShell). Per esempio, ecco come aprire il conto #123, depositare 50, prelevare 10 e controllare il saldo:

curl -X POST http://127.0.0.1:8000/accounts/123/open
curl -X POST http://127.0.0.1:8000/accounts/123/deposit/50
curl -X POST http://127.0.0.1:8000/accounts/123/withdraw/10
curl http://127.0.0.1:8000/accounts/123/balance

Il saldo è 40. Gli ID dei conti e gli importi devono essere interi senza segno. Le operazioni di aggiornamento restituiscono OK in caso di successo o un errore dell'implementazione del conto in caso di fallimento. Per chiudere il conto #123:

curl -X POST http://127.0.0.1:8000/accounts/123/close

Per provare richieste concorrenti su Linux/macOS, usa un ID di conto nuovo e invia 100 depositi da otto client:

curl -X POST http://127.0.0.1:8000/accounts/456/open
seq 100 | xargs -P 8 -I '{}' curl --fail --silent --show-error -X POST http://127.0.0.1:8000/accounts/456/deposit/1
curl http://127.0.0.1:8000/accounts/456/balance

Su Windows, usa PowerShell 7+ per l'esempio in parallelo:

curl.exe -X POST http://127.0.0.1:8000/accounts/456/open
1..100 | ForEach-Object -Parallel { curl.exe --fail --silent --show-error -X POST http://127.0.0.1:8000/accounts/456/deposit/1 } -ThrottleLimit 8
curl.exe http://127.0.0.1:8000/accounts/456/balance

Tutti i depositi dovrebbero andare a buon fine e il saldo dovrebbe essere 100.

Come la demo gestisce la concorrenza

Ogni richiesta legge il conto, chiama le funzioni Roc e salva il risultato all'interno di una transazione Immediate di SQLite. Le operazioni fallite vengono annullate senza modificare il conto. SQLite consente un solo scrittore alla volta, il che impedisce alle richieste concorrenti di sovrascrivere gli aggiornamenti l'una dell'altra (anche tra conti diversi).

Nota: l'esercizio usa U64, ma la demo memorizza i saldi come interi SQLite e rifiuta gli aggiornamenti che superano il valore massimo di I64 (9223372036854775807).

Per un esempio di esecuzione di calcoli indipendenti in parallelo, prova l'esercizio Frequenza delle lettere in parallelo.

Suggerimenti

Mostra i suggerimenti

Usa match per distinguere Closed da Open(balance). Un'operazione restituisce un conto aggiornato invece di modificare il conto che le viene passato. Usa Ok(updated_account) per un aggiornamento riuscito e Err(...) per un'operazione rifiutata.

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Roc Exercism

Vuoi iniziare Conto bancario?

Iscriviti a Exercism per imparare e padroneggiare Roc con 135 esercizi e il mentoring di persone reali, tutto gratis.