Unix Pipes

Unix管道扫描稿

简单样例:

$ netstat -apn | grep 8080

相信这个大家经常使用,这里就不细说了。

那么管道基本思想是什么呢?

  • 让每个程序只完成一件事,并将其做好(do one thing and do it well),完成一个新任务,新建一个程序,而不是在旧程序中添加新特性
  • 标准化每个程序的输入和输出,让任意符合标准的程序可以串在一起(write programs to work together)
  • 设计和创造软件,而不是架构或系统

NodeJS Stream

NodeJS中引入流概念来解决I/O异步问题,如果没有Stream,我们可能要这么写代码:

  1. var http = require('http');
  2. var fs = require('fs');
  3. // 著名的回调地狱又来了
  4. var server = http.createServer(function (req, res) {
  5. fs.readFile(__dirname + '/data.txt', function (err, data) {
  6. res.end(data);
  7. });
  8. });
  9. server.listen(8000);

但有了Stream,我们就可以更优雅的编写代码:

  1. var http = require('http');
  2. var fs = require('fs');
  3. var server = http.createServer(function (req, res) {
  4. var stream = fs.createReadStream(__dirname + '/data.txt');
  5. // 把两个管子接起来
  6. stream.pipe(res);
  7. });
  8. server.listen(8000);

想添加一个新功能?要用gzip压缩文件?OK,可以这么写:

  1. var http = require('http');
  2. var fs = require('fs');
  3. var oppressor = require('oppressor');
  4. var server = http.createServer(function (req, res) {
  5. var stream = fs.createReadStream(__dirname + '/data.txt');
  6. // 将三个管子连起来
  7. stream.pipe(oppressor(req)).pipe(res);
  8. });
  9. server.listen(8000);

Back-end to Font-end

随着EventStream、Gulp、Webpack管道在后端的盛行,管道逐渐从后端向前端渗透,如Angular、Vuejs。我们在Q.js、高可扩展数据层组件DB.core中大量使用了管道过滤器(Pipe-And-Filter)模式。

(webpack的核心:管道式插件)

那么前端的管道又是怎样的呢?让我们看看DB.core中的例子。

Pipes in DB.core

DB的设计初衷在于解决CGI拉取的通用性问题,例如:区分正确和错误逻辑、通用错误逻辑处理、登陆态通用处理。但DB却难以复用,因为我们发现每个业务的通用性各不相同,通常我们新起一个业务总是要将DB复制下来后做大量侵入式修改,才能适用于新的业务要求。而在齐齐互动视频中,我们例如管道过滤器模式重构了我们的DB。 具体请参见:https://github.com/miniflycn/db

问题在哪里?
  • Rule of Simplicity: Design for simplicity; add complexity only where you must.
  • Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.

DB干了太多事情,导致每次干一件事情就要插入各种代码。通过管道过滤器模式,将每件事情拆成独立的过滤器,每个过滤器只做一件事,但将一件事情做到极致。

单一功能原则(Single responsibility principle)规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。所有它的(这个类的)服务都应该严密的和该功能平行(功能平行,意味着没有依赖)。

马丁把功能(职责)定义为:“改变的原因”,并且总结出一个类或者模块应该有且只有一个改变的原因。一个具体的例子就是,想象有一个用于编辑和打印报表的模块。这样的一个模块存在两个改变的原因。第一,报表的内容可以改变(编辑)。第二,报表的格式可以改变(打印)。这两方面会的改变因为完全不同的起因而发生:一个是本质的修改,一个是表面的修改。单一功能原则认为这两方面的问题事实上是两个分离的功能,因此他们应该分离在不同的类或者模块里。把有不同的改变原因的事物耦合在一起的设计是糟糕的。

——from wiki

