Saturday, June 20, 2009

Duplicated Code: Form template method

Continuiamo con lo smell: Duplicated Code
noclone

Problema:

Abbiamo 2 o più metodi che eseguono lo stesso codice anche se con una sequenza logica diversa.
Un esempio di logica errata:
  Immagine
Code Snippet
  1.     class Employee
  2.     {
  3.         public int EmpID { get; set; }
  4.         public string EmpName { get; set; }
  5.         public string Salary { get; set; }
  6.         public Employee(int empID, string empName, string sal)
  7.         {
  8.             this.EmpID = empID;
  9.             this.EmpName = empName;
  10.             this.Salary = sal;
  11.         }
  12.  
  13.         public string Display()
  14.         {
  15.             string s;
  16.             s = "$" + Salary;
  17.             //Display all Employees Details.
  18.             s += "Employee ID: " + EmpID;
  19.             s += "Employee Name: " + EmpName;
  20.             s += "Employee Salary: " + Salary;
  21.             s += "-------------------";
  22.  
  23.             return s;
  24.         }
  25.     }
  26.  
  27.     class Department
  28.     {
  29.         public int DeptID { get; set; }
  30.         public string DeptName { get; set; }
  31.         public string Location { get; set; }
  32.         public Department(int deptID, string deptName, string loc)
  33.         {
  34.             this.DeptID = deptID;
  35.             this.DeptName = deptName;
  36.             this.Location = loc;
  37.         }
  38.  
  39.         public string Display()
  40.         {
  41.             if (Location == "BLORE")
  42.             {
  43.                 Location = "BANGALORE";
  44.             }
  45.             else if (Location == "HYD")
  46.             {
  47.                 Location = "HYDERABAD";
  48.             }
  49.             else
  50.             {
  51.                 Location = "DELHI";
  52.             }
  53.             //Display all Departments Details.
  54.            
  55.             string s = "Department ID: " + DeptID;
  56.             s += "Department Name: " + DeptName;
  57.             s += "Department Location: " + Location;
  58.             s += "-------------------";
  59.             return s;
  60.         }
  61.     \

Motivazione:
Il polimorfismo viene in aiuto per eliminare il codice duplicato. Quando abbiamo due subclasses con lo stesso metodo portiamo tutto nella classe base e abbiamo risolto.
Ma quando i due metodo non sono esattamente gli stessi, cosa possiamo fare?

Soluzione:
 refactored
Code Snippet
  1.     abstract class AbstractDAO
  2.     {
  3.         public abstract void LoadDetails();
  4.         public abstract void FormatAndDisplayDetails();
  5.         public virtual void StartUp()
  6.         {
  7.             Console.WriteLine("Start of Processing");
  8.             Console.WriteLine("-------------------");
  9.         }
  10.         public virtual void Dispose()
  11.         {
  12.             Console.WriteLine("End of Processing");
  13.         }
  14.         public void Display()
  15.         {
  16.             StartUp();
  17.             LoadDetails();
  18.             FormatAndDisplayDetails();
  19.             Dispose();
  20.         }
  21.     }
  22.  
  23.     class Employees : AbstractDAO
  24.     {
  25.         private List empList = new List();
  26.         public override void LoadDetails()
  27.         {
  28.             //Get Data From Database.
  29.             empList.Add(new Employee(10, "TEST", "2000"));
  30.             empList.Add(new Employee(20, "TEST1", "3000"));
  31.             empList.Add(new Employee(30, "TEST2", "4000"));
  32.         }
  33.  
  34.         public override void FormatAndDisplayDetails()
  35.         {
  36.             //Add $ to Salary
  37.             foreach (Employee emp in empList)
  38.             {
  39.                 emp.Salary = "$" + emp.Salary;
  40.                 //Display all Employees Details.
  41.                 Console.WriteLine("Employee ID: " + emp.EmpID);
  42.                 Console.WriteLine("Employee Name: " + emp.EmpName);
  43.                 Console.WriteLine("Employee Salary: " + emp.Salary);
  44.                 Console.WriteLine("-------------------");
  45.             }
  46.         }
  47.     }
  48.     class Departments : AbstractDAO
  49.     {
  50.         private List deptList = new List();
  51.         public override void LoadDetails()
  52.         {
  53.             //Get Data From Database.
  54.             deptList.Add(new Department(1000, "HRA", "BLORE"));
  55.             deptList.Add(new Department(2000, "FIN", "HYD"));
  56.             deptList.Add(new Department(3000, "MARKETING", "DEL"));
  57.         }
  58.  
  59.         public override void FormatAndDisplayDetails()
  60.         {
  61.             //Expand Location.
  62.             foreach (Department dept in deptList)
  63.             {
  64.                 if (dept.Location == "BLORE")
  65.                 {
  66.                     dept.Location = "BANGALORE";
  67.                 }
  68.                 else if (dept.Location == "HYD")
  69.                 {
  70.                     dept.Location = "HYDERABAD";
  71.                 }
  72.                 else
  73.                 {
  74.                     dept.Location = "DELHI";
  75.                 }
  76.                 //Display all Departments Details.
  77.                 Console.WriteLine("Department ID: " + dept.DeptID);
  78.                 Console.WriteLine("Department Name: " + dept.DeptName);
  79.                 Console.WriteLine("Department Location: " + dept.Location);
  80.                 Console.WriteLine("-------------------");
  81.             }
  82.         }
  83.     \



Benefici e non
+ Rimuove il codice duplicato.
+ Nasconde come si comporta l’algoritmo a seconda dell’oggetto.
+ Permette alle sottoclassi di customizzare l’algoritmo.

- Complica il design.
 
 
 
 
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 :)

No comments:

Post a Comment