學而不思則罔,思而不學則殆。
過去的程式設計忍者使用這些技巧來磨練程式維護人員的心智。
程式碼審查大師在測試任務中尋找這些技巧。
新手開發人員有時比程式忍者更擅長使用它們。
仔細閱讀它們,找出你是忍者、新手,還是程式碼審查者?
許多人嘗試走忍者路線,但只有少數人成功。
簡潔是智慧的靈魂
讓程式碼盡可能簡短,展現你的聰明才智。
讓微妙的語言功能引導你。
例如,看看這個三元運算子'?'
// taken from a well-known javascript library
i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
很酷,對吧?如果你這樣寫,遇到這行程式碼並試圖了解i
是什麼值的開發人員將會度過一段快樂時光。然後來找你,尋求答案。
告訴他們較短的總是較好,引導他們走上忍者的道路。
單字母變數
道隱於無言,唯道善始善終。
縮短程式碼的另一種方法是在所有地方使用單字母變數名稱,例如a
、b
或c
。
一個短變數會像真正的忍者在森林中一樣消失在程式碼中。沒有人能夠使用編輯器的「搜尋」功能找到它。即使有人做到了,他們也無法「解碼」a
或b
名稱的意義。
…但有一個例外。真正的忍者絕不會在"for"
迴圈中使用i
作為計數器。任何地方都可以,但這裡不行。四處看看,還有許多更奇特的字母。例如,x
或y
。
如果迴圈主體佔用 1-2 頁(如果可以,請延長),則使用奇特的變數作為迴圈計數器特別酷。然後,如果有人深入查看迴圈,他們將無法快速找出名為x
的變數是迴圈計數器。
使用縮寫
如果團隊規則禁止使用單字母和模糊名稱,請縮短它們,使用縮寫。
像這樣
list
→lst
。userAgent
→ua
。browser
→brsr
。- …等
只有真正具有良好直覺的人才能理解這些名稱。試著縮短所有內容。只有有價值的人才能維護你的程式碼開發。
飛得高。抽象化。
大圓無角
大器晚成
大音希聲
大象無形
在選擇名稱時,請嘗試使用最抽象的字詞。例如 obj
、data
、value
、item
、elem
等。
-
變數的理想名稱是
data
。只要可以,就使用它。畢竟,每個變數都包含 資料,對吧?…但是如果
data
已經被使用了怎麼辦?試試value
,它也是通用的。畢竟,變數最終會得到一個 值。 -
根據其類型命名變數:
str
、num
…試試看。年輕的入門者可能會想 - 這些名稱對忍者真的有用嗎?的確如此!
當然,變數名稱仍然表示一些東西。它表示變數中的內容:字串、數字或其他東西。但是當局外人試圖理解程式碼時,他們會驚訝地發現實際上根本沒有任何資訊!最終將無法更改你深思熟慮的程式碼。
透過除錯可以輕鬆找出值類型。但是變數的意義是什麼?它儲存哪個字串/數字?
沒有良好的冥想,根本無法弄清楚!
-
…但是如果沒有更多這樣的名稱呢?只要新增一個數字:
data1、item2、elem5
…
注意力測試
只有真正專注的程式設計師才能理解你的程式碼。但是如何檢查?
其中一種方法 - 使用類似的變數名稱,例如 date
和 data
。
在可以的地方混合它們。
快速閱讀此類程式碼變得不可能。當出現錯字時…嗯…我們會卡很久,是時候喝茶了。
智慧的同義詞
可以言說的道,不是不變的道。可以命名的名,不是不變的名。
對 相同 的事物使用 相似的 名稱,讓生活更有趣,並向大眾展現你的創造力。
例如,考慮函式前綴。如果函式在螢幕上顯示訊息 - 以 display…
開頭,例如 displayMessage
。然後,如果另一個函式在螢幕上顯示其他內容,例如使用者名稱,請以 show…
開頭(例如 showName
)。
暗示這些函式之間存在微妙的差異,而實際上並不存在。
與團隊中的忍者夥伴達成協議:如果 John 在程式碼中使用 display...
開始「顯示」函式,那麼 Peter 可以使用 render..
,而 Ann 則使用 paint...
。注意程式碼變得更有趣且多樣化。
…現在是帽子戲法了!
對於具有重要差異的兩個函式,請使用相同的前綴!
例如,函式 printPage(page)
將使用印表機。函式 printText(text)
會將文字放在螢幕上。讓不熟悉的讀者仔細思考類似名稱的函式 printMessage
:「它將訊息放在哪裡?印表機還是螢幕上?」為了讓它真正發光,printMessage(message)
應該在新的視窗中輸出它!
重複使用名稱
一旦整體被分割,各部分
需要名稱。
已經有足夠多的名稱了。
必須知道何時停止。
僅在絕對必要時新增變數。
相反地,重複使用現有的名稱。只要將新的值寫入其中即可。
在函式中,請嘗試僅使用作為參數傳遞的變數。
這將使識別變數中現在的確切內容變得非常困難。還有它來自哪裡。目的是培養閱讀程式碼的人的直覺和記憶力。直覺較弱的人必須逐行分析程式碼,並追蹤每個程式碼分支的變更。
這種方法的高階變體是在迴圈或函式中間秘密地 (!) 用類似的東西取代值。
例如
function ninjaFunction(elem) {
// 20 lines of code working with elem
elem = clone(elem);
// 20 more lines, now working with the clone of the elem!
}
一位想要在函式後半部使用 elem
的程式設計師會感到驚訝…只有在除錯期間,在檢查程式碼後,他們才會發現他們正在使用複製品!
在程式碼中經常看到。即使對於經驗豐富的忍者來說,也是致命有效的。
為了好玩而使用底線
在變數名稱之前加上底線 _
和 __
。例如 _name
或 __value
。如果只有你知道它們的含義,那就太好了。或者,更好的是,僅為了好玩而新增它們,完全沒有特定的含義。或在不同的地方有不同的含義。
一箭雙鵰。首先,程式碼變得更長且更難讀取,其次,其他開發人員可能會花很長時間試圖找出底線的含義。
一位聰明的忍者會在程式碼的某個地方加上底線,而在其他地方避開它們。這使得程式碼更加脆弱,並增加了未來出現錯誤的可能性。
展現你的愛
讓所有人看到你的實體有多麼宏偉!像 superElement
、megaFrame
和 niceItem
這樣的名稱肯定會讓讀者茅塞頓開。
的確,一方面,寫了一些東西:super..
、mega..
、nice..
但另一方面 - 這沒有提供任何細節。讀者可能會決定尋找隱藏的含義,並沉思一兩個小時他們有償的工作時間。
覆蓋外部變數
在光線中時,無法在黑暗中看到任何東西。
在黑暗中時,可以在光線中看到所有東西。
在函式內外使用相同的變數名稱。很簡單。無需費力想出新名稱。
let user = authenticateUser();
function render() {
let user = anotherValue();
...
...many lines...
...
... // <-- a programmer wants to work with user here and...
...
}
跳進 render
的程式設計師可能會沒有注意到有一個本機 user
遮蔽了外部 user
。
然後他們會嘗試使用 user
,假設它是外部變數,是 authenticateUser()
的結果……陷阱出現了!你好,除錯器……
到處都是副作用!
有些函式看起來沒有改變任何東西。例如 isReady()
、checkPermission()
、findTags()
……假設它們執行計算,尋找並傳回資料,而不會改變它們之外的任何東西。換句話說,沒有「副作用」。
一個非常漂亮的技巧是在它們中新增一個「有用的」動作,除了主要任務之外。
當你的同事看到一個名為 is..
、check..
或 find...
的函式改變了一些東西時,他們臉上驚訝的表情 - 肯定會擴展你的推理界限。
另一個驚喜的方式是傳回非標準結果。
展現你的原創思考!讓 checkPermission
的呼叫傳回的不是 true/false
,而是一個包含檢查結果的複雜物件。
那些嘗試寫 if (checkPermission(..))
的開發人員會疑惑為什麼它不起作用。告訴他們:「閱讀文件!」並提供這篇文章。
強大的函式!
偉大的道到處流動,
向左也向右。
不要受限於函式名稱所寫的內容。要更廣泛。
例如,函式 validateEmail(email)
可以(除了檢查電子郵件是否正確)顯示錯誤訊息並要求重新輸入電子郵件。
函式名稱不應明顯顯示其他動作。真正的忍者程式設計師會讓它們在程式碼中也不明顯。
將多個動作合併成一個動作可以保護你的程式碼不被重複使用。
想像一下,另一個開發人員只想檢查電子郵件,而不輸出任何訊息。你的函式 validateEmail(email)
同時執行這兩個動作,不適合他們。因此,他們不會因為詢問任何相關問題而打斷你的冥想。
摘要
以上所有「建議」都來自實際程式碼……有時是由經驗豐富的開發人員撰寫的。也許比你更有經驗 ;)
- 遵循其中一些建議,你的程式碼將充滿驚喜。
- 遵循其中許多建議,你的程式碼將真正屬於你,沒有人會想改變它。
- 遵循所有建議,你的程式碼將成為尋求啟蒙的年輕開發人員的寶貴課程。
留言
<code>
標籤,要插入多行程式碼,請將它們包在<pre>
標籤中,要插入超過 10 行的程式碼,請使用沙盒(plnkr、jsbin、codepen…)