版權全部 © 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用來工做的人數那麼少,我是不期望本方法能流行,但發表出來,若是能幫助他人開拓思想,有所得益,仍是一件使人快樂的事。