前端常用的管道过滤器模式基本实现
  1. /**
  2. * _apply
  3. * @param {Array} handles 处理函数列队,每一个是一个管子
  4. * @param {*} data 要处理的数据
  5. * @param {Object} options 可选参数
  6. * @param {Function} cb 处理后回调
  7. */
  8. _apply: function (handles, data, options, cb) {
  9. var i = 0,
  10. l = handles.length,
  11. res = data;
  12. for (i; i < l; i++) {
  13. res = handles[i].call(this, res, options);
  14. // if handle return false, just break
  15. if (res === false) return;
  16. }
  17. cb(res);
  18. },
db.core完整实现
  1. var $ = require('jquery');
  2. /**
  3. * DB
  4. * @class
  5. * @param {Object} options this is just a $.ajax setting
  6. * @param {Array} options.errHandles
  7. * @param {Array} options.succHandles
  8. * @param {Function} options.succ
  9. * @param {Function} options.err
  10. */
  11. function DB(options) {
  12. this._init(options);
  13. }
  14. $.extend(DB.prototype, {
  15. _init: function (options) {
  16. this.errHandles = options.errHandles || [];
  17. this.succHandles = options.succHandles || [];
  18. this.errHandles.unshift.apply(this.errHandles, DB.options.errHandles || []);
  19. this.succHandles.unshift.apply(this.succHandles, DB.options.succHandles || []);
  20. options = $.extend({}, DB.options || {}, options);
  21. this.options = options;
  22. },
  23. _wrap: function (options) {
  24. var self = this;
  25. options.success = function (data) {
  26. // you may want to modify this line for judging error or success
  27. data.retcode === 0 ?
  28. self._apply(self.succHandles, data, options, options.succ) :
  29. self._apply(self.errHandles, data, options, options.err);
  30. };
  31. options.error = function (data) {
  32. self._apply(self.errHandles, data, options, options.err);
  33. };
  34. return options;
  35. },
  36. _apply: function (handles, data, options, cb) {
  37. var i = 0,
  38. l = handles.length,
  39. res = data;
  40. for (i; i < l; i++) {
  41. res = handles[i].call(this, res, options);
  42. // if handle return false, just break
  43. if (res === false) return;
  44. }
  45. cb(res);
  46. },
  47. /**
  48. * ajax
  49. * @param {Object} options this is just a $.ajax setting
  50. * @param {Function} options.succ
  51. * @param {Function} options.err
  52. */
  53. ajax: function (options) {
  54. options = this._wrap($.extend({}, this.options, options));
  55. !options.data &&
  56. (options.data = options.param);
  57. $.ajax(options);
  58. }
  59. });
  60. $.extend(DB, {
  61. httpMethod: function (options) {
  62. var db = new DB(options);
  63. return function (opt) {
  64. db.ajax(opt);
  65. return this;
  66. };
  67. },
  68. extend: jQuery.extend,
  69. // default options
  70. options: {}
  71. });
  72. module.exports = DB;

这样我们就可以把以前的各种业务数据检测,甚至是数据组装都放在succHandles和errHandles进行。这是我们在齐齐项目中使用的一个例子,可以看见,我们把数据组装也放在了DB层进行。

