關於譯者:這是一個流淌着滬江血液的純粹工程:認真,是 HTML 最堅實的樑柱;分享,是 CSS 裏最閃耀的一瞥;總結,是 JavaScript 中最嚴謹的邏輯。通過捶打磨練,成就了本書的中文版。本書包含了函數式編程之精髓,但願能夠幫助你們在學習函數式編程的道路上走的更順暢。比心。javascript
譯者團隊(排名不分前後):阿希、blueken、brucecham、cfanlife、dail、kyoko-df、l3ve、lilins、LittlePineapple、MatildaJin、冬青、pobusama、Cherry、蘿蔔、vavd317、vivaxy、萌萌、zhouyaohtml
函數式編程人員: 沒有任何一個函數式編程者會把變量命名爲 x,函數命名爲 f,模塊代碼命名爲「zygohistomorphic prepromorphism」。前端
James Iry @jamesiry 5/13/15java
https://twitter.com/jamesiry/status/598547781515485184git
函數式編程(FP),不是一個新的概念,它幾乎貫穿了整個編程史。我不肯定這麼說是否合理,可是很肯定的一點是:直到最近幾年,函數式編程才成爲整個開發界的主流觀念。因此我以爲函數式編程領域更像學者的領域。程序員
然而一切都在變。不僅是從編程語言的角度,一些庫和框架都對函數式編程的興趣空前高漲。你極可能也在讀相關內容,由於你終於意識到函數式編程是不容忽視的東西。或者你跟我同樣,已經嘗試不少次去學函數式編程,但卻很難理解全部的術語或數學符號。github
不管你出於何目的翻閱本書,歡迎加入咱們!編程
我有一個很是簡單的前提,這是我做爲軟件開發老師(JavaScript)所作的一切基礎:你不能信任的代碼是你不明白的代碼。此外,對你不信任或不明白的代碼,你將不能肯定這些代碼是否符合你的業務場景。代碼運行時也只能祈求好運。segmentfault
信任是什麼意思?信任是指你經過讀代碼,不只是跑代碼,就能理解這段代碼能幹什麼事,而不僅是停留在它多是幹什麼的層面。也許咱們不該該總傾向於經過運行測試程序,來驗證程序的正確性。我並非說測試很差,而是說咱們應該對代碼瞭如指掌,這樣咱們在運行測試代碼以前就會知道它確定能跑通。架構
經過讀代碼就能對咱們的程序更有信心,我相信函數式編程技術的基礎構成,是本着這種心態設計的。理解函數式編程並在程序中用心實踐的人,得益於函數式編程已經被證明的原則,可以寫出可讀性高和可驗證的代碼,來達到他們想要的目的。
我但願你能經過理解輕量級函數式編程的原則,對你編寫的代碼更有信心,而且能在以後的路上越走越好。
函數式編程爲什麼如此重要?爲了回答這個問題,咱們退一萬步先來討論一下編程自己的重要性。
我認爲代碼不是電腦中的一堆指令,這麼說你可能感到很奇怪。事實上,代碼能指示電腦運行就是一個意外的驚喜。
我深信代碼的主要做用是方便人與人交流。
根據以往經驗你可能知道,有時候花不少時間「編程」其實只是讀現有的代碼。咱們的大部分時間其實都是在維護別人的代碼(或本身的老代碼),只有少部分時間是在敲新代碼。
你知道研究過這個話題的專家給出了怎樣的數據嗎?咱們在維護代碼過程當中 70% 的時間花在了閱讀和理解代碼上。 也難怪全球程序員天天的平均代碼行數是 5 行。咱們一天花七個半小時用來讀代碼,而後找出這 5 行代碼應該寫在哪裏。
我想咱們應該更多的關注一下代碼的可讀性。可能的話,不妨多花點時間在可讀性上。順便提一句,可讀性並不意味着最少的代碼量,對代碼的熟悉程度也會影響代碼的可讀性(這一點也是被證明過的)。
所以,若是咱們要花費更多的時間來關注代碼的可讀性和可理解性,那麼函數式編程爲咱們提供了一種很是方便的模式。函數式編程的原則是完善的,通過了深刻的研究和審查,而且能夠被驗證。
若是咱們使用函數式編程原則,我相信咱們將寫出更容易理解的代碼。一旦咱們知道這些原則,它們將在代碼中被識別和熟悉,這意味着當咱們讀取一段代碼時,咱們將花費更少的時間來進行定位。咱們的重點將在於如何組建全部已知的「樂高片斷」,而不是這些「樂高片斷」是什麼意思。
函數式編程是編寫可讀代碼的最有效工具之一(可能還有其餘)。這就是爲何函數式編程如此重要。
很重要的是,我先花點時間來說述一種多年來讓我感到困惑和沮喪的現象,在寫本書時該問題尤其尖銳。
這也多是許多開發人員會遇到的問題。親愛的讀者,當你讀這篇文章的時候,你可能會發現本身也會遇到一樣的情況。可是要振做起來,堅持下去,陡峭的學習曲線總會過去。
咱們將在下一章更深刻的討論這個問題。可是你可能寫過一些命令式的代碼,像 if
語句和 for
循環這樣的語句。這些語句旨在精確地指導計算機如何完成一件事情。聲明式代碼,以及咱們努力遵循函數式編程原則所寫出的代碼,更專一於描述最終的結果。
還有個殘酷的問題擺在眼前,我在寫本書時花費了不少時間在此問題上:我須要花費更多的精力和編寫更多的代碼來提升代碼的可讀性,儘可能減小乃至消除可能會引入程序錯誤的代碼部分。
若是你指望用函數式編程重構過的代碼可以馬上變得更美觀、優雅、智能和簡潔的話,這個有點不太現實,這個變化是須要一個過程的。
函數式編程以另外一種方式來思考代碼應該如何組織才能使數據流更加明顯,並能讓讀者很快理解你的思想。這種努力是很是值得的,然而過程很艱辛,你可能須要花不少時間基於函數式編程來調整代碼直到代碼可讀性變得好一些。
另外,個人經驗是,轉換爲聲明式的代碼以前,大約須要作六次嘗試。對我來講,編寫符合函數式編程的代碼更像是一個過程,而不是從一個範例到另外一個範例的二進制轉換。
我也會常常對寫過的代碼進行重構。就是說,寫完一段代碼,過幾個小時或一天再看會有不同的感受。一般,重構以前的代碼是比較混亂不堪,因此須要反覆調整。
函數式編程的過程並無讓我在藝術的畫布上筆下生輝,讓觀衆拍案叫好。相反,編程的過程很艱辛且歷歷在目,感受像坐在一輛不靠譜的馬車穿過一片雜草叢生的灌木樹林。
我並非試圖打消你的激情,而是真切但願你也可以在編程的道路上披荊斬棘。事後我終於看到可讀性曲線向上延伸,全部付出都是值得的,我相信你也會有一樣的感覺。
咱們要系統的學習函數式編程,探索發現最基本的原則,我相信規範的函數式編程編程者會遵循這些原則並把它們做爲開發的框架。但在大多數狀況下,咱們大都選擇避開晦澀的術語或數學符號,不然很容易使學習者受挫。
我以爲一項技術你怎麼稱呼它不重要,重要的是理解它是什麼而且它是怎麼工做的。這並非說共享術語不重要,它無疑能夠簡化經驗豐富的專業人士之間的交流。但對學習者來講,它有點分散人的注意力。
因此我但願這本書能更多地關注基本概念而不是花哨的術語。這並非說沒有術語,確定會有。但不要太沉迷於華麗的詞藻,追尋其背後的含義,這正是本書的目的。
我把這種欠缺正式實踐的編程思想稱爲「輕量級函數式編程」,由於我認爲真正的函數式編程的形式主義在於, 由於我認爲若是你還不習慣函數式編程主張的思想,你可能很難用它。這不只僅只是猜想,而是個人親身經歷。即便在傳教函數式編程過程和完成這本書以後,我仍然能夠說,函數式編程中術語和符號的形式化對於我來講是很是很是困難的。我已經再三嘗試,發現大部分都是很難掌握的。
我知道不少函數式編程編程者會認爲形式主義自己有助於學習。但我認爲這是一個坑,當你試圖用形式主義得到某種安慰時,你就會踩坑。但若是碰巧你有數學背景,甚至還有一些 CS 經驗,這些問題對你來講就可能得心應手。可是咱們中的一些人不具有這些條件,無論咱們怎麼努力,形式主義老是阻礙咱們前進。
所以,這本書介紹了一些我認爲函數式編程會涉及到的概念,雖然不能直接讓你受益但能夠幫你逐步理解函數式編程整個過程。
若是你規劃一個項目花了很長時間,那麼別人必定會告訴你「YAGNI」 —— 「你不須要它」。這個原則主要來自極限編程,強調構建特性的高風險和成本,這個風險和成本源自於項目自己是否須要。
有時咱們考慮到未來可能會用到一個功能,而且認爲如今構建它可以使得構建其餘應用時更容易,後來意識到咱們猜錯了,原來這個功能並不須要,或者須要的徹底是另一套。另一種情形是咱們預估的功能是正確的,但構建得太早的話,至關於佔用了開發現有功能的時間。有點像賠了夫人又折兵。
YAGNI 挑戰,告訴咱們:即便有的功能在某種狀況下是反直覺的,咱們也經常應該推遲構建,直到當前須要這個功能。咱們傾向於誇大一個功能將來重構成本的心理估計,但每每這個重構是在未來須要時纔會作。
上述狀況對函數式編程也一樣適用,不過我仍是要先敲個警鐘: 本書包含了大量你想去嘗試的有趣的開發模式,但這不意味着你的代碼必定要使用這些模式。
我與不少函數式編程開發人員的不一樣之處在於:你掌握了函數式編程並不意味着你必定得用它。此外,解決問題的方法不少,即便你掌握了更精煉的方法,能對維護和可擴展性更"經得起將來的考驗",但更輕量的函數式編程模式可能更適合該場景。
通常來講,我建議你在代碼中尋求平衡,而且當你掌握函數式編程的訣竅時,在應用的過程當中也應保持謹慎。在決定某個模式或抽象概念是否能使得部分代碼可讀性提升,或是否只是引入更智能的庫時,YAGNI 的原則一樣適用。
提醒一句,一些不曾用過的擴展點不只浪費精力,並且可能妨礙你的工做。
Jeremy D. Miller @jeremydmiller 2/20/15
https://twitter.com/jeremydmiller/status/568797862441586688
記住,你編寫的每一行代碼以後都要有人來維護,這我的多是你的團隊成員,也多是將來的你。若是代碼寫的太過複雜,那麼不管誰來維護都會對你炫技式的故做聰明的作法倍感壓力。
最好的代碼是可讀性高的代碼,由於它在正確的(理想主義)和必然的(正確的)之間尋求到了恰到好處的平衡。
我撰寫這篇文章的過程參考了許多不一樣的資源。我相信你也會從中受益,因此我想花點時間把它們列出來。
一些你務必要閱讀的函數式編程 / JavaScript 書籍:
一些其餘做者和相關內容供查閱:
本書中的代碼段不使用庫。咱們發現的每個操做,將派生出如何在獨立的、普通的 JavaScript 中實現它。然而,當你開始使用函數式編程構建更多的真正代碼時,你很快就會使用現有庫中所提供的更可靠高效的通用功能。
順便說一下,你要確保檢查你所使用的庫函數的文檔,以確保你知道它們是如何工做的。它與本文中構建的代碼有許多類似之處,但毫無疑問即使跟最流行的庫相比仍是會存在一些差別。
下面是一些流行的 JavaScript 版本的函數式編程庫,能夠開啓你的探索之路:
附錄 C 展現了用到了本書中一些示例的庫。
這就是 JavaScript 輕量級函數式編程。咱們的目標是學會與代碼交流,而不是在符號或術語的大山下被壓的喘不過氣。但願這本書能開啓你的旅程!
【上一章】翻譯連載 |《JavaScript 輕量級函數式編程》- 引言&前言
【下一章】翻譯連載 |《JavaScript 輕量級函數式編程》- 第 2 章:函數基礎
iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、噹噹開售。