天天看點

[譯] JavaScript 的函數式程式設計是一種反模式

<b>本文講的是[譯] JavaScript 的函數式程式設計是一種反模式,</b>

<b></b>

[譯] JavaScript 的函數式程式設計是一種反模式

寫了幾個月 Clojure 之後我再次開始寫 JavaScript。就在我試着寫一些很普通的東西的時候,我總會想下面這些問題:

“這是 ImmutableJS 變量還是 JavaScript 變量?” “我如何 map 一個對象并且傳回一個對象?” “如果它是不可變的,要麼使用 &lt;這種文法&gt; 的 &lt;這個函數&gt;,否則使用 &lt;不同的文法和完全不同行為&gt; 的 &lt;同一個函數的另一個版本&gt;” “一個 React 元件的 state 可以是一個不可變的 Map 嗎?” “引入 lodash 了嗎?” “<code>fromJS</code> 然後 &lt;寫代碼&gt; 然後 <code>.toJS()</code>?”

這些問題似乎沒什麼必要。但我猜想我已經思考這些問題上百萬次了隻是沒有注意到,因為這些都是我知道的。

當使用 React、Redux、ImmutableJS、lodash、和像 lodash/fp、ramda 這樣的函數式程式設計庫的任意組合寫 JavaScript 的時候,我覺得沒什麼方法能避免這種思考。

我需要一直把下面這些事記在腦海裡:

lodash 的 API、Immutable 的 API、lodash/fp 的 API、ramda 的 API、還有原生 JS 的 API 或一些組合的 API

處理 JavaScript 資料結構的可變程式設計技術

處理 Immutable 資料結構的不可變程式設計技術

使用 Redux 或 React 時,可變的 JavaScript 資料結構的不可變程式設計

就算我能夠記住這些東西,我依然會遇到上面那一堆問題。不可變資料、可變資料和某些情況下不能改變的可變資料。一些常用函數的簽名和傳回值也是這樣,幾乎每一行代碼都有不同的情況要考慮。我覺得在 JavaScript 中使用函數式程式設計技術很棘手。

如果我使用 ramda 或者 lodash/fp 會好一些,可以很容易地組合函數并且寫出清晰整潔的代碼。但是它不能和 Immutable 資料結構一起使用。我可能還是要寫一些參數集合在後而其他時候在前的代碼。我必須知道更多的函數名、簽名、傳回值,并引入更多的基本函數。

當我單獨使用 ImmutableJS,一些事變得容易些了。Map.set 傳回全新的值。一切都傳回全新的值!這就是我想要的。不幸的是,ImmutableJS 也有一些糾結的事情。我不可避免地要處理兩套不同的資料結構。是以我不得不清楚 <code>x</code> 是 Immutable 的還是 JavaScript 的。通過學習其 API 和整體思維方式,我可以使用 Immutable 在 2 秒内知道如何解決問題。當我使用原生 JS 時,我必須跳過該解決方案,用另一種方式來解決問題。就像 ramda 和 lodash 一樣,有大量的函數需要我了解 —— 它們傳回什麼、它們的簽名、它們的名稱。我也需要把我所知的所有函數分成兩類:一類用于 Immutable 的,另一類用于其它。這往往也會影響我解決問題的方式。我有時會不自主地想到柯裡化群組合函數的解決方案。但不能和 ImmutableJS 一起使用。是以我跳過這個解決方案,想想其他的。

當我全部想清楚以後,我才能嘗試寫一些代碼。然後我轉移到另一個檔案,做一遍同樣的事情。

[譯] JavaScript 的函數式程式設計是一種反模式

JavaScript 中的函數式程式設計。

[譯] JavaScript 的函數式程式設計是一種反模式

反模式的可視化。

我已孤立無援,并且把 JavaScript 的函數式程式設計稱為一種反模式。這是一條迷人之路卻将我引入迷宮。它似乎解決了一些問題,最終卻創造了更多的問題。重點是這些問題似乎沒有更高層次的解決方案能避免我一次有又一次地處理問題。

我沒有确切的數字,但我敢說如果不必去想“在這裡我可以用什麼函數?”和“我可否改變這個變量”這樣的問題,我可以更高效地開發。這些問題對我想要解決的問題或者我想要增加的功能沒有任何意義。它們是語言本身造成的。我能想到避免這個問題的唯一辦法就是在路的起點就不要走下去 —— 不要使用 ImmutableJS 、ImmutableJS 資料結構、Redux/React 概念中的不可變資料,以及 ramda 表達式和 lodash。總之就是寫 JavaScript 不要使用函數式程式設計技術,它看似不是什麼好的解決方案。

如果你确定并同意我所說的(如果不同意,也很好),那麼我認為值得花 5 分鐘或一天甚至一周時間來考慮:保持在 JavaScript 路子上相比用一個不同的東西取代,耗費的長期成本是什麼?

