PTT推薦

Re: [心得] 好的註解是解釋為何需要這段 code

看板Soft_Job標題Re: [心得] 好的註解是解釋為何需要這段 code作者
gobears5566
(golden bear 5566)
時間推噓29 推:29 噓:0 →:62

※ 引述《alihue (wanda wanda)》之銘言:
: 轉自推特
: https://twitter.com/BenLesh/status/1372562839475470336?s=20
: Add comments about WHY code exists, not what it does.
: The code is right there, we know what it does.
: 註解應該用來解釋這段 code 的背景需求/含意,
: 而不是把 code 表面上的意思再講一次

上週在重構某段程式碼時,其中一位同事在 code review 中建議把某個註解刪掉,另一個同事看到這個評論時,在下面留了言說他認為不應該刪掉,於是我們就拉了一個小討論,聊在程式碼中寫註解這件事。

因為這個經驗,我回去重翻史丹佛電腦科學教授 John Ousterhout 寫的《A Philosophyof Software Design》一書,並整理了筆記。該教授的觀點是認為程式碼寫註解有很多好處,但不是任何地方都該寫註解。

在版上找到這篇之前有版大發的文,基本上跟 John Ousterhout 教授的觀點一樣,
就是註解要解釋背後的「為什麼」,而不是把程式碼做的事重複說一次。

------ (以下是我讀完該章節後整理的筆記) ------

## 網誌好讀版: http://bit.ly/3WdTo1b

每當提到在程式中寫註解 (comments),你大概會在網路上看到兩派人馬,有人覺得應該要寫註解;又有另一群人覺得程式碼應該要寫得夠清楚,如果有註解就代表寫不夠清楚,應該要重構而不是加註解。當然除了這極端的兩派人馬外,多數人都是在中間,部分的程式碼寫註解,但不會全部都寫。

關於寫註解這件事,在 《A Philosophy of Software Design》 書當中也有談及。JohnOusterhout 教授的觀點是,如果註解寫得好,將有效改善整體的系統設計。假如你是反註解派的人,或許可以一起來讀讀他為什麼這麼認為。


## 程式本身寫得夠清楚,就不用註解嗎?
「程式本寫得夠清楚,就不用註解」是很多人認為不該寫註解的第一大理由。然而程式本身或許可以清楚表達該程式碼做的事,但不能解釋「為什麼」要這樣寫,也不能解釋在什麼情境可能比較適合某個方法。對於這些相對後設 (meta) 的內容,註解就是很好的幫手。

更進一步說,好的軟體設計,應該要把複雜度藏起來,要藏起複雜度,我們需要抽象化,讓其他使用該段程式碼的開發者,可以不用去管背後的細節。因此,如果一個開發者,還要去讀程式的細節才能懂如何用該函式或方法,那就失去抽象化的意義。寫註解可以讓其他開發者,不用去讀程式裡頭的細節也知道如何用該函式或方法,這才能達到抽象化的意義。因此不論程式本身寫的清楚與否,好的抽象化搭配好的註解,都是對整個程式庫的維護有幫助的。


## 別說你沒時間寫註解
在開發時,很多開發者會認為寫註解的優先順序比較低,因此會想把時間花在寫新功能,而不是為已經開發好的功能寫註解。然而在軟體開發中,永遠有寫不完的功能,如過說因為要開發新功能而沒時間寫註解,就永遠不會有註解。從長遠的角度來看,這樣的代價是程式庫的可維護性會降低。如果從效益與成本的角度來看,寫註解的時間,會遠比其他開發者花在弄懂沒註解的程式所花的時間要少很多。


## 不要找其他不寫註解的理由
很多開發者也會找其他理由不寫註解。例如認為註解如果沒隨著程式更新,反而會誤導人;或者是因為過去讀過別人寫的註解覺得沒用,就認為註解沒有用。這些都是外部因素,無法證成註解本身沒有效益。此外這些都是可以透過好的流程而解決的,所以作者認為不要找這些理由不寫註解,而是要去打造更好的流程來改善這些問題。


## 寫註解的好處
上面談了這麼多,大概可以看出 John Ousterhout 教授有強烈的觀點認為要寫註解。不過回過頭來說,寫註解有什麼好處呢? 他認為最大的好處在於註解可以捕捉到程式碼沒辦法傳達的資訊,這能夠讓未來要維護這段程式碼的開發者,能夠更快速地上手。特別對於團隊中加入的新成員,程式碼中的註解可以大幅降低讀程式的認知負擔 (cognitive
load),以及減少未知。

如果沒有記錄下這些脈絡與原因,未來的開發者就不會知道為什麼當初是這樣寫,這變得只能猜測原作者的意圖。這不僅更耗時,也可能會因為理解錯原本的意圖,導致在維護該段程式碼時出錯。很多時候,未來要維護程式碼的是自己,許多人在寫完某段程式碼幾個月後,可能忘了自己當初為什麼這樣寫,所以寫註解不僅是幫助其他開發者,也很可能是在幫助未來的自己。


