// 上一篇:线性化(linearization)

// 下一篇:指令序列(opcode)


最近阅读了酷壳上的一篇深度好文:LINUX PID 1 和 SYSTEMD。这篇文章介绍了systemd干掉sysvinit和UpStart的故事,作者在自己对三者深入理解的基础上对systemd所解决的问题做了精彩的解说。我也觉的systemd干的漂亮,把系统初始化过程中能并发的过程尽一切可能并发了,而且还能保持构架上的优雅,可见往往复杂事物的最佳解法本身也会是一个漂亮的结构。我也去阅读了下systemd作者对各种质疑的答疑文章:The Biggest Myths,从文章中的描述来看,systemd非但没有违背Unix的管道(pipeline)思想,如果说一个组件是一个齿轮,那么它把那么多的齿轮完美的拼接在一起,不正是管道思想的最佳体现么?

In Unix-like computer operating systems, a pipeline is a sequence of processes chained together by their standard streams, so that the output of each process (stdout) feeds directly as input (stdin) to the next one.

现在的工作中,在工程实践上,我会比较注意去思考那些看上去随意的工作怎样用经过设计(解决方案)的脚本系统/命令行工具统一解决,使得一个团队工作中日常运行每天都要流转的那些部分被经过设计的机器逻辑替代,从而规避低水平人工操作,消除低水平人工操作,通过解决问题进而提高效率。当然,不是所有人都看得到这些部分,有时候,你需要把东西做出来,切实改变了工程师团队的痛点和效率,工程师们才会体会到经过设计的工具所带来的好处。积累多了之后,以后可以慢慢再展现这些过程。

日常工作代码里,实际上也有许多在函数级别可以体现的管道思想,例如下面这段改造自实际代码的示例(原始代码在需求变更,BUG解决中琐碎的多,此处简化示例,也跟我挺长时间没写非C++代码,导致有些地方重复出现以前犯过的低阶错误有关):

function onResponse(err, obj){
if(this.bindable()){
if(err){
this.unCommitBindInfo(obj.bindInfo);
this.unCommitInfo(obj.info);
doComplete(err);
return;
} this.commitBindInfo(obj.bindInfo,(err)=>{
if(err){
this.unCommitBindInfo(obj.bindInfo);
doComplete(err);
return;
} this.commitInfo(obj.info, (err)=>{
if(err){
this.unCommitInfo(obj.info);
}
doComplete(err);
});
});
}else{
if(err){
this.unCommitInfo(obj.info);
doComplete(err);
return;
}
this.commitInfo(obj.info, (err)=>{
if(err){
this.unCommitInfo(obj.info);
}
doComplete(err);
});
}
} function doComplete(err, obj){
if(err){
this.m_complete({result:err});
}else{
this.m_complete({result:RESULT.SUCCESS, obj:obj})
}
}

在切换到动态语言的过程中,我发现一个意思的事情。就是很长一段时间写C++代码的程序员,在切到动态语言的时候,会经历一个返祖现象。以前在静态语言里锻炼的模块化/代码洁癖会在一段时间内因为动态语言带来的便利而出现暂时性丢失,例如:不用class,随手写出一个充满全局函数的能工作的“脚本”;随处使用魔数,拼接路径而不是集中配置管理...;当然,毕竟不是新手,在大家发现问题的时候,及时同步了下共通的问题后,大部分人还是能及时纠正过来。

上述代码是一种常见的逻辑分枝:在一段处理逻辑里有两种可能的大分枝,例如此处是被if(this.bindable())所分开的,第一个分支里会处理obj.bindinfo相关的逻辑后再处理obj.info相关的逻辑;第二个分支里则只处理obj.info相关的逻辑,那么其实两个分支处理obj.info部分的逻辑是重复的。一不小心就会直接用if-else把两个分支分开写,然后随着需求变更,两个分支里的碎片代码会变的繁杂,一段时间之后自己会觉得不可维护。

想清楚这点后,我们可以改变控制结构,使用管道(pipeline)的思想来改进。那就是,在抽象概念上,让这个流程变成一定先处理obj.bindinfo,再处理obj.info的流式处理。如果有更多的流程,可以继续串下去,这样它们就构成一个管道。

改进后的代码如下:

function onResponse(err, obj){
this.processBindInfo(err,obj,(err)=>{
this.processInfo(err,obj,(err)=>{
this.doComplete(err);
});
})
} function processBindInfo(err,obj,callback){
this.tryCommitBindInfo(err,obj,(err)=>{
if(err){
this.unCommitBindInfo(obj.bindInof);
}
callback(err);
})
} function processInfo(err,obj,callback){
this.tryCommitInfo(err,obj,(err)=>{
if(err){
this.unCommitInfo(obj.info);
}
callback(err);
});
} function tryCommitBindInfo(err, obj, callback){
if(!this.bindable()){ // 1. 消灭在这里
callback(err);
return;
} if(err){ // 2. 错误处理
callback(err);
return;
} this.commitBindInfo(obj.bindInfo,(err)=>{
callback(err);
});
} function tryCommitInfo(err, obj, callback){
if(err){ // 2‘. 错误处理
callback(err);
return;
} this.commitInfo(obj.info,(err)=>{
callback(err);
});
} function doComplete(err, obj){
if(err){
this.m_complete({result:err});
}else{
this.m_complete({result:RESULT.SUCCESS, obj:obj})
}
}

