Refactoring: longer and longer switches... case and if... else, switchcase

Source: Internet
Author: User

Refactoring: longer and longer switches... case and if... else, switchcase

In Code, conditional expressions such as switch... case or if... else are usually expanded with a Type Code. As the business logic of the project increases and the code is modified over years, these conditional judgment logics become increasingly lengthy. Especially when the same logic judgment appears in multiple places (the structure is illustrated below), the code readability and maintenance difficulty will become very bad. Each time you modify a logical branch, you must find all the logical branches and modify them.

 1 switch(type) 2 { 3     case "1": 4         ... 5         break; 6     case "2": 7         ... 8         break; 9     case default:10         ...11         break;12 }13 14 ... ...15 ... ...16 17 switch(type)18 {19     case "1":20         ...21         break;22     case "2":23         ...24         break;25     case default:26         ...27         break;28 }

When such a situation occurs in the code, you should consider refactoring it. (another saying is that you should try to refactor the switch... case statement to prevent it from appearing in your code ).

 

To reconstruct the conditional expression for Type Code judgment, we need to introduce the object-oriented polymorphism mechanism. Method 1:Use subclass to replace conditional expressions.

Let's take the Employee salaries of different role as an example to explain the reconstruction process step by step. The class structure to be reconstructed is as follows:

1 public class Employee_Ori 2 {3 private int _ type; 4 5 private const int ENGINEER = 1; 6 private const int SALESMAN = 2; 7 private const int MANAGER = 3; 8 9 private decimal _ baseSalary = 10000; 10 private decimal _ royalty = 100; 11 private decimal _ bonus = 400; 12 13 public Employee_Ori (int type) 14 {15 this. _ type = type; 16} 17 18 public decimal getEmployeeSalary () 19 {20 var monthlySalary = 0 m; 21 22 switch (this. _ type) 23 {24 case ENGINEER: 25 monthlySalary = _ baseSalary; 26 break; 27 case SALESMAN: 28 monthlySalary = _ baseSalary + _ royalty; 29 break; 30 case MANAGER: 31 monthlySalary = _ baseSalary + _ bonus; 32 break; 33} 34 35 return monthlySalary; 36} 37}

The getEmployeeSalary () method returns the current month's salary based on the roles of employees. Of course, the logic here is just a diagram. Do not go into it.

The class structure after reconstruction using the subclass method is as follows:

1 public class Engineer_Sub: Employee_Sub 2 {3... 4} 5 6 public class Salesman_Sub: Employee_Sub 7 {8... 9} 10 11 public class Manager_Sub: Employee_Sub12 {13... 14}

At the same time, the constructor of the Employee base class is transformed into a static Create factory function.

 1 public static Employee_Sub Create(int type) 2 { 3     Employee_Sub employee = null; 4  5     switch (type) 6     { 7         case ENGINEER: 8             employee = new Engineer_Sub(); 9             break;10         case SALESMAN:11             employee = new Salesman_Sub();12             break;13         case MANAGER:14             employee = new Manager_Sub();15             break;16     }17 18     return employee;19 }

The static factory method also contains a switch logic. In the restructured code, the switch determines that there is only one such field. It is only involved in the object creation process and does not involve any business logic. Therefore, it is acceptable.

Each role subclass overwrites the getEmployeeSalary () method in the base class, and uses its own rules to calculate the salary.

1 private decimal _baseSalary = 10000;2 3 public override decimal getEmployeeSalary()4 {5     return _baseSalary;6 }

In this way, the getEmployeeSalary () method in the base class Employee has no practical significance and changes it to the abstract method.

1 public abstract decimal getEmployeeSalary();

Subclass has completely replaced the bloated switch expression. If Engineer, Salesman, or Manager has new behaviors, you can add methods to their subclass. Or there will be a new Employee Type later, which can be achieved by adding a new subclass. Here, the isolation between services and their use is achieved through polymorphism.

 

However, in some cases, for example, the object type needs to change in the lifecycle (refined to this example, for example, the Engineer is promoted to Manager) or the type host class already has a subclass, then, the method of subclass reconstruction cannot work. In this case, the second method is used:Replace conditional expressions with State/Strategy.

Similarly, first upload the class structure after the reconstruction of this method:

1 public class Employee_State2 {3 // employee's type can be changed4 private EmployeeType_State _ employeeType = null; 5}

EmployeeType is the base class, and the employee type is used as its subclass. The EmployeeType class contains a static factory method Create for creating employee types.

 1 public static EmployeeType_State Create(int type) 2 { 3     EmployeeType_State empType = null; 4  5     switch (type) 6     { 7         case ENGINEER: 8             empType = new EngineerType_State(); 9             break;10         case SALESMAN:11             empType = new SalesmanType_State();12             break;13         case MANAGER:14             empType = new ManagerType_State();15             break;16     }17 18     return empType;19 }

The Employee salary calculation method getEmployeeSalary () is migrated from the Employee class to the Employee type base class EmployeeType. This method override each specific employee type class. Considering that EmployeeType has no specific business logic, change the getEmployeeSalary () method in EmployeeType to an abstract method.

1 public class EngineerType_State : EmployeeType_State2 {3     private decimal _baseSalary = 10000;4 5     public override decimal getEmployeeSalary()6     {7         return _baseSalary;8     }9 }

 

Finally, add the sample code and click here to download it.

 

References:

Refactoring to improve the design of existing code Martin Fowler

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.