// 下一篇:卫语句(guard clause)


典型代码:

function doSomething1(){
// ...
}
function doSomething2(){
// ...
}
function doSomething3(){
// ...
}
function doSomething(){
doSomething1();
doSomething2(); // some dirty codes
for(let i in works){
let work = works[i];
work();
} doSomething4();
}

结构分析

此处的问题,// some dirty codes 后面的一段代码逻辑和doSomethins 系列位于同一个抽象层上,但是写代码的人没有意识到这点,于是把细节代码在此处直接展开。改写的方式是:

function doSomething1(){
// ...
}
function doSomething2(){
// ...
}
function doSomething3(){
// ...
}
function doSomething4(){
// some dirty codes
for(let i in works){
let work = works[i];
work();
}
}
function doSomething(){
doSomething1();
doSomething2();
doSomething3();
doSomething4();
}

语义分析

这里的核心是,把函数分层,A->B->C->D,同一层函数只做这层的一件事,上一层的函数则做对下一层函数的组织,每一层为了组织下一层,都会用到顺序、分支、循环三种控制结构。

sequence形式的层组织结构

function doSomething(){
doSomething1();
doSomething2();
doSomething3();
doSomething4();
}

if/else形式的层组织结构

function doSomething(){
if(condition1){
doSomething1();
}else{
doSomething2();
}
}

for形式的层组织结构

function doSomething(){
doSomething1();
doSomething2();
for(let i in somethings){
let something = somethings[i];
something();
}
doSomething4();
}

你可以尝试把上面三种结构里,把某个doSomethingi();的代码就地展开,你会发现代码的组织变的不清晰,理解的时候就会累(阅读的时候,你会倾向于认为一行代码和一行代码之间是等价粒度的,但是显然,展开某个doSomethingi()后,doSomethingi()的细节代码的任意一行和doSomethingj()之间的粒度不同,如果你随机展开其中部分doSomethingi(),代码会变的更糟糕,看上去「繁杂」,其实这是不必要的。

在A->B->C->D这样的结构里,任意两层可以看作是分枝/叶子双层结构。

例如A->B,那么,如果你把应该在B层的逻辑代码写到A层的函数里,A层的一个函数里就会同时存在下面两种类型代码的混合:

  1. 对B层函数的调用代码
  2. 一段本来应该在B层做的逻辑代码的直接展开

这样的代码能运行,但是可读性差,不利于阅读和维护,因为每次通过阅读把一个函数里的上述两种逻辑代码“理解”出来,这增加了成本。而如果分层良好,阅读的时候就会流畅,理解清晰,也更不容易出BUG,你只需要关注:

  1. A/B层分别在自己那层只做一件事。
  2. 当前层的if/else/for基本控制结构是否合理。
  3. 如果A层函数里需要知道某个B层的细节,去B层函数查找即可。
  4. 不追求一层函数内部的代码量少,而是层次清晰,只做这层的一件事这个语义的实施。

我在实际编程中重构过许多此类代码,当层层把这种结构梳理清晰之后,代码的可读性/可维护性就得到了一次梳理。

控制结构(1): 分枝/叶子(branch/leaf)的更多相关文章

  1. 控制结构(1) 分枝/叶子(branch/leaf)

    // 下一篇:卫语句(guard clause) 典型代码: function doSomething1(){ // ... } function doSomething2(){ // ... } f ...

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

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

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

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

  4. feilong's blog | 目录

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

  5. 机器学习算法 --- Decision Trees Algorithms

    一.Decision Trees Agorithms的简介 决策树算法(Decision Trees Agorithms),是如今最流行的机器学习算法之一,它即能做分类又做回归(不像之前介绍的其他学习 ...

  6. Atitit 常见的树形结构 红黑树  二叉树   B树 B+树  Trie树 attilax理解与总结

    Atitit 常见的树形结构 红黑树  二叉树   B树 B+树  Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...

  7. SQL Server中的索引

    1 SQL Server中的索引 索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度.索引包含由表或视图中的一列或多列生成的键.这些键存储在一个结构(B 树)中,使 SQL Serve ...

  8. Oracle性能优化之SQL语句

    1.SQL语句执行过程 1.1 SQL语句的执行步骤 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. ...

  9. Oracle 11G INDEX FULL SCAN 和 INDEX FAST FULL SCAN 对比分析

    SQL> drop table test; 表已删除. SQL> create table test as select * from dba_objects where 1!=1; 表已 ...

随机推荐

  1. [.NET] 《Effective C#》快速笔记(二)- .NET 资源托管

    <Effective C#>快速笔记(二)- .NET 资源托管 简介 续 <Effective C#>读书笔记(一)- C# 语言习惯. .NET 中,GC 会帮助我们管理内 ...

  2. Java开发笔记(四十)日期与字符串的互相转换

    前面介绍了如何通过Date工具获取各个时间数值,但是用户更喜欢形如“2018-11-24 23:04:18”这种结构清晰.简洁明了的字符串,而非啰里八唆依次汇报每个时间单位及其数值的描述.既然日期时间 ...

  3. windows安装elasticsearch

    1. 去官网 https://www.elastic.co/cn/ 下载 注意: ES对JDK版本有较高的要求,5.x及以上版本需要JDK8支持,本人此次使用2.4.6版本2. 下载后,JDK先安装, ...

  4. js autocomplete输入延迟触发执行事件

    需求:延迟查询,autocomplete延迟触发执行事件.当有下一个事件开始时,本次事件中断.目的是为了防止调用服务器过于频繁. var timeout = 0;//延时处理 $("#cus ...

  5. 【代码笔记】Web-CSS-CSS id和Class选择器

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  6. iOS----------拨打电话的3种方式

    iOS实现拨打电话的方式:   方法一.requestWithURL,此方法拨打前弹出提示 NSMutableString * string = [[NSMutableString alloc] in ...

  7. Android获取定位权限,获取设备所在的经纬度

    转载请标明出处:http://www.cnblogs.com/tangZH/p/8969898.html  前言: 有时候我们仅仅是想要获取设备所在的经纬度,那么直接调用Android相关的api就可 ...

  8. 最简单打开三星note8三星galaxy susb调试模式的方法

    每当我们使用安卓手机连接PC的时候,如果手机没有开启usb调试模式,PC则无办法成功检测到我们的手机,部分APP也无办法正常使用,这时我们需要找处理方法将手机的usb调试模式开启,以下内容我们介绍三星 ...

  9. 理解java的三种代理模式

    代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象的功能扩展. 比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing(). 1 public class ...

  10. SQLServer之创建隐式事务

    隐式事务创建注意事项 IMPLICIT_TRANSACTIONS为 ON 时,系统处于“隐式”事务模式. 这意味着如果 @@TRANCOUNT = 0,下列任一 Transact-SQL 语句都会开始 ...