Menu
Coddy logo textTech

Sistema bancario

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 106 di 107.

challenge icon

Sfida

Facile

Costruiamo un sistema bancario che gestisca conti, transazioni e operazioni finanziarie! Creerai un sistema robusto in cui l'integrità dei dati è fondamentale: i saldi dei conti dovrebbero cambiare solo tramite metodi convalidati e gli errori, come gli scoperti o gli importi non validi, devono essere gestiti correttamente.

Organizzerai il codice in cinque file:

  • account.go: Definisci un'interfaccia Transactable con i metodi Deposit(amount float64) error e Withdraw(amount float64) error. Poi crea due tipi di conto che implementano questa interfaccia:

    Un CheckingAccount con i campi non esportati id, holder e balance. I conti correnti consentono prelievi che portano il saldo esattamente a zero, ma non sotto.

    Un SavingsAccount con gli stessi campi non esportati, più un campo minBalance. I conti di risparmio devono mantenere un saldo minimo di 100.0: i prelievi che farebbero scendere il saldo sotto questa soglia devono essere rifiutati.

    Entrambi i tipi di conto richiedono costruttori (NewCheckingAccount e NewSavingsAccount) e un metodo getter Balance() float64. Per i depositi, rifiuta gli importi negativi o pari a zero. Per i prelievi, rifiuta gli importi negativi o pari a zero e quelli che superano i fondi disponibili.

  • transaction.go: Crea una struct Transaction per registrare l'attività dei conti. Ogni transazione ha un Type (string: "deposit" o "withdrawal"), un Amount (float64) e un AccountID (string). Includi un costruttore NewTransaction e un metodo String() string che restituisca il formato: [Type] $[Amount] on [AccountID], con l'importo formattato con due cifre decimali.
  • bank.go: Crea una struct Bank che gestisca più conti e registri le transazioni. Memorizza i conti in una mappa indicizzata per ID e conserva una slice di transazioni. Implementa:
    • NewBank() *Bank: inizializza raccolte vuote
    • AddAccount(id string, account Transactable): registra un conto
    • Deposit(accountID string, amount float64) error: effettua un deposito su un conto e registra la transazione in caso di successo
    • Withdraw(accountID string, amount float64) error: effettua un prelievo da un conto e registra la transazione in caso di successo
    • Transfer(fromID, toID string, amount float64) error: trasferisce denaro tra conti in modo atomico (se il prelievo riesce ma il deposito fallisce, annulla il prelievo)
    • GetBalance(accountID string) (float64, error): restituisce il saldo di un conto

    Restituisci gli errori appropriati per i conti inesistenti.

  • errors.go: Definisci errori sentinella per le operazioni bancarie:
    • ErrAccountNotFound: quando un ID conto non esiste
    • ErrInsufficientFunds: quando il prelievo supera il saldo disponibile
    • ErrInvalidAmount: quando l'importo del deposito o del prelievo è pari a zero o negativo
    • ErrMinBalanceRequired: quando un prelievo dal conto di risparmio violerebbe il saldo minimo
  • main.go: Crea una banca ed elabora le operazioni in base all'input.

    Leggi il numero di conti da creare. Per ciascun conto, leggi il tipo di conto (checking o savings), l'ID, il nome dell'intestatario e il saldo iniziale. Crea il tipo di conto appropriato e aggiungilo alla banca.

    Poi leggi il numero di operazioni. Ogni operazione è una tra:

    • deposit [accountID] [amount]
    • withdraw [accountID] [amount]
    • transfer [fromID] [toID] [amount]
    • balance [accountID]

    Per ogni operazione, stampa il risultato: OK per depositi, prelievi o trasferimenti riusciti, il saldo formattato con due cifre decimali per le richieste del saldo, oppure Error: [message] in caso di errore, usando i messaggi dei tuoi errori sentinella.

Verranno forniti i seguenti input:

  • Numero di conti, poi per ogni conto il tipo, l'ID, l'intestatario e il saldo iniziale (4 righe ciascuno)
  • Numero di operazioni, poi ogni operazione (1 riga ciascuna)

Per esempio, dato:

2
checking
ACC001
Alice
500.00
savings
ACC002
Bob
1000.00
6
deposit ACC001 200
balance ACC001
withdraw ACC002 950
withdraw ACC001 800
transfer ACC001 ACC002 100
balance ACC002

L'output dovrebbe essere:

OK
700.00
Error: minimum balance required
Error: insufficient funds
OK
1000.00

E dato:

1
checking
C100
Charlie
100.00
4
withdraw C100 100
balance C100
deposit C100 -50
withdraw C999 50

L'output dovrebbe essere:

OK
0.00
Error: invalid amount
Error: account not found

Nota come l'interfaccia Transactable consenta a Bank di lavorare uniformemente con entrambi i tipi di conto, mentre ogni tipo di conto applica le proprie regole. Il metodo Transfer dimostra le operazioni atomiche: se qualcosa va storto durante il processo, il sistema rimane coerente!

Provalo tu

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// Leggi il numero di conti
	scanner.Scan()
	numAccounts, _ := strconv.Atoi(scanner.Text())

	// Crea una nuova banca
	bank := NewBank()

	// Leggi e crea i conti
	for i := 0; i < numAccounts; i++ {
		scanner.Scan()
		accountType := scanner.Text()
		scanner.Scan()
		id := scanner.Text()
		scanner.Scan()
		holder := scanner.Text()
		scanner.Scan()
		balance, _ := strconv.ParseFloat(scanner.Text(), 64)

		// TODO: Crea il tipo di conto appropriato in base a accountType
		// e aggiungilo alla banca
		_ = accountType
		_ = id
		_ = holder
		_ = balance
	}

	// Leggi il numero di operazioni
	scanner.Scan()
	numOps, _ := strconv.Atoi(scanner.Text())

	// Elabora ogni operazione
	for i := 0; i < numOps; i++ {
		scanner.Scan()
		parts := strings.Fields(scanner.Text())
		operation := parts[0]

		// TODO: Gestisci ogni tipo di operazione:
		// - "deposit": deposita sul conto, stampa "OK" o un errore
		// - "withdraw": preleva dal conto, stampa "OK" o un errore
		// - "transfer": trasferisci tra conti, stampa "OK" o un errore
		// - "balance": ottieni e stampa il saldo formattato con 2 cifre decimali
		_ = operation
	}
}

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online