忍者程式碼(Ninja Code)

Len Chen
Len Chen
Sep 14 · 8 min read
https://www.flickr.com/photos/dlato/5530553658

過去的程式忍者使用這些技巧來讓程式碼維護者的心思更加敏銳。

程式碼審查大師得在測試任務中尋找它們。

初學的開發者有時候將它們用的比程式忍者更好。

細心閱讀然後找出你的角色是 — 程式忍者、初學者、或者程式碼審查者?

很多人試著跟隨忍者的腳步,但很少有人成功。

要言不煩(Brevity is the soul of wit)

讓程式碼盡可能簡短,以顯示出你多麼聰明。

讓微妙的語言特性指引你。

舉例,看一下這個三元運算子 ?

// 從知名 javascript 函式庫取得的程式碼
i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

酷,對吧?若你也像這樣寫,那些看到這一行程式碼並試圖理解 i 值的開發者們,將會有個美好的時光,接著就會來找你尋求答案。

告訴他們更短總是更好,引領他們進入忍者之路。

單一字母變數

道隱無名。夫唯道,善貸且成。
— 老子(道德經)

另一個寫程式更快的方式是到處使用單一字母的變數名稱,像是 abc

短變數會像個真正的忍者處於森林中一樣,消失於程式碼之中,沒有人能夠使用編輯器的 “搜尋” 找到它們。即使有人辦得到,他們也無法 “破譯” ab 名稱的意義。

…但有個例外,一個真正的忍者永遠不會在 for 迴圈內使用 i 作為計數器。任何地方都行,就是這裡不可以。觀察四周看看,還有其他像是 xy 這種異樣的字母呢。

若迴圈本體有 1–2 頁這麼長(若可以就讓它盡量長),那麼以異樣的變數作為迴圈計數器會是特別的酷。然後若有人深入迴圈內部,他們將無法快速知道以 x 為名的變數就是迴圈計數器。

使用縮寫

若團隊規則禁止使用單一字母或模糊的名稱 — 盡量縮短它們,使用縮寫吧。

像這樣:

  • list -> lst
  • userAgent -> ua
  • browser -> brsr
  • …等等

只有真正擁有良好直覺的人才有辦法理解這些名稱。盡量縮短一切事物,只有天選之人才夠格接手你的程式開發。

突破天際的抽象化

大方無隅,
大器晚成,
大音希聲,
大象無形。
— 老子(道德經)

在選擇一個名稱時,試著使用最為抽象的詞,像是 objdatavalueitemelem 等等。

  • 變數的理想名稱是 data在任何能用地方都用,每個變數都確實都有 data 不是嗎?

…但如果 `data` 已經被用過了怎麼辦?試著使用 value,它也很普遍,畢竟一個變數最終總會得到一個 value

  • 使用變數類型命名:strnum

嘗試看看,新手可能會懷疑 — 這種名稱真的對成為忍者有用嗎?是的,就是會!

確實,該變數名稱依然含有意義。它說明了變數內部有些什麼:一串字串、一個數值或其它東西。但當外部使用者試著理解程式碼時,他們會驚訝地發現事實上根本不具有任何資訊!且最終將無法改變你精思熟慮過的程式碼。

值的類型很容易就可以經由除錯得知,但此變數的意義呢?它儲存著哪種 字串/數值?

不經過良好的冥想是無法理解的!

…但如果這種名稱不夠用怎麼辦?加個數字就好了:data1, item2, elem5

注意力測試

只有真正細心的程式設計師才夠格理解你的程式碼,要如何確認?

其中一個方法 — 使用相似的名稱,像是:datedata

盡可能的混合在一起。

快速閱讀這種程式碼是不可能的,而且當還有錯字時… 嗯… 我們卡在這很久了,來喝個茶吧。

聰明的同義詞

最困難的事是在黑暗的房間內尋找一隻黑貓,尤其當那裡根本沒有貓時。
— 孔子(譯者註:這則引用應是個烏龍,孔子沒有說過這句話,可上網查詢相關來源)

同件 事情使用 相似 的名稱使得生活更為有趣,並向大眾顯示出你的創意。

例如,函式前置。若某個函式在螢幕上顯示一段訊息 — 使用 display... 開頭,像是 displayMessage。然後若另一個函式在螢幕上顯示別的東西,像是使用者名稱,就用 show... 開頭(像是 showName)。

暗示這些函式之間有些微妙的不同,而其實並沒有。

與團隊中的忍者夥伴達成一個協議:若 John 在程式碼中用 display... 作為 “顯示” 函式的起始,那 Peter 可以用 render..,而 Ann 就用 paint...,注意看看程式碼會變得多麼有趣且多樣化啊。

…接著是帽子戲法!

對於兩個有著重要差異的函式 — 使用同樣的前置!

