控制结构(2) 卫语句(guard clause)
// 上一篇:分枝/叶子(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)的更多相关文章
- 控制结构(2): 卫语句(guard clause)
// 上一篇:分枝/叶子(branch/leaf) // 下一篇:状态机(state machine) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. 典型代码: 同步版本 f ...
- Replace Nested Conditional with Guard Clauses(用卫语句代替嵌套循环)
函数中的条件逻辑,使人难以看清正常的执行路径. 使用卫语句表现所有特殊情况. double getPayAmount() {double result;if (_isDead) result = de ...
- java - 策略模式、状态模式、卫语句,避免多重if-else(转)
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- 【转】Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- Swift基础之守卫语句guard
本篇文章翻译自:http://ericcerney.com/swift-guard-statement/原作者:ecerney该语法为swift2.0之后添加的新特性 最开始在Apple的Platfo ...
- feilong's blog | 目录
每次把新博客的链接分享到技术群里,我常常会附带一句:蚂蚁搬家.事实上也确实如此,坚持1篇1篇的把自己做过.思考过.阅读过.使用过的技术和教育相关的知识.方法.随笔.索引记录下来,并持续去改进它们,希望 ...
- Effective Scala
Effective Scala Marius Eriksen, Twitter Inc.marius@twitter.com (@marius)[translated by hongjiang(@ho ...
- ruby编程语言-学习笔记5(第5章 语句和控制结构)
以下是2种表达方式一样. if expression code end if expression then #推荐这种形式 code end expression的值不是false或nil,则cod ...
随机推荐
- OpenStack(企业私有云)万里长征第六步——OpenStack网络及虚拟机存储位置
一.前言 昨天又装了一遍OpenStack.码农这项工作就如同人生,永远有你想不到的意外在等着你,时而是惊喜时而是悲伤.在装的过程中倒是很顺利,只是在安装完成之后碰到了两个之前没有碰到的问题,这里记录 ...
- js获取节点和编辑的方法
创建新节点 1.创建一个DOM片段createDocumentFragment() 例如: var d=document.createDocumentFragment(); d.appendChild ...
- node.js之setTimeout()、clearTimeout()与 setInterval()与clearInterval()
1.setTimeout函数与clearTimeout函数 setTimeout(cb,ms,[arg],[...])延时一定时间执行回调函数该函数中cb参数为必填函数,为需要执行的回调函数ms为经过 ...
- LinkedList之modCount和expectedModCount
modCount和expectedModCount是用于表示修改次数的,其中modCount表示集合的修改次数,这其中包括了调用集合本身的add方法等修改方法时进行的修改和调用集合迭代器的修改方法进行 ...
- ubuntu下发布asp.net core并用nginx代理之旅
asp.net core 1.0.1发布已有些日子了,怀着好奇的心情体验了把ubuntu下的asp.net core 系统运行环境:ubuntu 16.0.4 for developer 首先搭建.n ...
- SoapUI中读取法文字符
最近测试中,使用SoapUI时需要读取excel中的法文数据作为参数,groovy script中使用的是jxl进行excel的读取, 开始时一直显示乱码,而后在script中添加如下wookbook ...
- Markdown最佳实践
Markdown 最佳实践 结合目前看到的信息,总结使用Markdown的最方便的方式. 我的需求是: 能够配合各种笔记软件使用,目前主要使用的是为知笔记和有道笔记.笔记的内容需要记录代码及数学公式, ...
- wcf 上传文件报413,404和发布错误
上传文件错误: 其实要修改所有的服务,不管是服务端还是客户端,Binding那边增加一个没有设置名字的默认配置就OK了: <binding closeTimeout="00:10 ...
- 设置input框文字垂直居中和宽度
input { solid #999;height:22px; background:#ffffff; line-height:22px; margin:0px; padding:0px;/*表单输入 ...
- Cognos 11.0快速开发指南 Ⅱ
1. 创建报表 在创建好数据源之后,我们就可以创建报表了,报表的开发是浏览器中完成的,这里我选用了chrome浏览器,在地址栏输入:http://localhost:80/ibmcognos ( ...