重构多重嵌套的代码 - 思考

本文链接: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个以上,如果达到了,那么我们可以停下来思考,能否重构?多重联表亦然如此

 

posted @ 2018-03-31 16:18  hongxinerke  阅读(1242)  评论(0编辑  收藏  举报