// 上一篇:分枝/叶子(branch/leaf)

// 下一篇:状态机(state machine)


基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构。

典型代码:

  • 同步版本
function loadFunc(funcInfo){
if(funcInfo){
let funcObj = doParserFunc(funcInfo);
if(funcObj){
let package = doLoadPackage(funcObj.packageName);
if(pacakge){
let module = doLoadModule(pacakge,funcObj.moduleName);
if(module){
let func = module[funcObj.functionName];
if(func){
return func;
}else{
// do something
}
}else{
// do something
}
}else{
// do something
}
} else {
// do something
}
}
return null;
}
  • 异步版本
function loadFunc(funcInfo, onComplete){
if(funcInfo){
let funObj = doParseFunc(funcInfo);
if(funcObj){
doLoadPackage(funcObj.packageName, function(err,package){
if(package){
doLoadModule(package, funcObj.moduleName, function(err, module){
if(module){
let func = module[funcObj.functionName];
if(func){
onComplete(0,func);
}else{
onComplete(1);
}
}else{
onComplete(1);
}
})
}else{
onComplete(1);
}
});
}else{
onComplete(1);
}
}else{
onComplete(1);
}
}

结构分析

无论是同步版本,还是异步版本,都存在嵌套持续变深的问题。随着开发的进行,需求的变更,代码会变的越发繁杂。一种方式是通过上一节的方式,合理组织函数的分层,让函数的组织表达更清晰。但是另一方面,在支持lambda表达式和匿名函数的语言里,编程的时候总是会大量使用语言提供的这种便利,写带有许多lambda表达式或匿名函数的逻辑代码。一种常见的方式是使用卫语句(guard clause)的方式提前返回,减少嵌套。

  • 同步版本
function loadFunc(funcInfo){
if(!funcInfo){
return null;
} let funcObj = doParserFunc(funcInfo);
if(!funcObj){
return null;
} let package = doLoadPackage(funcObj.packageName);
if(!package){
return null;
} let module = doLoadModule(pacakge,funcObj.moduleName);
if(!module){
return null;
} let func = module[funcObj.functionName];
if(!func){
return null;
} return func;
}
  • 异步版本
function loadFunc(funcInfo, onComplete){
if(!funcInfo){
return onComplete(RESULT.INVALID_PARAMETER);
} let funcObj = doParserFunc(funcInfo);
if(!funcObj){
return onComplete(RESULT.PARSE_ERROR);
} doLoadPackage(funcObj.packageName, function(err,package){
if(!package){
return onComplete(RESULT.LOAD_PACKAGE_FAILED);
} doLoadModule(package, funcObj.moduleName, function(err, module){
if(!module){
return onComplete(RESULT.LOAD_MODULE_FAILED);
} let func = module[funcObj.functionName];
if(!func){
return onComplete(RESULT.FUNC_NOT_EXIST);
} onComplete(RESULT.SUCCESS,func);
});
});
}

语义分析

编程语言提供的if/else结构,有两种基本的用法:

  • 优先考虑满足条件就做什么
if(condition){
doSomething();
}else{
logError();
}
  • 优先考虑不满足条件就处理错误
if(!condition){
logError();
}else{
doSomething();
}

这两种结构,各自都能写出逻辑严密的代码。例如,在前一种优先模式下,一种重要的方式把所有的if分支都写下它的else分支,保证逻辑上少漏洞。典型的控制结构是这样的:

if(condition1){
// <a>
if(condition2){
// <b>
if(condition3){
// <c>
if(condition4){
// <d>
doSomething1();
}else{
// <e>
doSomething2();
}
}else{
// <f>
doSomething3();
}
}else{
// <g>
doSomething4();
}
}else{
// <h>
doSomething5();
}

这种结构确实也能更直接的和大脑里的流程结构对上,如果勤快一点画流程图,也能直接对上。程序是会根据需求变化的,在需求变化的时候,很容易在上述<a><b>, ...处产生碎片代码,此时如果对上一节介绍的函数分层有比较好的实施,则代码依然保持良好的可读/可维护。

但是,在混合了同步、异步之后,即使有了良好的函数组织,也还是容易出现嵌套深的情况,此时,可以配合适当的guard结构去组织代码。使用guard语句,可以让代码更加线性化。具体在情景代码中应该使用哪种方式,就是一种编程中的选择问题。如果考虑一致性,最好一个模块保持一致。