Unix Pipes to Javascript Pipes的更多相关文章

  1. Sqlserver 远程连接的 TCP/IP 和 Named Pipes的区别

    TCP/IP:  TCP/IP是 Internet 上广泛使用的通用协议.它与互连网络中硬件结构和操作系统各异的计算机进行通信.TCP/IP包括路由网络流量的标准,并能够提供高级安全功能.它是目前在商 ...

  2. hadoop下的Pipes(用C++进行hadoop程序开发)

    说明:这篇博客来自我的CSDN博客:http://blog.csdn.net/lxxgreat/article/details/7755369 经过一上午的努力,终于以伪分布式模式运行了C++版的Ma ...

  3. 搭建及修正Hadoop1.2.1 MapReduce Pipes C++开发环境

    Hadoop目前人气超旺,返璞归真的KV理念让人们再一次换一个角度来冷静思考一些问题. 但随着近些年来写C/C++的人越来越少,网上和官方WIKI的教程直接落地的成功率却不高,多少会碰到这样那样的问题 ...

  4. Haskell语言学习笔记(83)Pipes

    安装 pipes $ cabal install pipes Installed pipes-4.3.9 Prelude> import Pipes Prelude Pipes> impo ...

  5. 在Hadoop 2.3上运行C++程序各种疑难杂症(Hadoop Pipes选择、错误集锦、Hadoop2.3编译等)

    首记 感觉Hadoop是一个坑,打着大数据最佳解决方案的旗帜到处坑害良民.记得以前看过一篇文章,说1TB以下的数据就不要用Hadoop了,体现不 出太大的优势,有时候反而会成为累赘.因此Hadoop的 ...

  6. 【计算几何】【二分图判定】Gym - 101485C - Cleaning Pipes

    题意:有n个水井,每个水井发出一些管线(都是线段),然后每条管线上最多只有一个水井.所有从不同的水井发出的管线的相交点都是清洁点(不存在清洁点是大于两条管线点的交点).你需要在某些管线上放出一些机器人 ...

  7. js 取得 Unix时间戳(Unix timestamp)

    js 取得 Unix时间戳 Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间19 ...

  8. 时间:UTC时间、GMT时间、本地时间、Unix时间戳

    转自:http://blog.csdn.net/u012102306/article/details/51538574 1.UTC时间 与 GMT时间 我们可以认为格林威治时间就是时间协调时间(GMT ...

  9. 简述unix时间戳

    unix时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒. Unix时间戳(英文为Unix epoch, Unix time, POSIX time 或 Unix ti ...

随机推荐

  1. Java 第六章 循环结构2

    循环结构 2 会使用 for 循环结构 会在程序中使用 break 和 continue for 比 while 更简洁 什么是 for 循环 ... 语法: for 循环的语法和执行顺序 备注:2条 ...

  2. Find Minimum in Rotated Sorted Array II leetcode

    题目链接 这个博客的算法思想简单好! 还是贴上自己的蹩脚代码吧!! class Solution { public: int findMin(vector<int>& nums) ...

  3. wav文件格式分析(一)

    (一)概述 WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范: (二)音频知识 1.常见的声音文 ...

  4. 6.5 为什么Android用Java不用c实现?

    C/C++过于底层,开发者要花很多的经历对C/C++的语言研究清楚,例如C/C++的内存机制,如果稍不注意,就会忘了开启或者释放.而Java的GC会自动处理这些,省去了很多的时间让开发者专注于自己的业 ...

  5. 数据库知识整理<四>

    使用DML语句更改数据: 所谓DML语句是指数据库操作语句,其中包括的是对数据库数据的修改.删除.插入. 4.1添加新数据: 插入单行的记录:基本的SQL语句为-insert into <表明& ...

  6. ORACLE之ASM学习

    ASM(Automatic Storage Management)是Oracle10g R2中为了简化Oracle数据库的管理而推出来的一项新功能,这是Oracle自己提供的卷管理器,主要用于替代操作 ...

  7. [转]编译VC++程序warning C4819快速解决

    文章来自:http://www.cppblog.com/API/archive/2012/11/12/195056.aspx 编译VC++程序的时候出现如下提示警告: warning C4819: T ...

  8. Windows2003 架设VPN服务

    一.确保Windows防火墙关闭. 在我的电脑上右键=>管理,在左边窗口找到“服务和应用程序”,展开,单击“服务”,在右边窗口中找到“Windows Firewall/Internet Conn ...

  9. paip.自定义java 泛型类与泛型方法的实现总结

    paip.自定义java 泛型类与泛型方法的实现总结 ============泛型方法     public static <atiType,retType> retType reduce ...

  10. iOS开发-- 开发环境,证书和授权文件

    一.成员介绍 1.    Certification(证书)证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种:1)    Developer Certification(开发证书)安装在电脑 ...