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.         public string Display()
  13.         {
  14.             string s;
  15.             s = "$" + Salary;
  16.             //Display all Employees Details.
  17.             s += "Employee ID: " + EmpID;
  18.             s += "Employee Name: " + EmpName;
  19.             s += "Employee Salary: " + Salary;
  20.             s += "-------------------";
  21.             return s;
  22.         }
  23.     }
  24.     class Department
  25.     {
  26.         public int DeptID { get; set; }
  27.         public string DeptName { get; set; }
  28.         public string Location { get; set; }
  29.         public Department(int deptID, string deptName, string loc)
  30.         {
  31.             this.DeptID = deptID;
  32.             this.DeptName = deptName;
  33.             this.Location = loc;
  34.         }
  35.         public string Display()
  36.         {
  37.             if (Location == "BLORE")
  38.             {
  39.                 Location = "BANGALORE";
  40.             }
  41.             else if (Location == "HYD")
  42.             {
  43.                 Location = "HYDERABAD";
  44.             }
  45.             else
  46.             {
  47.                 Location = "DELHI";
  48.             }
  49.             //Display all Departments Details.
  50.            
  51.             string s = "Department ID: " + DeptID;
  52.             s += "Department Name: " + DeptName;
  53.             s += "Department Location: " + Location;
  54.             s += "-------------------";
  55.             return s;
  56.         }
  57.     \


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.     class Employees : AbstractDAO
  23.     {
  24.         private List<Employee> empList = new List<Employee>();
  25.         public override void LoadDetails()
  26.         {
  27.             //Get Data From Database.
  28.             empList.Add(new Employee(10, "TEST", "2000"));
  29.             empList.Add(new Employee(20, "TEST1", "3000"));
  30.             empList.Add(new Employee(30, "TEST2", "4000"));
  31.         }
  32.         public override void FormatAndDisplayDetails()
  33.         {
  34.             //Add $ to Salary
  35.             foreach (Employee emp in empList)
  36.             {
  37.                 emp.Salary = "$" + emp.Salary;
  38.                 //Display all Employees Details.
  39.                 Console.WriteLine("Employee ID: " + emp.EmpID);
  40.                 Console.WriteLine("Employee Name: " + emp.EmpName);
  41.                 Console.WriteLine("Employee Salary: " + emp.Salary);
  42.                 Console.WriteLine("-------------------");
  43.             }
  44.         }
  45.     }
  46.     class Departments : AbstractDAO
  47.     {
  48.         private List<Department> deptList = new List<Department>();
  49.         public override void LoadDetails()
  50.         {
  51.             //Get Data From Database.
  52.             deptList.Add(new Department(1000, "HRA", "BLORE"));
  53.             deptList.Add(new Department(2000, "FIN", "HYD"));
  54.             deptList.Add(new Department(3000, "MARKETING", "DEL"));
  55.         }
  56.         public override void FormatAndDisplayDetails()
  57.         {
  58.             //Expand Location.
  59.             foreach (Department dept in deptList)
  60.             {
  61.                 if (dept.Location == "BLORE")
  62.                 {
  63.                     dept.Location = "BANGALORE";
  64.                 }
  65.                 else if (dept.Location == "HYD")
  66.                 {
  67.                     dept.Location = "HYDERABAD";
  68.                 }
  69.                 else
  70.                 {
  71.                     dept.Location = "DELHI";
  72.                 }
  73.                 //Display all Departments Details.
  74.                 Console.WriteLine("Department ID: " + dept.DeptID);
  75.                 Console.WriteLine("Department Name: " + dept.DeptName);
  76.                 Console.WriteLine("Department Location: " + dept.Location);
  77.                 Console.WriteLine("-------------------");
  78.             }
  79.         }
  80.     \

 

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 :)