zoukankan      html  css  js  c++  java
  • 改善过多的if else

    刚看到一个提问帖: 《如果程序中出现多层嵌套的 if...else...语句,如何重构可使程序逻辑变得更为清晰易读?》,因回答篇幅比较大,单独开个帖子答一下。

    个人喜好代码风格不一样,下面只是我认为好的代码风格,不喜勿喷。如果有其他好的技巧,欢迎分享补充。

    file

    技巧一#

    删除 else

    如:

    function test($arg)
    {
        if($arg == 'foobar'){
            return true;
        }else{
            return false;
        }
    }
    

    尽量写成这样

    function test($arg)
    {
        if($arg == 'foobar'){
            return true;
        }
    
        return false;
    }

    优先将代码量少,可使流程中断的代码块(return, throw excetion, continue ...)放到 if 中, 提前中断代码。

    技巧二#

    拆分为多个函数

    如果整个 if else 中的代码比较多,或者 if 与 else 中带代码不会导致后面的判断流程中断,并且还有 if else 之外的代码,将就 if else 中的代码拆分为多个函数。

    if($age > 18){
        doSomeThingA();
        doSomeThingB();
        doSomeThingC();
    }else{
        doSomeThingD();
        doSomeThingE();
    }

    这种方式需要将函数名取的尽量清晰易懂,不要嫌长。

    技巧三#

    罗列规则式的写代码

    多层 if 嵌套的语法,把他写成线性的,就像写规则一样将其一条条罗列出来

    如:

    function match($age, $salary, $pretty){
        if($age > 18){
             // do some thing A;
            if($salary > 5000){
                // do some thing B;
                if($pretty == true){
                    return true;
                }
            }
        }
    
        return false;
    }

    改写成这样是不是清晰多了?

    function match($age, $salary, $pretty){
        if($age < 18){
            return false;
        }
    
        // do some thing A;
    
        if($salary < 5000){
            return false;
        }
    
        // do some thing B;
    
        return $pretty == true;
    }
    

    总结#

    少用 else , 提前中断(return)!!!#

    少用 else , 提前中断(return)!!!#

    少用 else , 提前中断(return)!!!#

    重要的事情说三遍!

    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

    我也来尝试回答这个问题如果程序中出现多层嵌套的 if...else...语句,如何重构可使程序逻辑变得更为清晰易读?

    一般原则是if 是越少越好,能不用就不用,层级越少越好。

    技巧1:映射表法#

    function contry_initial($country){
        if ($country==="China" ){
           return "CHN";
        }else if($country==="America"){
           return "USA";
        }else if($country==="Japna"){
          return "JPN";
        }else{
           return "OTHER";
        }
    }

    这样的if语句,可以看到值和返回是一一对应的,所以你可以这样写

    function contry_initial($country){
      $countryList=[
          "China"=> "CHN",
          "America"=> "USA",
          "Japna"=> "JPN",
        ];
    
        if(in_array($country, array_keys($countryList))) {
            return $countryList[$country];
        }
        return "Other";
    
    }

    如果需要更加自由的定义映射表的话,可以这样写

    function contry_initial($country, array $countryList){
        if(in_array($country, array_keys($countryList))) {
            return $countryList[$country];
        }
        return "Other";
    }

    完全去掉if语句可以写成

    function contry_initial($country, array $countryList){
        return in_array($country, array_keys($countryList))?$countryList[$country]:"Other";
    }

    技巧二:多维映射表#

    自己制定一个标准,建立一个多维的映射表,然后尽量少的if语句去囊括所有范例

    function match($age,$gender,$pretty){
    $list=[
          ['age'=>[1,12], 'gender'=>"Male",'pretty'=>true,'action'=>function(){//do something},'return'=>'pretty young  man'],
          ['age'=>[1,12], 'gender'=>"Female",'pretty'=>true,'action'=>function(){//do something},'return'=>'pretty young lady'],
          ['age'=>[1,12], 'gender'=>"Male", 'pretty'=>false,'action'=>function(){//do something},'return'=>'boy'],
          ['age'=>[1,12], 'gender'=>"Female",'pretty'=>false,'action'=>function(){//do something},'return'=>'girl'],
          ['age'=>[13,18], 'gender'=>"Male", 'pretty'=>true,'action'=>function(){//do something},'return'=>'pretty man'],
    ....
       ];
    
        foreach($list as $item){
           if($age>=$item['age'][0]&&$age<=$item['age'][1]&&$gender===$item['gender']&&$pretty===$item['pretty']){
                $item['action']();
              return $item['return'];
    
           }
        }
          return null;
    
    }
    

    当然,这样排列组合可能会有很多案例,而callable的代码也会有重复。所以改进的方案是

    function match($age,$gender,$pretty){
        $ageList=[
            [ "age"=>[1,12],"action"=>function(){},"return"=>"young"],
            [ "age"=>[13,18],"action"=>function(){},"return"=>"teenage"],
            [ "age"=>[19,100],"action"=>function(){},"return"=>"adult"],
            [ "age"=>[100,1000],"action"=>function(){},"return"=>"adult"],
        ];
    
        $genderList=[
            'Male'=>["action"=>function(){},"return"=>"man"],
            'Female'=>["action"=>function(){},"return"=>"lady"],
            'default'=>["action"=>function(){},"return"=>"person"],
        ];
    
        $prettyList=[
            true=>["action"=>function(){},"return"=>"pretty"],
            false=>["action"=>function(){},"return"=>""],
        ];
    
        foreach($ageList as $item){
            if($age>=$item['age'][0]&&$age<=$item['age'][1]){
                $item['action']();
                $returnValue=    $item['return'];
            }
        }
    
         if(in_array($gender,array_keys($genderList))) {
            $genderList[$gender]['action']();
            $returnValue .=" ".$genderList[$gender]['return'];
        } else {
            $genderList['default']['action']();
            $returnValue .=" ".$genderList['default']['return'];
        }
    
        $prettyList[$pretty]['action']();
    
        return   $prettyList[$pretty]['return']." ".$returnValue;
    }
    

    总结#

    以上代码并不完美,总之要更具需要去重构,而不是为了优雅而重构。

    使用映射表法的好处是提高单元测试的覆盖率,而坏处是增加了加载时间和消耗内存空间

    当然,还是要注意一些

    • return能越早越好
    • if else 语句越少越好,可以用condition?a:b 表达的,就不要用if else
    • 有一一对应关系的,使用映射表。
  • 相关阅读:
    需求分析-配置软件开发的出发点
    有关tab页的
    有关菜单的
    有关树形结构的
    需求分析-新闻发布的完整需求
    需求分析-网盘类的需求分析
    需求分析-有关有关富文本编辑器的需求
    Objective-C中的instancetype和id区别
    webservice远程调试开启
    Controller之间传递数据:Block传值
  • 原文地址:https://www.cnblogs.com/clphp/p/5939905.html
Copyright © 2011-2022 走看看