重构多重嵌套的代码 - 思考
本文链接: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个以上,如果达到了,那么我们可以停下来思考,能否重构?多重联表亦然如此
源码面前,了无秘密