giovedì 24 gennaio 2013

Extreme Design: una piccola provocazione (3° parte)

Proviamo ad implementare la richiesta di deposito.

Dobbiamo sempre implementare l'interfaccia IOperation per poter interagire con IOperations. Notate che Deposit rispetto a Balance notifica le sue richieste non Direttamente a IView ma all'interfaccia IViewDeposit

   public interface IViewDeposit : IViewResponse
   {
      void Request(IDepositInput deposit);
   }

Questo avviene tramite la notifica Request che invia l'oggetto che richiede l'importo da depositare all'operatore, infatti Deposit passa se stesso a IViewDeposit.

Quando l'operatore inserisce l'importo Deposit riceve tramite la notifica IDepositInput.Return il valore da verificare prima di richiedere ad Account di depositare l'importo richiesto.

   public interface IDepositInput
   {
      void Return(string value);
   }

   public class Deposit : IOperation, IDepositInput
   {
      private readonly IAccount account;
      private readonly IViewDeposit view;

      public Deposit(IAccount account, IViewDeposit view)
      {
         this.account = account;
         this.view = view;
      }

      public void Display(Action<string> action)
      {
         action("Deposito");
      }

      public void Execute()
      {
         view.Response(string.Format("Inserire importo da depositare"));
         view.Request(this);
      }

      void IDepositInput.Return(string value)
      {
         decimal amount;
         if (decimal.TryParse(value, out amount))
         {
            account.Deposit(new Amount(amount));
            return;
         }
         view.Response(string.Format("Importo inserito non valido"));
         Execute();
      }
   }

Vediamo come aggiornare l'oggetto View per gestire questa nuova funzionalità:

   public class ViewIViewOperations, IViewDeposit
   {
      void IViewResponse.Response(string output)
      {
         Console.WriteLine(output);
      }

      void  IViewOperations.Request(IOperationsInput operations)
      {
         operations.Return(Console.ReadLine());
      }

      void IViewDeposit.Request(IDepositInput deposit)
      {
         deposit.Return(Console.ReadLine());
      }
   }

Analizziamo lo stack per capire il flusso delle richieste e notifiche:

   Account.Deposit(Amount amount)
   Deposit.IDepositInput.Return(string value)
   View.IViewDeposit.Request(IDepositInput deposit)
   Deposit.Execute()
   Operations.IOperationsInput.Return(string value)
   View.IViewOperations.Request(IOperationsInput operations)

Notate che:
  • tutti i metodi sono void
  • l'aggiunta delle nuove funzionalità non ha coinvolto il codice esistente, sono state solo aggiunte le parti per gestire la nuova funzionalità; Implica che tutti i test continuano a funzionare
  • le interazioni tra gli oggetti sono isolati nell'ambito di appartenenza, non è possibile chiamare implicitamente un metodo che non è attinente all'area di esecuzione
Aggiorniamo anche Account per gestire la richiesta di deposito:

   public interface IAccount
   {
      void BalanceRequest(IBalanceResponse balance);
      void Deposit(Amount amount);
   }

   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);
      }
   }

Note: l'unico if inserito è per il parse della stringa ad intero.

Nessun commento:

Posta un commento