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
- if (ac.Name.Equals("ATTACCO"))
- // ...
- else if (ac.Name.Equals("DIFESA"))
- // ...
- else if (ac.Name.Equals("BERSERK"))
- // ...
- else if (ac.Name.Equals("GUARDINGO"))
- // ...
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:
- Poca flessibilità a runtime
- 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
- class CommandPattern
- {
- delegate void Invoker();
- static Invoker Execute, Undo, Redo;
- class Command
- {
- public Command(Receiver receiver)
- {
- Execute = receiver.Action;
- Redo = receiver.Action;
- Undo = receiver.Reverse;
- }
- }
- public class Receiver
- {
- string build, oldbuild;
- string s = "some string ";
- public void Action()
- {
- oldbuild = build;
- build += s;
- Console.WriteLine("Receiver is adding " + build);
- }
- public void Reverse()
- {
- build = oldbuild;
- Console.WriteLine("Receiver is reverting to " + build);
- }
- }
- static void Main()
- {
- new Command(new Receiver());
- Execute();
- Redo();
- Undo();
- Execute();
- Console.ReadLine();
- }
- }
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.
posted @ martedì 16 giugno 2009 19:07