控制结构(2) 卫语句(guard clause)的更多相关文章

  1. 控制结构(2): 卫语句(guard clause)

    // 上一篇:分枝/叶子(branch/leaf) // 下一篇:状态机(state machine) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. 典型代码: 同步版本 f ...

  2. Replace Nested Conditional with Guard Clauses(用卫语句代替嵌套循环)

    函数中的条件逻辑,使人难以看清正常的执行路径. 使用卫语句表现所有特殊情况. double getPayAmount() {double result;if (_isDead) result = de ...

  3. java - 策略模式、状态模式、卫语句,避免多重if-else(转)

    前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...

  4. Java重构-策略模式、状态模式、卫语句

    前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...

  5. 【转】Java重构-策略模式、状态模式、卫语句

    前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...

  6. Swift基础之守卫语句guard

    本篇文章翻译自:http://ericcerney.com/swift-guard-statement/原作者:ecerney该语法为swift2.0之后添加的新特性 最开始在Apple的Platfo ...

  7. feilong's blog | 目录

    每次把新博客的链接分享到技术群里,我常常会附带一句:蚂蚁搬家.事实上也确实如此,坚持1篇1篇的把自己做过.思考过.阅读过.使用过的技术和教育相关的知识.方法.随笔.索引记录下来,并持续去改进它们,希望 ...

  8. Effective Scala

    Effective Scala Marius Eriksen, Twitter Inc.marius@twitter.com (@marius)[translated by hongjiang(@ho ...

  9. ruby编程语言-学习笔记5(第5章 语句和控制结构)

    以下是2种表达方式一样. if expression code end if expression then #推荐这种形式 code end expression的值不是false或nil,则cod ...

随机推荐

  1. SpringMVC注解@RequestMapping之produces属性导致的406错误

    废话不多说,各位,直接看图说话,敢吗?这个问题网上解决的办法写的狠是粗糙,甚至说这次我干掉它完全是靠巧合,但是也不否认网上针对406错误给出的解决方式,可能是多种情况下出现的406吧?我这次的流程就是 ...

  2. 011.Adding Search to an ASP.NET Core MVC app --【给程序添加搜索功能】

    Adding Search to an ASP.NET Core MVC app 给程序添加搜索功能 2017-3-7 7 分钟阅读时长 作者 本文内容 1.Adding Search by genr ...

  3. Maven详解(一)------ Maven概述

    1.引言 你能搜到这个教程,说明你对 Maven 感兴趣,但是又不是太理解.那么接下来这个系列的教程将会详细讲解 Maven 的用法,相信你看完之后,一定能对 Maven 的理解更进一步! 2.常规项 ...

  4. python对字符串分割和截取的方法

    对字符串的截取我们可以使用split方法,split是分割的按照不同分隔符来分割 现在我们想对正则匹配的内容进行截取   我们先看一下split怎么实现字符串分割 >>> b='aa ...

  5. 基于Grafana的Repeate Panel快速定义面板

    Grafana提供的Repeate Panel功能,可以快速定义一类相同的面板. 一.定义模板变量 点击"设置"."模板",如下所示: 设置模板变量名称.类型. ...

  6. ubuntu下发布asp.net core并用nginx代理之旅(续)

    前面实现了ubuntu下的发布,然而实际项目一般为visual studio中发布文件系统,然后上传至生产环境中,(部分参考:上传文件到linux - ubuntu) 这节就发布到生产环境中的: 1. ...

  7. 缓存一致性和跨服务器查询的数据异构解决方案canal

    当你的项目数据量上去了之后,通常会遇到两种情况,第一种情况应是最大可能的使用cache来对抗上层的高并发,第二种情况同样也是需要使用分库 分表对抗上层的高并发...逼逼逼起来容易,做起来并不那么乐观, ...

  8. JAVA_多线程_单例模式

    这篇是入职之后的第二篇了,上一篇我简单介绍了一下LOCK里面的类的方法,感兴趣的话可以去了解一下,以后坚持每周至少会更新一篇关于多线程方面的文章,希望博友们可以一起加油成长. 这篇主要的内容是单例模式 ...

  9. 框架整合——Spring与MyBatis框架整合

    Spring整合MyBatis 1. 整合 Spring [整合目标:在spring的配置文件中配置SqlSessionFactory以及让mybatis用上spring的声明式事务] 1). 加入 ...

  10. H5性能测试学习

    工欲善其事,必先利其器,在做H5前端性能测试之前,选择合适的工具能让我们的测试工作事半功倍.本文要提到的工具有两类: 一类是抓包工具,如Fiddler.Charles等.这类工具不仅可以抓包,还可以对 ...