這個所謂不同的東西對于我來說就是 Clojurescript。它是一門像 ES6 一樣的 “compile-to-JS” 語言。大體上說,它是一種使用不同文法的 JavaScript。它的底層是被設計成用于函數式程式設計的語言,操作不可變的資料結構。對我來說,它比 JavaScript 更容易,更有前途。

[譯] JavaScript 的函數式程式設計是一種反模式

Clojurescript 類似 Clojure,除了它的宿主語言是 JavaScript 而不是 Java。它們的文法完全相同:如果你學 Clojurescript,其實你就在學 Clojure。這意味着如果你了解了 Clojurescript,你就可以寫 JavaScript 和 Java。“30 億的裝置上運作着 Java”;我非常确定其他裝置上運作着 JavaScript。

和 JavaScript 一樣,Clojure 和 Clojurescript 也是動态類型的。你可以 100% 地使用 Clojurescript 語言用 Node 寫服務端的全棧應用。與單獨編譯成 JavaScript 的語言不同,你也可以選擇寫一個基于 Java 的 servrer 來支援多線程。

作為一個普通的 JavaScript/Node 開發者,學習這門語言及其生态系統對我來說并不困難。

[譯] JavaScript 的函數式程式設計是一種反模式

在編輯器中執行任意你想要執行的代碼。

你可以在編輯器中一鍵執行任何代碼。 的确如此,你可以在編輯器中輸入任何你想寫的代碼,選中它(或者把光标放在上面)然後運作并檢視結果。你可以定義函數,然後用你想用的參數調用它。你可以在應用運作的時候做這些事。是以,如果你不知道一些東西如何運作,你可以在你的編輯器的 REPL 裡求值,看看會發生什麼。

函數可以作用于數組和對象。 Map、reduce、filter 等對數組和對象的作用都相同。設計就是如此。我們毋須再糾結于 <code>map</code> 對數組和對象作用的不同之處。

不可變的資料結構。 所有 Clojurescript 資料結構都是不可變的。是以你再也不必糾結一些東西是否可變了。你也不需要切換程式設計範式,從可變到不可變。你完全在不可變資料結構的領地上。

它很簡潔。 相對于其他任何程式設計語言,它隻需要短短幾行的代碼就能表達你的想法。(通常少得多)

函數式程式設計。 Clojurescript 是一門徹底的函數式程式設計語言 —— 支援隐式傳回聲明、函數是一等公民、lambda 表達式等等。

使用 JavaScript 中所需的任何内容。 你可以使用 JavaScript 的一切以及它的生态系統,從 <code>console.log</code> 到 npm 庫都可以。

性能。 Clojurescript 使用 Google Closure 編譯器來優化輸出的 JavaScript。Bundle 體積小到極緻。用于生産的打包過程不需要從設定優化到 <code>:advanced</code> 的複雜配置。

可讀的庫代碼。 有時候了解“這個庫的功能是幹嘛的?”很有用。當我使用 JavaScript 中的“跳轉到定義處”,我通常都會看到被壓縮或錯位的源代碼。Clojure 和 Clojurescript 的庫都直接被顯示成寫出來的樣子,是以不需離開你的編輯器去看一些東西如何工作就很簡單,因為你可以直接閱讀源碼。

是一種 LISP 方言。 很難列舉出這方面的好處,因為太多了。我喜歡的一點是它的公式化,(有這麼一種模式可以依靠)代碼是用語言的資料結構來表達的。(這使得元程式設計很容易)。Clojure 不同于 LISP 因為它并不是 100% 的 <code>()</code>。它的代碼和資料結構中可以使用 <code>[]</code> 和 <code>{}</code>,就像大多數程式設計語言那樣。

既然說它這麼棒,可它怎麼不上天呢?有人指出它已經很流行了,它隻是不如 lodash、React、Redux 等等那麼流行而已。但既然它更好,不應該和它們一樣流行嗎?為什麼偏愛函數式程式設計、不可變性和 React 的 JS 開發者還沒有遷移到 Clojurescript?

因為在工作中很難使用? 可能是吧。它是一種新技術,就像 React 和 Redux 曾經那樣,在某些時候也是很難推廣的。即使也沒什麼技術限制 ——  Clojurescript 內建到現有代碼庫和內建 React 的方式是類似的。你可以把 Clojurescript 加入到已經存在的代碼庫中,每次重寫一個檔案的舊代碼,新代碼依然可以和未更改的舊代碼互動。

有數量上的劣勢,我認了。但“人多勢衆”否決了所有其他可能的因素。

假設有一條路通向 100 美元,它很不受歡迎,而另一條路通向 10 美元,它極其受歡迎,我會選擇受歡迎的那條路嗎?

恩,也許會的吧!那裡有成功的先例。它一定比另一條路安全,因為更多的人選擇了它。他們一定不會遇到什麼可怕的事。而另一條路聽起來美好,但我确定那一定是個陷阱。如果它像看起來那麼美好,那麼它就是最受歡迎的那條路了。

<b>原文釋出時間為:2017年7月11日</b>

<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>