## 註解該寫什麼?
雖說 John Ousterhout 教授的觀點是認為寫註解對軟體設計有幫助,但他也同意不是什麼都該寫成註解。他認為只有在程式碼中不顯而易見的才該寫註解 (comments should
describe things that aren’t obvious from the code)。

在軟體設計中最重要的抽象化,即是提供一個更簡易的思考方式,讓開發者可以不用深入過於細節的部分。即使開發者可以透過細讀程式碼來了解其如何運作,但這樣做太花時間。John Ousterhout 教授的觀點認為開發者應該要不讀程式碼內容,即可理解模組提供的抽象化,而註解是能夠協助做到這樣的方法。


## 不要重複程式碼本身
前面提到,註解應該要講「為什麼」這樣寫,而不是講程式碼在做什麼。畢竟程式碼本身就代表程式碼在做的事,如果註解在寫一次,會是多此一舉。下面是書中提到的負面教材,基本上註解就是把程式碼做的事情。

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

要怎麼判斷你寫的這段註解是不是跟程式碼本身一樣? 書中提到,在你寫完註解後可以問問自己「如果某個之前沒讀過這段程式碼的人,能不能看著這段註解寫出程式碼?」如果可以的話,就代表註解只是在描述程式碼,而不是在解釋為什麼這樣寫該段程式碼。因此,在寫完註解後,可以再比對一下程式碼與註解,如果重複就真的不推薦寫。


## 從讀者的角度出發
最後 John Ousterhout 教授提到,寫註解要從程式碼讀者的角度出發,要思考有哪些關鍵資訊是讀者不知道的。特別是在程式碼審查 (code review) 時,如果你寫的某段程式碼讓別人說很難懂,或者某個資訊讓別人說並不顯而易見,這時候不要去跟對方爭,而是去想為什麼對方會有困惑,以及你可以如何靠註解讓程式碼更好被理解。

(文末備註:這個章節本身有很多範例,但為了避免筆記變太長,就僅有放其中一個。有興趣透過案例更具體了解作者的觀點的話,推薦直接買這本書來讀)。





--
南漂一不小心漂到了新加坡
https://www.explainthis.io/zh-hant/singapore

--

※ PTT留言評論
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 116.86.64.199 (新加坡)
PTT 網址

FukadaKyoko01/15 20:44推~感謝分享

S206703001/15 21:19推 謝謝大大分享

ohmylove34701/15 21:25好文推推

prag22201/15 21:57沒時間看完整篇文章,這就跟一萬小時變大師的觀點呵呵

iamOsaka01/15 22:43

derekjj01/15 23:12推 我註解都看心情 然後畫恐龍註解圖 嘻嘻

holebro01/15 23:59講的好

viper970901/16 00:03推分享~註解本來就該寫這段在做啥,為啥這樣做

drajan01/16 01:18推~上次看這本書好久以前了 看完心得整理好像又讀一遍了

wei11501/16 02:04我想要知道函式的功能 和為什麼要用無符號整數來存指標QQ

zrna051501/16 08:04推,meta data那段講的不錯

aaa123413601/16 08:45分享推

lou0101/16 09:06感謝分享~

aidansky098901/16 09:11那需求一直變,後續也要持續維護這段註解嗎?

vi00024601/16 09:50我記憶力很差 我的註解都是為了讓以後維護的我看得懂這

vi00024601/16 09:50段code在寫啥

leolarrel01/16 10:30樓上的狀況我也有,只是我都用git取代註解就是了

hobnob01/16 10:30回 aid:我自己會註解加說是什麼時候的需求、修改的新邏

hobnob01/16 10:30輯是什麼,程式註解我都會維護

t6414101/16 10:57註解是需要維護的,但註解只是輔助工具,理論上不會多到

t6414101/16 10:57造成負擔,如果會,可能是程式太亂需要大量註解,或是有

t6414101/16 10:57太多沒必要的註解

chatnoir01/16 11:21我註解只會寫特殊的商業邏輯來輔助程式碼的不足~

knives01/16 11:53推樓上

fiiox301/16 11:55當文件的一環吧

fiiox301/16 11:55文件要維護,註解當然也要

yuinami01/16 12:19優文推一個,謝謝分享

wulouise01/16 12:28註解當然要維護啊,但至少沒維護歷史看得出來

aidansky098901/16 13:44感謝回覆,之前看clean code提到很多寫註解的壞處

aidansky098901/16 13:44,像是接手的人不一定會維護註解、註解缺少維護可

aidansky098901/16 13:44能會過時、誤導等壞處,後來只有TODO我才會寫註解

aidansky098901/16 13:44,寧可後人多跟PM確認新的現狀

aidansky098901/16 13:45不然註解寫出來,也不太有人敢修改、刪除

