版权全部 © 2018 林鹏程, 保留全部权利。html
最近,在微信群里介绍纯函数管道数据流时,回群友关于构造方法的提问,整理一下,放这里。java
纯函数管道数据流是我在我的项目实践过程总结创造出来的方法,基于个人知识体系,融合了集成电路、科学化管理思想、大工业流水线思想、函数式编程(FP)、统计学R语言的向量式编程等技术,在系统构造过程当中的抽象、策略选择判断过程应用了科学化管理思想、大工业流水线思想来作为依据,是最契合个人思惟方式的方法,不是象那些FP和OO狂信徒从外来的理论学习、沉迷、洗脑、走火入魔的状态:-)。算法
大海航行靠舵手,编程朝着数据走。初始状态,最终状态,两点间直线距离最短。 沿着数据变换造成的数据流,沿途汇流,直至最终状态,这叫百川东到海、结果导向、直指大道。天下武功,惟快不破。 简单直接是快速稳定可靠的根本。FP和OO其实全是在走弯路 :-)。编程
纯函数管道数据流方法是使项目纯粹由->>
块组成,一个->>
块函数至关于一个集成电路元件(或板),这样整个项目象个集成电路(或城市水网,或企业制度流程)。代码示意图化和象形化 对系统架构逻辑和流程相似所见即所得,对阅读、理解、优化颇有帮助。每一步都是可测试、可验证,代码重用和组合很是的爽,逻辑也很简洁清晰,系统构造、调试、扩展、维护、使用也能够引用成熟的集成电路理论。数组
数据流设计时,要特别注意设立函数输入输出的数据规范标准,按大工业标准化生产模式。微信
由于Clojure
语言对纯函数管道数据流提供了语言级核心支持,有不少种类的->>
宏,写纯函数管道数据流最天然最方便,因此如下内容的代码用Clojure
语言表达。数据结构
1.元件:一个->>
块函数至关于一个集成电路元件(或板),利用纯函数的输入输出特性看成管道(导线)使用。架构
一个->>
块里面的一系列函数,最多只能有一个带反作用的函数且只能处于末尾。另外,要注意作好数据标准化工做,在出入口检查,中间就能够极限裸奔,这样作简洁、流畅、稳定、高效。并发
通常只有在带反作用的函数里才有try-catch
异常处理,异常处理是个垃圾机制,我不喜欢try-catch
异常机制,使用try-catch
异常机制也只是为了兼容系统外部的库、语言和平台的异常机制而已,对外来的只能接受,只能管好本身。在数据流里,一切用数据解决,能够接着向下传递数据信号表达情况,这种思想相似C语言的错误号数据传递机制。经典的计算机技术不少是很好的,好比数据结构+算法,错误号等。一帮不知所谓的家伙炒做出FP/OO/异常等一堆垃圾,为创新而创新,为paper而创新。函数式编程
在clojure
语言里,建议函数尽可能设计成参数为hash-map类型的单参数函数,象R
语言大多数函数那样,能够设计不少带默认值的命名参数,有很强的可扩展性。另外,clojure
操做hash-map的核心函数不少,操做方便,不只在使用->>宏时能够不用写括号,并且参数的造成,校验,变换与函数调用一体化、一条龙数据流处理。还有clojure
解构方便,在函数体内形式参数使用上与通常多参数函数是同样方便的。
(defn f [x] (->> x f1 f2))
(defn f [{:keys [x y] :as m}] (->> x (f1 y ,) f2))
2.分支:一个(cond)或(if)块做为一个函数。代码示意:
(defn f [x] (cond (= x 1) (f1) (= x 2) (f2) :else (f3)))
(defn f2 [x y] (-> (> x 2) (and , (< y 6)) (if , 25 30)))
(defn path-combine [s1 s2] (cond (string/starts-with? s2 "/") s2 (not (string/ends-with? s1 "/")) (-> (string/split s1 #"[\\/]") butlast (#(string/join "/" %)) (str , "/") (path-combine , s2)) :else (-> (string/join "/" [s1 s2]) (string/replace , #"[\\/]+" "/"))))
3.反馈电路(回流):一个尾递归函数至关于一个反馈电路。备注:map是批处理,另外也能够当作相似对一个游客队列,在入口重复进行验票动做,是一个前进动做,不是反馈或回流。
(defn f [i] (if-not (zero? i) (f1) (-> i dec recur)))
4.分流:至关于并发或并行。例如:对数据进行分块,并行处理,代码示意:
(->> data (partition n ,) (pmap f ,))
(->> [pipe-f1 pipe-f2 pipe-f3] (pmap #(% data) ,))
5.合流:至关对分流的结果进行reduce,联合后的代码示意:
(->> data (partition n ,) (pmap f1 ,) (reduce f2 ,))
注1:和其余数据流的区别:
之前也曾出现不少数据流思想,但实现和设计都很不理想,从代码上看与集成电路相差极远。纯函数管道数据流clojure最合适,从语义和表现形式上看,都是最简单直观的。下面附带一个代码比较连接:
1.个人数据流代码大概是这个形式:
https://clojureverse.org/t/ho...
通常是一个->>
块一个函数。
2.对比一下akka的数据流:
https://doc.akka.io/docs/akka...
咱们能够看出它们代码的象形和逻辑上的差距,akka代码与文章里的集成电路示意图形式上差距很大。
更不用说Rxjava那种丑爆的代码
注2:与ring middleware区别
代码看起来类似,但理念是本质上的差异。
1.middleware函数的输入输出是函数,流转的是层层打包的函数,是同心圆,middleware调试是很麻烦的。
2.纯函数管道数据流输入输出是数据,流转的是数据,是串并联。
3.我不能认同中间件的理念,和集成电路思想是冲突的。电路里,元件(电路板)是没法流转的,只有数据(电流)才能流转,理解不要有误差。
注3:本文主讲系统构造,不在于精妙的代码,文章内是伪代码,整个软件工程100%由纯粹的->>
块构成才是重点,也是难点, ->>
宏使用这种语法不是重点,->>
构造系统是一种流程优化,使数据和逻辑分离得很清楚,达到科学、简单、灵活的架构。不用->>
架构的架构数据和逻辑混杂,我称为“可怕的泥石流”。
最后,大道至简,这种系统构造方法看起来方法很简单,象自由博击和形意拳同样,只有基本元件和基本组合方法,须要把基本功练成本能,神而明之、触之即发、变幻无穷的应用,不要用固定的模式限制本身的想象力,没有FP和OO那么多套路和招数,可是对数据抽象和逻辑抽象的要求比FP还要高得多,辅之道法天然、变幻无穷、天马行空的想像力和创造力。
作一件好事很容易,一生纯作好事很难。写一个纯函数管道数据流函数很容易,写一个100%由纯函数管道数据流函数组成的系统很难。
看到能把FP用来工做的人数那么少,我是不期望本方法能流行,但发表出来,若是能帮助他人开拓思想,有所得益,仍是一件使人快乐的事。