zoukankan      html  css  js  c++  java
  • extract method(提炼函数)

    你有一段代码可以被组织在一起并提炼出来

    // 提炼前
    void printOwning(double amount){
      printBananer();
      
      // print details
      Sysout.out.println("name:" + _name);
      Sysout.out.println("amount:" + amount);
    }
    
    // 提炼后
    void printOwning(double amount){
      printBananer();
      printDetails(amount)
    }
    
    void printDetails(double amount){
      Sysout.out.println("name:" + _name);
      Sysout.out.println("amount:" + amount);
    }
    

    动机

    • 函数越小可读性越高

    • 函数越小复用的机会就越大

    可读性高的前提是能给函数取一个好名字

    根据名字就可以直接明白函数是干啥的,而不需要跳转进去

    需要一定的词汇量并且会归纳

    做法

    1. 取一个好名字

    我们提炼的目的是增加代码的可读性,如同看文章一样,见到函数的名就知道它是做什么的,而不用再去关心它是怎么做的,提高可读性。

    所以需要以函数做什么命名,而不是怎么做

    举例:

    查询订单的失效时间后,与当前时间判断,早于当前时间则订单失效,晚于当前时间则订单有效。

    这里我们做什么?判断订单是否有效

    所以提炼的方法名应为:isOrderEffective(),而不是compareWithNowTime()

    前者是做什么,后者是怎么做

    1. 提炼代码从源函数复制到新建的目标函数中
    1. 检查变量,有没有用到源函数的局部变量和参数;

    这里的目的是要看我们提炼的函数产生的影响,会不会受源函数的影响。

    1. 检查变量,有没有只在目标函数中使用的变量,如果有的话,在目标函数中声明为临时变量
    1. 检查被提炼代码段,看看有没有局部变量的值被它改变。

    如果有一个临时变量被修改了,看看能否将被提炼代码段处理为一个查询,并将结果赋值给相关变量。

    如果被修改的变量有点多了,就要先拆解变量,再来单独提炼。

    1. 将被提炼代码段中需要读取的局部变量,当做参数传给目标函数
    2. 处理完所有局部变量,编译
    3. 在源函数中,将被提炼代码段替换为对目标函数的调用,删除未使用的临时变量声明
    4. 编译、测试

    范例

    // 提炼前
    void printOwning(){
      Enumeration e = _orders.elements();
      double outstanding = 0.0;
      
      // print banner
      Sysout.out.println("**********************");
      Sysout.out.println("****Customer Ownes****");
      Sysout.out.println("**********************");
      
      // calculate outstanding
      while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        outstanding += each.getAmount();  
      }
      
      // print details
      Sysout.out.println("name:" + _name);
      Sysout.out.println("amount:" + outstanding);
    }
    
    // 1. 无局部变量,提炼函数 printBanner()
    void printOwning(){
      Enumeration e = _orders.elements();
      double outstanding = 0.0;
      
    	printBanner();
      
      // calculate outstanding
      while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        outstanding += each.getAmount();  
      }
      
      // print details
      Sysout.out.println("name:" + _name);
      Sysout.out.println("amount:" + outstanding);
    }
    
    void printBanner(){
      Sysout.out.println("**********************");
      Sysout.out.println("****Customer Ownes****");
      Sysout.out.println("**********************");
    }
    
    
    // 2. 使用到了源函数的局部变量且为只读,将源函数具备变量传入目标函数
    void printOwning(){
      Enumeration e = _orders.elements();
      double outstanding = 0.0;
      
    	printBanner();
      
      // calculate outstanding
      while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        outstanding += each.getAmount();  
      }
      
      printDetails(outstanding);
      	
    }
    
    void printDetails(double outstanding){
      Sysout.out.println("name:" + _name);
      Sysout.out.println("amount:" + outstanding);
    }
    
    // 3. 对局部变量再赋值:使用源函数局部变量,并且进行了操作
    void printOwning(){
    	printBanner();
     	double outstanding=getOutStanding();
      printDetails(outstanding);
    }
    
    double getOutStanding(){
       Enumeration e = _orders.elements();
       double outstanding = 0.0;
       while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        outstanding += each.getAmount();  
      }
      return outstanding;
    }
    
    // 4. 回传值改名
    double getOutStanding(){
       Enumeration e = _orders.elements();
       double result = 0.0;
       while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        result += each.getAmount();  
      }
      return result;
    }
    
    

    上面的情况中 getOutStanding 是没有入参的,因为源函数只是对 outstanding 做了初始化,而没有做其他操作,如果源函数中对 outstanding 做了其他的操作,就需要将 outstanding 作为入参传入。

    // 提炼前
    void printOwning(double previousAmount){
      Enumeration e = _orders.elements();
      double outstanding = previousAmount * 1.2;
      
    	printBanner();
      
      // calculate outstanding
      while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        outstanding += each.getAmount();  
      }
      
      printDetails(outstanding);
      	
    }
    
    // 1. 提炼之后,将操作后的 局部变量 作为入参传入目标函数
    void printOwning(double previousAmount){
      double outstanding = previousAmount * 1.2;
    	printBanner();
      outstanding = getOutStanding(outstanding)
      printDetails(outstanding);
    }
    
    double getOutStanding(double initialValue){
       double result = initialValue;
       Enumeration e = _orders.elements();
       while(e.hasMoreElements()){
        Order each = (Order)e.nextElement();
        result += each.getAmount();  
      }
      return result;
    }
    
    // 2. 去除临时变量,优化outstanding初始化过程
    void printOwning(double previousAmount){
    	printBanner();
      double outstanding = getOutStanding(previousAmount * 1.2)
      printDetails(outstanding);
    }
    
  • 相关阅读:
    单页面 Web 应用(Single Page Application,SPA)的工作原理介绍
    为什么 Web 开发人员需要学习一个 JavaScript 框架?
    SAP Commerce Cloud 项目 Spartacus 入门
    SAP Spartacus 的 CSS 架构
    什么是 Immutable Web Apps
    PHP中把stdClass Object转array的几个方法
    git tag常用操作
    报错No Input file specified
    python爬取抖音个人主页所有视频
    无水印抖音视频批量下载---基于python爬虫(全网最简单方法含详细解析)
  • 原文地址:https://www.cnblogs.com/wangshuyu/p/15244344.html
Copyright © 2011-2022 走看看