上述代码里,processBindInfoprocessInfo两个处理分支分别只处理自己哪个分支的事情,如果不需要处理,则让数据流(err)通过callback透传(pass-through)下去即可。可以看到在tryCommitBindInfo1这个地方,就把本来做大分枝用的bindable消灭掉了。而在tryCommitBindInfotryCommitInfo两个分支里的2位置以及2‘位置,则分别是两个处理流程里对错误的处理。

有时候,我觉的很多重构过程似成相识,应该是以前也干过同样的事情。所以,我想记录下来是比较重要的,记录下来常常review。

控制结构(9): 管道(pipeline)的更多相关文章

  1. 控制结构(9) 管道(pipeline)

    // 上一篇:线性化(linearization) // 下一篇:指令序列(opcode) 最近阅读了酷壳上的一篇深度好文:LINUX PID 1 和 SYSTEMD.这篇文章介绍了systemd干掉 ...

  2. [Linux] 流 ( Stream )、管道 ( Pipeline ) 、Filter - 笔记

    流 ( Stream ) 1. 流,是指可使用的数据元素一个序列. 2. 流,可以想象为是传送带上等待加工处理的物品,也可以想象为工厂流水线上的物品. 3. 流,可以是无限的数据. 4. 有一种功能, ...

  3. Android OpenGL ES(二)OpenGL ES管道(Pipeline) .

    大部分图形系统都可以比作工厂中的装配线(Assemble line)或者称为管道(Pipeline).前一道的输出作为下道工序的输入.主CPU发出一个绘图指令,然后可能由硬件部件完成坐标变换,裁剪,添 ...

  4. [并发并行]_[线程模型]_[Pthread线程使用模型之一管道Pipeline]

    场景 1.经常在Windows, MacOSX 开发C多线程程序的时候, 经常需要和线程打交道, 如果开发人员的数量不多时, 同时掌握Win32和pthread线程 并不是容易的事情, 而且使用Win ...

  5. redis使用管道pipeline提升批量操作性能(php演示)

    Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处理命令并将响应发送回客户 ...

  6. Redis 管道pipeline

    Redis是一个cs模式的tcp server,使用和http类似的请求响应协议. 一个client可以通过一个socket连接发起多个请求命令. 每个请求命令发出后client通常会阻塞并等待red ...

  7. jenkins~管道Pipeline的使用,再见jenkinsUI

    Pipeline在Jenkins里的作用 最近一直在使用jenkins进行自动化部署的工作,开始觉得很爽,省去了很多重复的工作,它帮助我自动拉服务器的代码,自动还原包包,自动编译项目,自动发布项目,自 ...

  8. jenkins~管道Pipeline里使用公用类库

    Pipeline使用了groovy语法,同时可以使用所有jenkins插件在groovy里进行调用,可以说通过UI可以实现的功能使用pipeline也可以实现,这一点我在上一篇文章里已经说明,今天主要 ...

  9. redis管道pipeline

    Jedis jedis = new Jedis("127.0.0.1",6379); Pipeline pipeline = jedis.pipelined(); for(int ...

随机推荐

  1. 【深度学习系列】卷积神经网络CNN原理详解(一)——基本原理

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

  2. NLP入门(七)中文预处理之繁简体转换及获取拼音

      在日常的中文NLP中,经常会涉及到中文的繁简体转换以及拼音的标注等问题,本文将介绍这两个方面的实现.   首先是中文的繁简体转换,不需要使用额外的Python模块,至需要以下两个Python代码文 ...

  3. Spring boot集成spring session实现session共享

    最近使用spring boot开发一个系统,nginx做负载均衡分发请求到多个tomcat,此时访问页面会把请求分发到不同的服务器,session是存在服务器端,如果首次访问被分发到A服务器,那么se ...

  4. Mybatis框架基础支持层——反射工具箱之MetaClass(7)

    简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能 public class MetaClass { ...

  5. PHP代码片段

    将数组拼接为 table 标签字符串 <?php //判断是否是图片 function isImage($string){ $isImage = false; $pics = ['.png', ...

  6. excel 函数1

    1 函数的相对引用和绝对引用 1.1绝对引用,相对引用和混合引用 按住F4键可以相互切换 1.2 if and or函数 案例图片 =IF(C7>30000,"大商家",&q ...

  7. Dynamics 365使用Execute Multiple Request删除系统作业实体记录

    摘要: 本人微信公众号:微软动态CRM专家罗勇 ,回复295或者20190112可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me ...

  8. git第一次提交代码到码云

    转载请标明出处:https://www.cnblogs.com/tangZH/p/10229598.html 不说废话,来看重点. 1.首先注册码云账号,然后建立仓库,这些就直接跳过,很简单. 2.下 ...

  9. ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门

    一.前言 1.本教程主要内容 ASP.NET Core 中间件介绍 通过自定义 ASP.NET Core 中间件实现请求验签 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SD ...

  10. VS2017在线安装包下载

    VS2017个人免费版即社区官方下载地址为:https://download.microsoft.com/download/D/1/4/D142F7E7-4D7E-4F3B-A399-5BACA91E ...