abbshr.github.io icon indicating copy to clipboard operation
abbshr.github.io copied to clipboard

管道连接未来

Open abbshr opened this issue 9 years ago • 0 comments

最近一直在忙, 闲暇之余也是东瞧西看, 涉略了不少新鲜的东西, 也无一例外都在广度而非深度. 我工的大三课程安排让生活很惬意, 今早刷了一圈~~全球最大的同性交友网站~~github, 偶遇event-stream, 将stream和functional programming结合, 充分发挥了Node stream和event driven pattern的优势和特点, 也体现了Unix中经典的设计哲学"do one thing and it well".

我喜欢这种编程方式, 这是一种符合人类原始思维的线性模式, 也就是说它属于synchronization. 并不是说我讨厌Node的asynchronous, 相反, 我觉得它(后者)更符合世界的本质(正如朴灵所言), 而事件恰巧就是连结异步空间的"虫洞", 把某一次元发生的情况直接传送到另一次元. 二者的有机结合成就了Node在I/O上的高效.

然而总是事与愿违, 纯粹异步编程并不是那么容易掌握的, 事件有可能在任意时间发生, 为了组织程序的逻辑, 你不得不在每个事件触发点上挂载庞杂的处理逻辑甚至进一步的事件监听. 能想象那些古早的黑暗年代里人们是怎么进行异步编程的吗?... 是的, 不能清晰的组织异步逻辑将使programming陷入地狱.

要同步还是要异步? 换句话说如何更好的利用事件和异步? 然而聪明的coder早已享受过诸如async, Q, promise, generator, coroutine等辅助带来的便利了. 从某种意义上讲, 这些宝贝已经解决了厄运金字塔和混乱的异步逻辑带来的痛苦: 化异步为同步. 其实Node中的pipe就是多数异步流次序控制的原型. 很多人喜爱管道设计模式, 因为这让开发者更专注于代码的核心逻辑而非前奏和尾声, 也让程序的职能划分的更加清楚.

管道连接一切, 这是美好的夙愿, 更让人兴奋的是去年已经有人开始将streaming programming作为标准编程范式代入一门新的语言了: matz的streem, 其中融入了管道, 流, 函数式编程的思想. 想象一下这种代码: (取自streem example)

# unix cat
STDIN | STDOUT

# simple echo server on port 8007
tcp_server(8007) | {s ->
  s | s
}

# seq(100) returns a stream of numbers from 1 to 100.
# A function object in pipeline works as a map function.
# STDOUT is an output destination.
seq(100) | {x ->
  if x % 15 == 0 {
    "FizzBuzz"
  }
  else if x % 3 == 0 {
    "Fizz"
  }
  else if x % 5 == 0 {
    "Buzz"
  }
  else {
    x
  }
} | STDOUT

换成Lisp系的函数式写法可能是这样:

(output (fizzbuzz (seq 100)))

函数式编程在解决许多问题上已经很直接了, 但我觉得相比管道的写法仍偏晦涩, 类Shell pipeline的写法无疑更易懂易写.

相比Node的I/O pipeline, streem把pipeline带到整个程序而不仅仅局限在I/O上. 看着仍处于开发中的streem, Noder们可能相视一笑了, 因为Node这边蓬勃的社区里, 早已经有这方面的实现了: eventstream库, 这是一种典型的用管道控制异步流工作次序的思路.

  var es = require('event-stream')
  var inspect = require('util').inspect

  process.stdin                        //connect streams together with `pipe`
    .pipe(es.split())                  //split stream to break on newlines
    .pipe(es.map(function (data, cb) { //turn this async function into a stream
      cb(null
        , inspect(JSON.parse(data)))   //render it nicely
    }))
    .pipe(process.stdout)  

(代码摘自eventstream第一个示例)

与streem相比, eventstream有点更偏函数式了, 不过仍然很好的诠释了streaming + functional programming的力量.

从我个人角度确实很看好pipe, 然而时刻记住误用会让你对其产生厌恶, 而厌恶将使你失去学习的机会!, 它对于coding而言也仅仅是一种design pattern, 不可能是万能药, 对不同的场景应用合适的模式才能极尽其能.

abbshr avatar Jun 12 '15 08:06 abbshr