working in progress: SharePoint 2010, Visual Studio 2010, ASP.NET, WPF, Scrum, Patterns, TDD, Refactorin To Pattern

0510/09 0

Long Method: Replace Conditional Dispatcher with Command

Continuiamo con lo smell: Long Method

   

Problema:

Logiche condizionali vengono usate per le richieste di dispaccio e per eseguire azioni.

Un esempio di logica errata:

Code Snippet
  1.             if (ac.Name.Equals("ATTACCO"))
  2.                 // ...
  3.             else if (ac.Name.Equals("DIFESA"))
  4.                 // ...
  5.             else if (ac.Name.Equals("BERSERK"))
  6.                 // ...
  7.             else if (ac.Name.Equals("GUARDINGO"))
  8.                 // ...

 
Motivazione:

Molti sistemi ricevono, instradano e lavorano con richieste.
Un conditional-dispatcher è un grosso blocco condizionale (if-else o switch) che si occupa di fare il gestire i messaggi ricevuti.

Le due maggiori motivazioni al refactoring di un conditional-dispatcher con una soluzione basata sul pattern Command sono:

  1. Poca flessibilità a runtime
  2. Uno conditional-dispatcher enorme

Il pattern Command rappresenta un’ottima soluzione per rispondere alla motivazioni precedenti.
Il pattern crea una differenza tra il client e gli oggetti che eseguono le operazioni. Questo pattern è estremamente versatile, supporta:

  • Spedire le request a differenti destinatari
  • Queue, logging e richieste da fiutare
  • Transazioni ad alto livello da operazioni primitive
  • Funzionalità di Redo e Undo

Tenendo conto della regola tenere tutto semplice si potrebbe storcere il naso sull’applicazione di questo pattern come soluzione al nostro problema.
Qual’ora il conditional-dispatcher dovrebbe diventare corposo bisogna ricordare che il pattern Command è facile da implementare, versatile e incredibilmente utile.

Soluzione:

Ecco come si mostrerà il codice di sopra applicando il State:

 

Code Snippet
  1.     class CommandPattern
  2.     {
  3.         delegate void Invoker();
  4.         static Invoker Execute, Undo, Redo;
  5.  
  6.         class Command
  7.         {
  8.             public Command(Receiver receiver)
  9.             {
  10.                 Execute = receiver.Action;
  11.                 Redo = receiver.Action;
  12.                 Undo = receiver.Reverse;
  13.             }
  14.         }
  15.  
  16.         public class Receiver
  17.         {
  18.             string build, oldbuild;
  19.             string s = "some string ";
  20.             public void Action()
  21.             {
  22.                 oldbuild = build;
  23.                 build += s;
  24.                 Console.WriteLine("Receiver is adding " + build);
  25.             }
  26.  
  27.             public void Reverse()
  28.             {
  29.                 build = oldbuild;
  30.                 Console.WriteLine("Receiver is reverting to " + build);
  31.             }
  32.         }
  33.  
  34.         static void Main()
  35.         {
  36.             new Command(new Receiver());
  37.             Execute();
  38.             Redo();
  39.             Undo();
  40.             Execute();
  41.             Console.ReadLine();
  42.         }
  43.     }
  44.  

 

Benefici e non
+ Crea un semplice meccaniscmo per l’esecuzione di diversi comportament in una maniera uniforme.
+ Da la possibilità di cambiare a runtime quali richieste sono gestite e come.
+ Richiede un’implementazione semplice.

- Complica il design se le condizioni sono poche.

E non prendete come scusa: “il mio sistema ormai è troppo evoluto per poterne apportare queste migliorie. E’ troppo tardi.”

Se fosse realmente così non esisterebbe il Refactoring :)

Per questo post ho preso spunto da libro Refactoring To Patterns di Joshua Kerievsky.

[top]

Related Post


(will not be published)
(es: http://www.mysite.com)