標籤:php b16 const 範圍 代碼風格 匯入 實用 這就是我 現在
前言
看到英文技術文檔、快哭了。含著淚也要把他讀完。
原文How I Structure My JavaScript File
內容
很多人都在問我怎麼寫我的JavaScript——好吧,這是一個謊言,沒人問我,但是如果他們這麼做了,我想指出這篇文章。在使用了多年的PHP之後,在閱讀了乾淨代碼(和其他書籍)之後,我在多年中採用了My Code風格。是的,PHP,不要敲它,它有一個偉大的社區和偉大的編碼通訊協定。當然,多年來和別人一起寫作,跟隨不同公司的風格。
結構並不依賴於JS模組,但我現在傾向於只編寫JS模組,所以我將使用這些模組。
結構,總結如下:
入口
在檔案的頂部是匯入。這是有道理的,他們比其他任何東西都要高。進口的順序無關緊要,除非你使用一些掛鈎(比如babel hook),所以我傾向於選擇:
本地模組-節點本地的東西。
庫模組- lodash, knex,等等。
本地庫——比如../db。
本地檔案- like ./helper或類似的。
讓我的模組保持有序,讓我更容易看到我在匯入什麼,以及我實際上在使用什麼。當我開始編寫代碼時,我也傾向於以這種方式編寫依賴關係。
我傾向於不關心字母排序(除了破壞匯入之外),我也沒有看到它的一個點。
本地模組
我傾向於將本地模組放在最上面,並以這樣的主題保持一個清晰的組織:
如果我在瀏覽器中,顯然跳過這一步。
庫模組
我儘可能只從庫中匯入我需要的東西,但是,我又一次將它們分組到某個主題中。
我還注意到,如果我正在執行一個預設的匯入(例如。我傾向於把它放在我的庫模組的頂部,並將被破壞的匯入降低。沒有必要,但我喜歡它的視覺效果。
Local/Internal libraries
在本地庫中,我指的是本地共用的模組,比如db。設定與書架串連的js檔案。或者,在我的工作中,我們有幾個庫處理我們產品中使用的數字和計算。
Local files
最後,我匯入本地檔案,這些檔案通常與我正在處理的檔案或一個目錄(最多)在同一個檔案夾中。例如,我為Redux寫了一個減速器,並把它放在一個單獨的檔案夾中。在該檔案夾中,我還保留了一個助手檔案,通常命名為[reducer name]Helpers.js:
Constants
在匯入所有依賴項之後,我通常會做一些前期工作,這些工作將在模組的其餘部分中使用。例如,我從書架執行個體中提取了knex。或者我可以設定值常數。
使用非常量通常表示我依賴於某種類型的單例。我盡量避免使用它們,但有時它是必要的,因為沒有簡單的其他方法來完成它,或者它不重要(比如一次性命令列指令碼)。
Exports
在我基本設定了所有模組層級別的依賴項之後:無論它們是常量值還是匯入庫,我都試著將我的匯出分組到檔案的頂部。基本上,這就是我把功能作為模組的粘合劑,實現模組的最終目的。
在Redux的情況下,我可能匯出一個單一的減速器,然後將工作分解並調用相關的邏輯。在ExpressJS的情況下,我可能在這裡匯出所有的路由,而實際的路由邏輯在下面。
我想說的是,這並不是我出口功能的唯一部分。
我感覺模組系統的工作方式使得在暴露最窄的API和匯出函數在測試中使用它們之間的界限變得有點困難。
例如,在上面的例子中,我從來不想在模組之外使用calculateSomething。我不完全確定OOP語言是如何處理測試私人函數的,但這是一個類似的問題。
Core Logic
這看起來很奇怪,但核心邏輯對我來說是最重要的。我完全理解當人們翻轉匯出和核心邏輯時,但這對我來說很有效,原因有很多。
當我開啟一個檔案時,頂層函數會告訴我抽象步驟中將會發生什麼。我很喜歡這樣。我一眼就能看出檔案的作用。我做了大量的CSV操作,並將其插入到DB中,而頂級函數始終是一個容易理解的流程,它有一個類似的流程:fetchCSV aggregateData insertData terminate script。
核心邏輯總是包括從上到下的出口。在內聯的例子中,我們有這樣的東西:
注意,readCSV沒有。這聽起來很普通,我應該把它放到一個helper檔案中,然後將它匯入上面。除此之外,你可以看到我的出口,而不是進退兩難。我不希望在模組外部提供彙總資料,但我仍然希望測試它。
在此之外,我傾向於把“meatier”函數放在上面,下面的函數更小。如果我有一個特定於模組的實用函數,一個我在多個地方使用的函數,但只在模組中使用,我將把它們放在底部。基本上,我的命令是:複雜性+使用。
所以順序是:
核心邏輯函數——由頂級匯出使用的函數。
更簡單/更小的函數——核心邏輯函數使用的函數。
實用函數——模組周圍多個地方使用的小函數(但不匯出)
Core-logic functions
核心邏輯函數就像我匯出的函數的“sub-glue”。根據模組的複雜性,這些可能存在,也可能不存在。功能的分解不是必需的,但是如果一個模組足夠大,核心邏輯函數就像主函數中的步驟。
如果你寫的是反應或角度,這些你的組件將是我上面提到的出口函數。但是,核心邏輯函數將是各種接聽程式或資料處理器的實現。用Express,這些將是您的特定路線。在一個Redux減速器中,這些將是在鏈條上足夠遠的單獨的減速器,沒有一個開關/case語句。
如果您處於角度,那麼在類中組織這些函數而不是在整個檔案的範圍內是完全公平的。
Simpler/Smaller functions
這些函數通常是核心邏輯和純公用程式之間的中間步驟。你可能會用到它們,或者它們可能只是一個比效用函數更複雜的tad。我可能會刪除這個類別,並說“寫你的功能,以減少複雜性或工作量”。
這裡沒有提及。也許onHandleInput事件監聽器需要一些邏輯來處理$event資料,所以如果它是純的,您可以將它從類中刪除,如果不是,您可以在類中保留它:
Utility functions
最後,效用函數。我傾向於組織最接近我使用它們的工具。在相同的檔案中,或者相同的檔案夾(必要時),相同的模組,等等。每次使用從檔案中擴充到項目的根或它自己的NPM模組時,我都將函數移出一個層級。
在我看來,效用函數應該始終是一種純方法,這意味著它不應該在它的範圍之外訪問變數,而且應該只依賴傳遞到它的資料,而且不需要任何形式的副作用。除非使用公用程式函數來訪問API或訪問資料庫。因為這些被認為是副作用,所以我認為它們是唯一的例外。
Anything else?
當然!我認為每個人都有自己獨特的書寫方式。上面所描述的結構在我多年來每天編寫大量代碼的過程中非常有效。最終,許多細微的差別開始出現,我發現自己編寫代碼更快,更喜歡它,並且更容易調試和測試。
在我完成這篇文章之前,我想和大家分享一些我已經習慣了的編碼,它們與文檔結構的關係更少,更多的是在編寫實際代碼時更傾向於使用小的偏好。
早期的回報
當我發現早期的回報時,那是一瞬間。當您可以提前返回時,為什麼要在else語句中封裝大量代碼?
我的經驗法則是,如果早期的返回條件小於其餘的代碼,那麼我將寫早期的返回,但是如果不是,我將顛倒代碼,這樣較小的代碼塊總是提前返回。
早期的回報在交換器上也很出色,我是Redux的超級粉絲。
分號塊
雖然我不再使用它(沒有更漂亮的支援),但我總是用分號來終止函數連結,在一個單獨的行上,一個縮排到鏈的縮排的左邊。這就建立了一個整潔的代碼塊,代碼不只是掛在那裡。
當然,這意味著我也喜歡用分號來代替。
Or better written, it might look like this:
總結
使用的是有道線上翻譯,如有不正確之處還望大佬指出。
譯:如何構造我的JavaScript檔案?