原文地址:Clean up your code by applying these 7 rules ⚡️javascript
原文做者:Joachim Zeelmaekershtml
譯者 & 校訂:HelloGitHub-小魚乾 & HelloGitHub-鴨鴨java
在這篇短文中,我將介紹一些你能夠用來改進你的代碼的方法。本文代碼示例均使用 JavaScript。ios
我發現但凡是可讀的代碼一定是可維護的。git
做爲一名開發人員,個人目標是編寫高質量的代碼。團隊中的每一個開發人員,無論他/她的技術水平如何,都必須可以經過閱讀理解我所寫的代碼。代碼的可讀性有助於年輕的開發人員編寫代碼時更加自信。程序員
固然,有些代碼能夠很是複雜。我深知這一點且見過不少次。在複雜的代碼中,我會寫些適當的文檔和代碼註釋。github
別誤會。我不是代碼註釋或 JavaScript JSdoc 的愛好者,並且基本上我能不用它們便不用。編程
我不須要任何註釋來解釋這個接收 X 個數組並將它們合併到一個新的數組中的函數。axios
function mergeArrays(...arrays) { let mergedArray = [] arrays.forEach(array => { mergedArray = [...mergedArray, ...array] }) return mergedArray }
像示例代碼,若是增添文檔並不能提升可讀性。我但願團隊成員知道展開操做符是什麼。若是他們不清楚,他們應該在代碼審查 code review 時來問我。api
固然,咱們不要忘記註釋的代碼塊。若是咱們忘記了,這裏只有一個解決方案:刪除代碼。既然了不得的 git 能夠檢出舊代碼,那麼爲何還要把它留在註釋中呢?
請中止把你的代碼庫變成垃圾場。
若是你看到函數名 mergeArrays,就應該很清楚地知道這是一個將 X 個數組組合成一個新的數組的函數。
我知道命名是件難事。函數越複雜,命名就越難… 我有個法子讓命名更容易,舉個例子:有一個函數,它會合並兩個數組並生成一個新的惟一的數字列表。你會怎麼命名?是下面這樣嗎?
function mergeNumberListIntoUniqueList(listOne, listTwo) { return [...new Set([...listOne, ...listTwo])] }
mergeNumberListIntoUniqueList
這個名字並無那麼糟糕,至少功能如其名。命名的難點在於這個函數要作兩件事:一個函數作的事情越多,命名它就越困難。將這個函數拆分爲兩個單獨的函數,命名會更容易且函數複用更容易。
function mergeLists(listOne, listTwo) { return [...listOne, ...listTwo] } function createUniqueList(list) { return [...new Set(list)] }
固然,不須要調用新函數就能夠很容易地建立美觀的一行代碼。但有時,一行代碼的可讀性並不高。
我對這個問題的命名無力… 看!命名不易…
但我常常看到這種狀況。
問題
if(value === 'duck' || value === 'dog' || value === 'cat') { // ... }
解決方法
const options = ['duck', 'dog', 'cat']; if (options.includes(value)) { // ... }
這樣作,你建立了一段像是英語句子般的可讀代碼。
若是選項包含值,那麼 ...
這個準則有不少種命名方式,但我選擇了 「提早退出 Early exit」 這個名字。
讓我給大家看一段代碼。我相信大家之前見過這樣的東西。
function handleEvent(event) { if (event) { const target = event.target; if (target) { // Your awesome piece of code that uses target } } }
來咱們檢查下對象 event
是否爲真,以及屬性 target
是否可用。問題是上面代碼咱們已經用了兩個 if
語句。
讓咱們看看如何在這裏實現 「提早退出」。
function handleEvent(event) { if (!event || !event.target) { return; } // Your awesome piece of code that uses target }
在這裏用 「提早退出」,你能夠檢查是否 event
和 event.target
同時非假 。很明顯,咱們確信這一事件 event.target
非假。由於若是這個語句爲假,程序就不會執行其餘代碼。
在 JavaScript 中,咱們能夠解構數據和對象。
根據 developer.mozilla.org 上的文檔,解構賦值語法是一種 JavaScript 表達式。經過解構賦值,能夠將值從數組、屬性從對象中取出,賦值給其餘變量
。
一些代碼示例
// Destructuring an object const numbers = {one: 1, two: 2}; const {one, two} = numbers; console.log(one); // 1 console.log(two); // 2 // Destructuring an array const numbers = [1, 2, 3, 4, 5]; const [one, two] = numbers; console.log(one); // 1 console.log(two); // 2
解構的問題在於,它有時會爲屬性建立一個很差的命名。最好的例子是從 API 獲取數據並接收具備 data 屬性的響應對象。
const url = "http://localhost:8080/api/v1/organizers/1" const response = await axios.get(url) const {name} = response.data
這個代碼示例說明你正在獲取 id 爲 1 的 organizer。organizer 對象有一個名字,你能夠解構它。這樣作沒什麼問題。
這段代碼能夠正常運行。可是爲何屬性名仍是 name
? 那將是整個範圍中惟一的 name
屬性嗎?屬性名又來自哪一個對象?
經過重命名屬性可避免這些問題。
const url = "http://localhost:8080/api/v1/organizers/1" const response = await axios.get(url) const {name: organizerName} = response.data
這段代碼變得更具可讀性。每一個人都知道變量是 organizer 的名字。
聽過這樣一句話嗎:「永遠保持離開時的露營地比你發現它時更整潔」?
這就是童子軍的規則。讓代碼比發現時更好。你發現代碼異味 code smell?重構它!你發現一個未使用的變量?刪除它!
我喜歡把童子軍規則和打掃房間的狀況進行類比。想象一下,你家裏的每一個人都把盤子放在水槽上,把全部垃圾都放在走廊上,把全部要洗的衣服都放在浴室裏。可是每一個星期天,你必須花費 4 個多小時清理整個房子。你會鐘意嗎?
我確定答案是 NO。因此若是每一個人都當即清理房間的小部分,星期天的工做量會小一些。
代碼庫同理。若是每一個小的代碼異味 code smell 都留在代碼庫中,沒有人刪除未使用的變量,linter 就會抓狂且有大約 77 個 warning。並且代碼庫將會有不少清潔工做要作,可是若是每一個人都承擔起本身的責任並遵照童子軍法則,不少問題將會獲得解決。
一樣重要的還有肯定團隊中的代碼風格。
我不 care 你是喜歡單引號仍是雙引號,空格仍是 tab,結尾逗號仍是不用。選擇一種風格並堅持下去。你能夠用 Linter 或者 Prettier 來作這件事。
有不少工具能夠用來解決代碼風格問題。我最鐘意的是使用 Husky 預提交鉤子。Prettier 的文檔中也有一個關於預提交鉤子的頁面。
這個預提交鉤子老是在每次提交以前運行配置好的命令。若是你正確地配置它,它會運行得更漂亮,並對全部文件應用全部規則。這確保了團隊老是擁有統一的代碼風格,而沒有任何糟糕的代碼。
我知道有些方法顯而易見,有些則不是。但做爲一名全職開發人員,我在不一樣的代碼庫上工做。這些規則的重要性只有在較大的代碼庫中才會突顯。但這並不意味着你不該該將這些方法用在小項目中,提升你的代碼質量讓小項目更高效。它讓團隊成員方便地閱讀你的代碼併合並你的 pull 請求。正如我所說的,可讀的代碼更容易維護,固然可讀的代碼還有其餘更多的好處。
若是你想了解更多關於代碼整潔之道的知識,能夠嘗試閱讀羅伯特・馬丁的《代碼整潔之道》。
最後,歡迎優秀的你加入 HelloGitHub 的「譯文亦舞」系列,讓你的才華舞動起來!把優秀的文章分享給更多的人。要求:
封面圖來自 Unsplash 由 Kevin Ku 拍攝