• 代码重构


    试想场景:

    我们要写一个逻辑比较复杂的函数,

    发现根之前一个函数很类似。

    怎么办,

    重新写?

    or

    coppy ——update——done

    坏处?

    重构?

    一 以多态取代条件表达式 

    为什么少用switch语句?

    class Employee { 
        @Autowired
        private EmployeeType _type; 
        int getType() { 
         return _type.getTypeCode(); 
       }
        int payAmount(Employee emp){ 
          switch(getType()) {
          case EmployeeType.ENGINEER:  
               return emp.getMonthlySalary();
          case EmployeeType.SALESMAN: 
               return emp.getMonthlySalary() + emp.getCommission();
          case EmployeeType.MANAGER: 
               return emp.getMonthlySalary() + emp.getBonus(); 
          ... 
         default: throw new RuntimeException("Incorrect Employee"); 
         }
      }
    }
     
    abstract class EmployeeType { 
          abstract int getTypeCode(); 
       }
    
    class Engineer extends EmployeeType {
        @Override
        int getTypeCode() {
        return Employee.ENGINEER; 
        } 
    }
    

    重构后

    class Employee { 
        public Employee(EmployeeType type) {
          this._type = type
        } 
        int payAmount(Employee emp) { 
          return _type.payAmount(emp); 
        } 
      }
    
    class EmployeeType { 
        abstract int payAmount(Employee emp); 
    }
    
    class Engine extends EmployeeType { 
        @Override
        int payAmount(Employee emp) { 
         return emp.getMonthlySalary(); 
        } 
    } 
     
    class Salesman extents EmployeeType { 
         @Override
         int payAmount(Employee emp) { 
            return emp.getMonthlySalary() + emp.getCommission(); 
         } 
    }
    
    class Manager extents EmployeeType { 
        @Override
        int payAmount(Employee emp) { 
             return emp.getMonthlySalary() + emp.getBonus(); 
        } 
    }

    二 过长参数列 

    1.以函数取代参数 

    重构前

    public double getPrice() { 
         int basePrice = _quantity * _itemPrice; 
         int discountLevel;
         if(_quantity > 100){ 
             discountLevel = 2; 
         }else{ 
            discountLevel = 1; 
         } 
         double finalPrice = discountedPrice(basePrice, discountLevel); 
      return finalPrice; 
    } 
    
    private double discountedPrice(int basePrice, int discountLevel) { 
         if(discountLevel == 2) { 
             return basePrice * 0.1; 
         }else { 
             return basePrice * 0.05; 
         } 
    }

    重构后

    public double getPrice() {
         return discountedPrice(); 
    }
    
    private doulbe discountedPrice() {
         if(getDiscountLevle() == 2){ 
             return getBasePrice() * 0.1; 
        } else{ 
             return getBasePrice() * 0.05; 
        } 
     }
    private int getDiscountLevle() { 
         if(_quantity > 100){
             return 2; 
         } else{
             return 1; 
         } 
     }
    
     private double getBasePrice() { 
          return _quantity * _itemPrice; 
     }

    对调用discountedPrice方法处使用内联函数,进一步重构

    public double getPrice() {
         return discountedPrice(); 
    }
    继续,内联函数变成
    public double getPrice() {
         if(getDiscountLevle() == 2) { 
             return getBasePrice() * 0.1; 
         } else{ 
             return getBasePrice() * 0.05; 
         } 
    }

    2.保持完整对象 

    重构前

    int low = daysRange.getLow(); 
    int high = daysRange.getHigh(); 
    withplan = plan.range(low, high); 

    重构后

    withplan = plan.range(daysRange); 

    3引入参数对象.

    重构前 

    int low = daysRange.getLow(); 
    int high = daysRange.getHigh(); 
    int start = getStart(); 
    int end = getEnd(); 
    
    class Plan() {
         withplan = plan.range(low, high, start,end); 
    }

    重构后

    int low = daysRange.getLow(); 
    int high = daysRange.getHigh(); 
    int start = getStart(); 
    int end = getEnd(); 
    
    class DaysCon() { 
       int low; 
       int high;
       int start;
       int end; 
    }
    
    
    class WithPlan() { 
       withplan = plan.range(daysCon); 
    }

    三 过长函数 

    1.提炼函数(主要手段)

    重构前 

    public void PrintOwing(double amount) {
       PrintBanner(); 
      //print details 
       Console.WriteLine("name:"+_name); 
       Console.WriteLine("amount:"+_amount); 
    }

    重构后

    public void PrintOwing(double amount) {
        PrintBanner(); 
        //print details 
        PrintDetails();
     } 
    
    
    private void PrintDetails() { 
        Console.WriteLine("name:" + _name); 
        Console.WriteLine("amount:" + _amount); 
    }

    2.查询取代临时变量 

    重构前

    class Price {
      @Autowired
      private Quantity _quantity;
      @Autowired
      private ItemPrice _itemPrice;
     
      public double getPrice() { 
          int basePrice = _quantity * _itemPrice;
          double discountFactor;
          if (basePrice > 5000) { 
              discountFactor = 0.95; 
          } else { 
              discountFactor = 0.98;
          } 
          return basePrice * discountFactor; 
      } 
    }

    重构后

    class Price {
      @Autowired
      private Quantity _quantity;
      @Autowired
      private ItemPrice _itemPrice;
    
    
      public double getPrice() {
           return basePrice() * discountFactor(); 
      } 
      private double basePrice() { 
           return _quantity * _itemPrice;
      } 
      private double discountFactor() {
           if (basePrice() > 5000) {
              return 0.95; 
           } else { 
              return 0.98; 
           } 
      }
    }

    四 重复函数

    模板模式

    例如人事系统 批量导入中

    DataImportProcesser类中的 process方法

    模板模式的适用场景特征

     

    五 空对象模式 

    重构前

    class Site {
        Customer _customer;
        Customer getCustomer() { 
          return _customer;
       } 
    } 
     
    class Customer { 
       public String getName() {...}
       public BillingPlan getPlan() {...} 
       public PaymentHistory getHistory() {...} 
    } 
     
    class PaymentHistory { 
       public int getWeeksDelinquentInLastYear() { 
         Customer customer = site.getCustomer(); 
         BillingPlan plan; 
         if (customer == null) 
             plan = BillingPlan.basic(); 
         else plan = customer.getPlan(); 
         String customerName; 
         if (customer == null) 
             customerName = "occupant";
         else customerName = customer.getName(); 
          ...
         int weeksDelinquent;
         if (customer == null)
             weeksDelinquent = 0; 
         else weeksDelinquent = customer.getHistory(); 
       } 
    }

    重构过程

    class NullCustomer extends Customer {
         public boolean isNull() { 
           return true; 
         }
     }
     
    class Customer { 
         public boolean isNull() { 
           return false;
         } 
         static Customer newNull() {
           return new NullCustomer(); 
         } 
    }
    
    class Site { 
         Customer getCustomer() { 
           return (_customer == null) ? Customer.newNull() : _customer; 
        
    }
    class PaymentHistory {
         Customer customer = site.getCustomer(); 
         BillingPlan plan; 
         if (customer.isNull())
            plan = BillingPlan.basic(); 
         else plan = customer.getPlan(); 
         String customerName; 
         if (customer.isNull()) 
            customerName = "occupant"; 
         else customerName = customer.getName(); 
         int weeksDelinquent; 
         if (customer.isNull()) 
            weeksDelinquent = 0; 
         else weeksDelinquent = customer.getHistory();
         ... 
    }

    重构后

    class NullCustomer extends Customer { 
         public boolean isNull() { 
             return true;
         } 
         public String getName() { 
             return BillingPlan.basic(); 
         }
         public String getPlan() { 
             return "occupant" 
         } 
         public PaymentHistory getHistory() {
             return 0; 
         }
     } 
    
    class Customer { 
         public boolean isNull() { 
             return false;
         } 
         static Customer newNull() { 
             return new NullCustomer(); 
         } 
     } 
    
    class Site { Customer getCustomer() { 
         return (_customer == null) ? Customer.newNull() : _customer; 
    } 
    
    class PaymentHistory { 
         public int getWeeksDelinquentInLastYear() { 
             Customer customer = site.getCustomer(); 
             BillingPlan plan = customer.getPlan();
             String customerName = customer.getName(); 
             int weeksDelinquent = customer.getHistory(); 
             ...
         }
     } 
    为什么看起来仿佛增加了代码的复杂程度? 

    六 过多的注释

    当你感觉需要撰写注释,请先尝试重构,试着让所有注释都变得多余!

    七 推荐书籍

        《重构——改善既有代码的设计》

           阅读方法

  • 相关阅读:
    Eclipse使用xdoclet1.2.3 生成hibernate配置文件和映射文件
    Eclipse安装SVN插件
    SourceTree安装和使用
    myeclipse通过数据表生成jpa或hibernate实体
    Delphi 快速读取TXT 指定行的数据
    delphi中如何将一整个文件读入内存
    Delphi TextFile读取文本文件
    Delphi读取和写入utf-8编码格式的文件
    Delphi 判断特定字符是为单字节还是双字节
    delphi按字节长度分割字符串函数(转)
  • 原文地址:https://www.cnblogs.com/wanghongsen/p/9073361.html
Copyright © 2020-2023  润新知