// 下一篇:卫语句(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语言 APP开发平台——Smobiler学习日志:如何快速实现Timer计时功能

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的”Smobil ...

  2. 第60章 设备流交互服务 - Identity Server 4 中文文档(v1.0.0)

    该IDeviceFlowInteractionService接口旨在提供用户界面用于在设备流授权期间与IdentityServer通信的服务.它可以从依赖注入系统获得,通常作为构造函数参数注入到Ide ...

  3. C# 1-2+3-4+5...+m的几种方法

    class Program { //第一种(1-2)+(3-4)+(5-6)...+m public static void Test(int m) { ; == ) { z = -(m / ); } ...

  4. PhpStorm 安装ApiDebugger

    ApiDebugger,是一个开源的接口调试IntelliJ IDEA插件,具有与IDEA一致的界面,无需切换程序即可完成网络API请求,让你的code更加沉浸式. 安装 File->Setti ...

  5. C-sizeof和strlen区别,以及sizeof如何计算结构体大小

    sizeof和strlen区别 sizeof是关键字,在编译时就能计算出值,可以计算任何类型 strlen是函数,只有在运行时才能去计算,且只能计算字符型的. 对于数组时,strlen是判断’\0’为 ...

  6. 罗汉果与Java虚拟机系列目录与说明

    声    明 罗汉果与Java虚拟机系列博文仅为本银结构性整合Java虚拟机知识的笔记和日常JVM问题的DEBUG记录.放到网上主要是为了方便自己今后查看.顺带能帮助到别人就更奈斯了. 目    录 ...

  7. JavaScript的自定义属性(事件内获得事件外的变量值)

    写轮播图点击下方圆点banBtnLi[i],切换到第i个图片banBtnLi是按钮集合,假设banBtnLi.length是4banImhLi是装图片的li,自然banImgLi.length也是4点 ...

  8. JS实现图片base64转blob对象,压缩图片,预览图片,图片旋转到正确角度

    base64转blob对象 /** 将base64转换为文件对象 * @param {String} base64 base64字符串 * */ var convertBase64ToBlob = f ...

  9. JavaWeb 消息总线框架 Saka V0.0.1 发布

    端午闲着无聊,自己撸了一个简单的框架,可以实现在使用SendClient发送消息,在Spring容器中,符合该消息机制的接收器将能够被执行,目前Saka处于0.0.1版本[Saka-GIthub地址( ...

  10. 微信小程序发红包

    背景: 近期一个朋友公司要做活动,活动放在小程序上.小程序开发倒是不难,不过要使用小程序给微信用户发红包,这个就有点麻烦 确定模式: 小程序目前没有发红包接口,要实现的话,只能是模拟红包,即小程序上做 ...