// 下一篇:卫语句(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. DSAPI之摄像头追踪指定颜色物体

    Private CAM As New DSAPI.摄像头_avicap32 Private Clr As Color = Color.FromArgb(230, 50, 50) Private _Lo ...

  2. Odd-e CSD Course Day 1

    First 強烈的建議,記得準備好當地的 SIM 卡及插座轉接頭,在這五天中很好用的 接下來,我就各個主題來介紹一下相關的心得.首先我們這五天裡會依照 Scrum 的流程,完全的跑過一次,從一開始的需 ...

  3. .NET: 使用.NET Core CLI开发应用程序

    要开发.NET Core应用程序,除了使用强大的Visual Studio之外,还可以使用.NET Core CLI..NET Core CLI (Command-Line Interface),也就 ...

  4. Java学习笔记之——异常处理

    1.异常: 在程序运行时,发生了一些错误导致程序不能正常结束或者中断 2.异常导致的后果 Java程序的执行过程中如果出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息,并将其被提交 ...

  5. 委托(2).net 1.x中的委托

    上一篇已经演示了使用委托实现一个多语言问候的程序,这一篇文章来总结一下在.net 1.x中委托的使用方法. 既然委托是一个类型(class),那么它就要经历像类一个先声明,然后new一个对象,最后调用 ...

  6. eclipse自定义工作区列表

    打开eclipse,在菜单栏上找到Window,点击Window--->Perspective--->Customize Perspective...,会看到 弹出来的一个窗口,然后点击最 ...

  7. 前端js 实现文件下载

    https://www.zhangxinxu.com/wordpress/2017/07/js-text-string-download-as-html-json-file/ 侵删 1.H5 down ...

  8. html iframe高度自适应

    想到的一种办法是,在父页面里获取子页面的高度,在父页面onlod里把获取到子页面的高度赋值给父页面iframe标签,不过这种方法感觉不是很好,因为浏览器兼容性不好,获取不到高度 这种方法有两种写法 & ...

  9. 【20190415】JavaScript-事件流与stopPropagation()、stopImmediatePropagation()的误区解析

    这两天仔细看了一下MDN上关于事件流机制和相关方法的文档,发现有个很大的误区.过去我一直以为stopPropagation()就是用来阻止事件冒泡的,甚至很多博客和菜鸟教程上都是这样写的.但实际上文档 ...

  10. JS 事件绑定,监听,委托(代理)

    我们经常会遇到JavaScript的事件机制,例如,事件绑定.事件监听.事件委托(事件代理)等.这些名词是什么意思呢,有什么作用呢? 在JavaScript中,有三种常用的绑定事件的方法: 在DOM元 ...