Nel
precedente post abbiamo implementato il deposito, affrontiamo in
questo post l'aggiunta della funzionalità per prelevare denaro.
Prima
di procedere dobbiamo fare una premessa, il prelievo ha delle
analogie al deposito per l'interazione con l'operatore. Infatti dopo
l'esecuzione di richiesta di prelievo, l'oggetto Withdrawal notifica
all'operatore che vuole sapere qual è l'importo desiderato da
prelevare.
Ovviamente
il prelievo non potrà essere confermato se la richiesta è superiore
all'importo disponibile, questa problematica ci obbliga a realizzare
due tipologie diverse di notifiche.
Vediamo
come realizzare il tutto:
//
interfaccia per richiedere all'operatore l'importo
public
interface IWithdrawalInput
{
void
Return(string
value);
}
Withdrawal
deve rispettare il contratto con IOperation per fare parte della
liste di operazioni disponibile all'operatore, inoltre come per
Deposit interagisce con la View (IViewWithdrawal) tramite
IWithdrawalInput per richiedere l'importo da prelevare. Tramite la
notifica Return viene letto e trasformato da stringa ad Amount
l'importo che si vuole prelevare e inviato ad Account.
public
class
Withdrawal
: IOperation,
IWithdrawalInput,
IWithdrawalResponse
{
private
readonly
IAccount
account;
private
readonly
IViewWithdrawal
view;
public
Withdrawal(IAccount
account, IViewWithdrawal
view)
{
this.account
= account;
this.view
= view;
}
public
void
Display(Action<string>
action)
{
action("Prelievo");
}
public
void
Execute()
{
view.Response(string.Format("Inserire
importo da prelevare"));
view.Request(this);
}
void
IWithdrawalInput.Return(string
value)
{
decimal
amount;
if
(decimal.TryParse(value,
out
amount))
{
account.Withdrawal(new
Amount(amount),this);
return;
}
view.Response(string.Format("Importo
inserito non valido"));
Execute();
}
void
IWithdrawalResponse.Completed()
{
view.Response(string.Format("Prelievo
eseguito."));
}
void
IWithdrawalResponse.InsufficientCredit()
{
view.Response(string.Format("Importo
non disponibile."));
}
}
Vediamo
come View notifica l'importo da prelevare:
public
interface IViewWithdrawal
: IViewResponse
{
void
Request(IWithdrawalInput
withdrawal);
}
public
class View
: IViewOperation, IViewDeposit,
IViewWithdrawal
{
void
IViewResponse.Response(string
output)
{
Console.WriteLine(output);
}
void
IViewOperation.Request(IOperationsInput
operations)
{
operations.Return(Console.ReadLine());
}
void
IViewDeposit.Request(IDepositInput
deposit)
{
deposit.Return(Console.ReadLine());
}
void
IViewWithdrawal.Request(IWithdrawalInput
withdrawal)
{
withdrawal.Return(Console.ReadLine());
}
}
Vediamo
come Withdrawal collabora con Account.
public
interface IAccount
{
void
BalanceRequest(IBalanceResponse
balance);
void
Deposit(Amount
amount);
void
Withdrawal(Amount
amount, IWithdrawalResponse
withdrawal);
}
public
class
Account
: IAccount
{
private
Amount
current;
public
Account()
{
current
= new
Amount(0);
}
public
void
BalanceRequest(IBalanceResponse
balance)
{
balance.Return(current);
}
public
void
Deposit(Amount
amount)
{
current
= new
Amount(current.Value
+ amount.Value);
}
public
void
Withdrawal(Amount
amount, IWithdrawalResponse
withdrawal)
{
if
(current.Value >= amount.Value)
{
current
= new
Amount(current.Value
- amount.Value);
withdrawal.Completed();
return;
}
withdrawal.InsufficientCredit();
}
}
Quando
Account riceve la richiesta di prelievo, oltre l'importo vuole sapere
l'oggetto a cui notificare lo stato della richiesta:
//
contratto per notificare all'operatore se il prelievo
// è confermato o
se il credito non è sufficiente
public
interface IWithdrawalResponse
{
void
Completed();
void
InsufficientCredit();
}
Analizziamo
lo stack per vedere i due tipi di feedback, conseguenza della
richiesta di prelievo:
Caso
1: prelievo superiore al credito disponibile
Withdrawal.IWithdrawalResponse.CreditInsufficient()
Account.Withdrawal(Amount
amount, IWithdrawalResponse withdrawal)
Withdrawal.IWithdrawalInput.Return(string
value)
View.IViewWithdrawal.Request(IWithdrawalInput
withdrawal)
Withdrawal.Execute()
Operations.IOperationsInput.Return(string
value)
View.IViewOperations.Request(IOperationsInput
operations)
Operations.Display()
Caso
2: prelievo valido
Withdrawal.IWithdrawalResponse.Completed()
Account.Withdrawal(Amount
amount, IWithdrawalResponse withdrawal)
Withdrawal.IWithdrawalInput.Return(string
value)
View.IViewWithdrawal.Request(IWithdrawalInput
withdrawal)
Withdrawal.Execute()
Operations.IOperationsInput.Return(string
value)
View.IViewOperations.Request(IOperationsInput
operations)
Operations.Display()
Anche per lo sviluppo di Withdrawal abbiamo:
- tutti i metodi sono void
- abbiamo un if per gestire il parse da stringa ad amount
- abbiamo un if per verificare il prelievo richiesto
- solo un metodo ha due parametri
- abbiamo isolato le notifiche nello scope di competenza
- tutto il codice può essere messo sotto test
Nessun commento:
Posta un commento