許多註解之所以無用,是因為它們重複了程式碼本身——所有資訊都能從旁邊的程式碼直接推得。
反例 1:每一行程式碼都加翻譯#
ptr_copy = get_copy(obj) # Get pointer copy
if is_unlocked(ptr_copy): # Is obj free?
return obj # return current obj
if is_copy(ptr_copy): # Already a copy?
return obj # return obj
thread_id = get_thread_id(ptr_copy)
if thread_id == ctx.thread_id: # Locked by current ctx
return ptr_copy # Return copy只有 Locked by current ctx 那一行可能透露程式碼看不出的事,其他都只是把程式碼再寫一遍。
反例 2:什麼都沒講的註解#
// Add a horizontal scroll bar
hScrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
add(hScrollBar, BorderLayout.SOUTH);
// Add a vertical scroll bar
vScrollBar = new JScrollBar(JScrollBar.VERTICAL);
add(vScrollBar, BorderLayout.EAST);
// Initialize the caret-position related values
caretX = 0;
caretY = 0;
caretMemX = null;前兩個註解的程式碼本身已夠清楚;第三個雖有寫註解的空間,但這個註解什麼資訊也沒提供。
自我檢查的方法#
寫完註解後問自己:
「一個從沒看過這段程式碼的人,能光看旁邊程式碼就寫出這條註解嗎?」
如果可以——這條註解沒幫上忙。
反例 3:把名字翻成句子#
/* Obtain a normalized resource name from REQ. */
private static String[] getNormalizedResourceNames(HTTPRequest req) ...
/* Downcast PARAMETER to TYPE. */
private static Object downCastParameter(String parameter, String type) ...
/* The horizontal padding of each line in the text. */
private static final int textHorizontalPadding = 4;這些註解只是把名稱拆成句子,加幾個介系詞——沒有任何附加資訊。第二個例子的「to」是註解中唯一不在程式碼裡的字。
紅旗:註解重複程式碼(Red Flag: Comment Repeats Code)#
註解中的資訊已經能從旁邊的程式碼看出 → 註解沒幫忙。
一個典型徵兆:註解使用了與被描述對象相同的字眼。
真正應該補的資訊#
上面的反例其實漏掉了很多重要的事:
- 什麼是
normalized resource name?回傳陣列的元素是什麼? downcast是什麼?- padding 的單位是什麼?是某一邊還是兩邊?
改寫範例#
/*
* The amount of blank space to leave on the left and
* right sides of each line of text, in pixels.
*/
private static final int textHorizontalPadding = 4;- 補上單位(pixels)
- 說明 padding 用在兩側
- 用「blank space」解釋什麼是 padding(避免術語陷阱)
寫好註解的第一步#
用與名稱不同的字寫註解。
註解裡的字應該提供「實體意義上的額外資訊」,而不是把名字再說一遍。