aidansky098901/16 13:45可能也是個問題

foreverk01/16 15:15沒寫註解基本上也不應該隨意修改刪除啊,要做的事情是

foreverk01/16 15:15補測試或是找人釐清需求,再去做變動,註解就是輔助工

foreverk01/16 15:15程師更好做到這些事

foreverk01/16 15:21很多人不寫註解或是不喜歡文件以及測試的理由都是要多

foreverk01/16 15:21維護的工,但往往省略掉這些以後,是花更多的時間開會

foreverk01/16 15:21,或是慢慢變技術債

fiiox301/16 18:24“不一定會維護“這為啥要算註解的缺點....

fiiox301/16 18:25整個軟體開發一堆東西都有人不維護= =

foreverk01/16 19:09另外需求一直變並不是不寫註解的理由,不寫就是用人腦

foreverk01/16 19:09記憶,沒紀錄還可能記錯,基本上就是賭這個未爆彈不會

foreverk01/16 19:09炸到你而已

aidansky098901/16 19:33修改刪除是指註解,因為不及時更新註解就會隨需求

aidansky098901/16 19:33變動過時,可能造成誤導而非指引

gobears556601/16 19:46這本書作者的論點跟 foreverk 大說的蠻相近的

gobears556601/16 19:46這位史丹佛教授在書中最開始就提到,他不認同蠻多

gobears556601/16 19:47Clean Code 裡面提到的觀點,但他也不覺得自己的就

gobears556601/16 19:47適合在所有脈絡。所以他的書名是 a philosophy

gobears556601/16 19:47而不是 the philosophy

foreverk01/16 20:38如果指得是不敢修改或刪除註解,那就代表改code的人並

foreverk01/16 20:38沒有完全掌握這項功能,改善方式應該是增加掌握度,而

foreverk01/16 20:38不是捨棄註解本身

jay123peter01/16 21:54

lovdkkkk01/16 21:55假如有好好寫 commit 訊息,再寫個簡單 script 可以過濾

lovdkkkk01/16 21:56時間/檔案/行數/關鍵字/作者 找出相關 commit 也不錯

moom5030201/17 00:18好的程式不需要註解,你說得都是文件應該要做到的

gggaaammm01/17 00:48

foreverk01/17 02:09不寫註解很常伴隨著不寫文件,最常見的第二個理由就是

foreverk01/17 02:09認為好程式不需要註解/文件,可是一些特殊商業邏輯所產

foreverk01/17 02:09生的程式,他不好但他是因應當時時空背景而生,這類情

foreverk01/17 02:09況還不寫,那就是上面我說的未爆彈

foreverk01/17 02:17樓上說的commit也是應該要好好寫的一點,甚至應該pr也

foreverk01/17 02:17好好寫,不想維護一整份文件的話,更應該從這些細節去

foreverk01/17 02:17提升程式可維護性

leolarrel01/17 10:12寫註解這種事就是誰當老闆就聽誰的...

leolarrel01/17 10:14現實世界就是階級,書再怎麼賣學校再有名都沒用

vi00024601/17 14:12如果有些重構會搬移程式碼到不同的專案或檔案

vi00024601/17 14:12這時git的紀錄也很難追踨

lovdkkkk01/17 20:43一個方式是搬家時舊的留著標 deprecated, see also...

lovdkkkk01/17 20:44留個線索給人查

superpandal01/17 22:18不認同 為什麼不是精簡化實現而是把有複雜度的東西藏

superpandal01/17 22:19起來 這團code怎麼亂七八糟都沒差反正有註解? 現在

superpandal01/17 22:21一堆東西坑很多就是這樣來的 包含框架

superpandal01/17 22:21甚至語言底層本身如果你不去仔細研究也會被坑到

superpandal01/17 22:22寫程式有兩種方式 一種是把程式寫的很簡單 明顯不容

superpandal01/17 22:22易有缺陷 一種是寫的很複雜 讓別人看不出有明顯的缺

superpandal01/17 22:23

superpandal01/17 22:24依照這樣搞你邊寫沒寫可以模糊焦點的註解 還可以邊藏

superpandal01/17 22:25bug和洞

superpandal01/17 22:26s/沒寫//

kyoe01/18 00:48有沒有可能一段程式複雜到需要註解的時候就是應該再拆分它然

kyoe01/18 00:48後把功能單一化的時候?

foreverk01/18 06:42我的經驗是,通常不是程式複雜到需要註解,而是因應特

foreverk01/18 06:42殊需求而出現的程式需要,他可能寫死很多地方,程式風

foreverk01/18 06:42格明顯不符,或根本是糞code,但暫時需要

strlen01/19 08:28我們非英語系國家 不然解法就是在method名稱上取一個好一

strlen01/19 08:28點的名稱讓大家所見即所得 然後一個method盡量只做一件事

strlen01/19 08:29但一堆人英文不好ABC狗嘎D method名稱亂取一通