舉個例,函式 printPage(page) 將會用到印表機,而函式 printText(text) 將會把文字放到螢幕上。讓某個不熟悉的讀者思考一下這個相似的函式名稱 printMessage:”它會把訊息丟到哪去?印表機還是螢幕上?” 為了讓它更為耀眼,printMessage(message) 應該要輸出訊息到新的視窗中!

重複使用名稱

始制有名,
名亦既有,
夫亦將知止。
知止所以不殆。
— 老子(道德經)

只在絕對需要時才加入新的變數。

否則,重複使用已存在的名稱。就只要對它們寫入新的值。

在函式中試著只使用作為參數傳遞的變數。

這樣做變數 現在 的值到底是什麼會變得很難確定,也會不知道它從哪來的。這麼做的目的是為了開發閱讀程式碼的人的直覺和記性。直覺不佳的人必須一行一行分析程式碼,並追蹤每段程式碼分枝的變化。

這種方法的進階變化是偷偷地(!)在像是迴圈或函式之中換掉它的值。

舉個例:

function ninjaFunction(elem) {
// 20 行程式碼用來處理 elem
elem = clone(elem); // 另外的 20 行,用來處理複製後的 elem!
}

想要在函式第二部分使用 elem 的程式夥伴會非常驚訝… 只有在除錯檢查完程式碼後,他們才會發現原來他們是在使用複製體!

這經常在程式碼中看到,即使是對於經驗豐富的忍者來說也是非常致命。

底線的樂趣

在變數名稱前使用底線 ___,像是 _name__value。若只有你知道它們的意義就太讚了,或者更棒的是,加上去只是為了樂趣,根本沒有特別的意義存在,或是在不同的地方就有不一樣的意義。

你一槍殺死了兩隻兔子耶。首先,程式碼變得更長且更不易讀了,再來,開發夥伴會花很長的時間試圖理解底線的意義。

一個聰明的忍者會把底線放在某處,然後刻意避免在其他地方使用。這會讓程式碼更為脆弱且增加未來出錯的機會。

展現你的熱情

讓大家看看你是多麼的氣壯山河!像是 superElementmegaFrameniceItem 這種名稱,一定可以達到啟發讀者的功效。

從某方面來看,這樣確實有寫下些什麼:super..mega..nice..,但從另一方面來看 — 毫無細節可言。讀者也許得在上班時間花一兩個小時冥想,來尋找背後隱藏的意義。

重疊外部變數

夫處明者,不見暗中一物,
而處暗者,能見明中區事。
— 關尹子

將函式的內部與外部變數都使用一樣的名稱。很簡單,也不用花時間創造新名稱。

let user = authenticateUser();function render() {
let user = anotherValue();
...
...many lines...
...many lines...
...
...
... // <-- 某個程式設計師想在這裡使用 user,然後...
...
}

一個跳進 render 內的程式設計師,可能會沒注意到有個區域的 user 隱蔽了外部的變數。

然後他們會試圖將 user 視為外部變數 authenticateUser() 的結果來使用… 翻開覆蓋的陷阱卡!哈囉,除錯器…

副作用(Side-effects)無所不在!

有些函式看起來不改變任何東西,像是 isReady()checkPermission()findTags()… 他們被設想為執行計算、找出並回傳資料,而不改變內部的任何東西,換句話說就是沒有 “副作用(side-effects)”。

有個真正漂亮的技巧,就是在他們的主要任務之外,再加個 “有用的” 動作。

當你的同事看到一個名為 is..check..find.. 的函式改變了某些東西時,他的臉上一定會充滿迷惑 — 絕對能拓展你理性的界線。

另一個給人驚喜的方式是回傳非標準的結果。

展現你原始的想法!讓 checkPermission 呼叫不回傳 true/false,而是回傳某個包含檢查結果的複雜物件。

那些試圖寫下 if(checkPermission(..)) 的開發者,會懷疑為什麼這麼寫不起作用。告訴他們:”看文件!”,然後把這篇文章丟給他們。

強大的函式!

大道泛兮,
其可左右。
— 老子(道德經)

別讓名稱限制了函式,變得更廣泛吧。

舉個例,函式 validateEmail(email) 可以(除了檢查 email 是否正確之外)顯示錯誤訊息並要求重新輸入 email。

額外的動作不該明顯出現在函式名稱中,真正的忍者程式人員會使它們在程式碼中也不這麼顯眼。

把多個動作合併成一個以避免你的程式碼被重複使用。

想像一下,別的開發者只想要檢查 email 而不要輸出任何訊息時,你的函式 validateEmail(email) 做這麼多事就不適合他們啦。所以他們才不會在你冥想的時候來問你問題。

總結

上述的 “這些建議” 都由實際的程式碼得來… 有時甚至是由有經驗的開發者寫下的,甚至是比你更有經驗的人 ;)

  • 遵循部分,你的程式碼會變得充滿驚奇。
  • 遵循多數,你的程式碼會真正成為你的程式碼,沒有人會想改變它。
  • 遵循全部,你的程式碼將成為年輕開發者尋求啟發的寶貴案例。

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade