• 重构多重嵌套的代码


    本文链接:http://www.cnblogs.com/zhenghongxin/p/8682715.html

    箭头型代码

    某些人的逻辑写法很喜欢按照自己的思维模式来,我们可以看到这样子的 “ 箭头型” 代码:

    function doSomeThing(){
         if($condition1 == true){
             if($condition2 == true){
                 if ($condition3 == true) {
                     if ($condition4 == true) {
                         if ($condition5 == true) {
                             if ($condition6 == true) {
                                 if($condition7 == true){
                                     // --------------> do something                                   
                                 }
                             }
                         }
                     }
                 }
             }
         }
    }

    看起来是不是中间很像一个箭头?可能开发者能理解这个逻辑,但其他人看着看着,很容易在一大堆if中迷失了逻辑。诸如此类的,还有for或foreach循环,一大堆循环中,计算量成倍增长。个人建议是:

    重构你的代码,最好不要超过三个嵌套代码,不管是if,for,foreach(还是查表语句的联表查询,不得已才超过这个量级),如果可以,重构代码以保证代码的整洁性

    重构:让出错的逻辑先返回

    不整洁的例子:

    FOREACH(Ptr<WfExpression>, argument, node->arguments) {
        int index = manager->expressionResolvings.Keys().IndexOf(argument.Obj());
        if (index != -1) {
            auto type = manager->expressionResolvings.Values()[index].type;
            if (! types.Contains(type.Obj())) {
                types.Add(type.Obj());
                if (auto group = type->GetTypeDescriptor()->GetMethodGroupByName(L"CastResult", true)) {
                    int count = group->GetMethodCount();
                    for (int i = 0; i < count; i++) { auto method = group->GetMethod(i);
                        if (method->IsStatic()) {
                            if (method->GetParameterCount() == 1 &&
                                method->GetParameter(0)->GetType()->GetTypeDescriptor() == description::GetTypeDescriptor<DescriptableObject>() &&
                                method->GetReturn()->GetTypeDescriptor() != description::GetTypeDescriptor<void>() ) {
                                symbol->typeInfo = CopyTypeInfo(method->GetReturn());
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    让不符合逻辑的代码先返回

    FOREACH(Ptr<WfExpression>, argument, node->arguments) {
        int index = manager->expressionResolvings.Keys().IndexOf(argument.Obj());
        if (index == -1)  continue;
         
        auto type = manager->expressionResolvings.Values()[index].type;
        if ( types.Contains(type.Obj()))  continue;
         
        types.Add(type.Obj());
     
        auto group = type->GetTypeDescriptor()->GetMethodGroupByName(L"CastResult", true);
        if  ( ! group ) continue;
      
        int count = group->GetMethodCount();
        for (int i = 0; i < count; i++) { auto method = group->GetMethod(i);
            if (! method->IsStatic()) continue;
            
            if ( method->GetParameterCount() == 1 &&
                   method->GetParameter(0)->GetType()->GetTypeDescriptor() == description::GetTypeDescriptor<DescriptableObject>() &&
                   method->GetReturn()->GetTypeDescriptor() != description::GetTypeDescriptor<void>() ) {
                symbol->typeInfo = CopyTypeInfo(method->GetReturn());
                break;
            }
        }
    }

     为了整个代码的易读性,我们可以抽象出函数,让逻辑看起来更加清晰

    重构:理清思路和修改更清晰的逻辑

    原始代码:

    for(....) {
        do_before_cond1()
        if (cond1) {
            do_before_cond2();
            if (cond2) {
                do_before_cond3();
                if (cond3) {
                    do_something();
                }
                do_after_cond3();
            }
            do_after_cond2();
        }
        do_after_cond1();
    }

    仔细读这段代码,思考我们如何重构?

    1)让出错或不符合下一步的代码先返回

    for(....) {
        do_before_cond1(); do_after_cond1();
    if ( !cond1 ) { continue }    do_before_cond2(); do_after_cond2(); if ( !cond2 ) { continue; } do_before_cond3(); do_after_cond3(); if ( !cond3 ) { continue; } do_otherSomething(); }

    这样子逻辑会读起来明显比第一种清晰得多

    2)换一下简洁的写法:

    for(....) {
        do_before_cond1();
        do_after_cond1();
        if ( !cond1 ) continue;
      
        do_before_cond2();
        do_after_cond2();
        if ( !cond2 ) continue;
     
        do_before_cond3();
        do_after_cond3();
        if ( !cond3 ) continue;
     
        do_something(); 
    }

    抽象出函数

    bool do_func3() {
       do_before_cond2();
       do_after_cond2();
       return cond3;
    }
     
    bool do_func2() {
       do_before_cond2();
       do_after_cond2();
       return cond2;
    }
     
    bool do_func1() {
       do_before_cond1();
       do_after_cond1();
       return cond1;
    }
     
    // for-loop 你可以重构成这样
    for (...) {
        bool cond = do_func1();
        if (cond) cond = do_func2();
        if (cond) cond = do_func3();
        if (cond) do_something();
    }
     
    // for-loop 也可以重构成这样
    for (...) {
        if ( ! do_func1() ) continue;
        if ( ! do_func2() ) continue;
        if ( ! do_func3() ) continue;
        do_something();
    }

    处理的方式很多,总之,我们并不能嵌套多重达到3个以上,如果达到了,那么我们可以停下来思考,能否重构?多重联表亦然如此

  • 相关阅读:
    解决Eclipse中“诡异”的错误:找不到或无法加载主类
    eclipse 中的注释 快捷键 多行注释快捷键 单行注释快捷键
    将Eclipse设置为黑色主题
    Javac提示不是内部或外部命令
    js粒子旋涡
    canvas黑客帝国代码雨特效 | jQuery特效|手机微信网站特效| 网页特效库
    python笔记--冒泡排序升级版
    MySQL5.7(二)数据库的基本操作
    Linux命令应用大词典-第1章 登录、退出、关机和重启
    第1章 Linux命令行简介
  • 原文地址:https://www.cnblogs.com/zhenghongxin/p/8682715.html
Copyright © 2020-2023  润新知