大家肯定都有寫過注釋,注釋這個東西不同于代碼,與程序邏輯的正確性沒有直接的關系,所以每個人可能都有自己的風格,每個人對哪里應該寫注釋,注釋應該寫成什么樣子可能都有自己的理解。
我個人對注釋的理解經歷了四個階段。
第一個階段,完全不寫注釋,這個階段還處在代碼邏輯的實現上面,花大量的時間去調試,修改代碼,根本就無暇顧及到注釋這個事情。過了一段時間后,發現之前寫的又臭又長的代碼完全看不明白了,才意識到注釋的重要性,于是開始慢慢進入了第二個階段。
第二個階段,哪哪都是注釋,每個文件,每個類,每個函數,設置每個分支,每個變量,都有一個注釋來說明,就怕漏掉某個小細節然后就看不懂了。后來又發現了一個叫做文檔注釋的東西(doxygen),這個東西不要太酷,可以根據你的寫的注釋直接生成文檔,于是到處都是文檔注釋,每個文件里面都有一段簡介,而簡介里面最重要的內容可能就是 @author: hatlonely
,生怕別人不知道這些這么low的代碼是你寫出來的???♀?,每個函數參數,函數參數的返回值等等,也都有詳盡的注釋,注釋的長度已經遠遠超過了代碼的長度。看起來好像媽媽再也不用擔心我看不懂之前寫的代碼了,然而,一段時間當我重新讀到add這個函數的注釋的時候,我發現這些信息對我來說好像并沒有用,這段代碼已經足夠的清晰簡單,甚至比注釋更容易讀懂,那這個注釋在這里存在的意義又是什么呢,僅僅是為了生成文檔注釋嗎?而更大的問題可能是,如果我要新增一個函數,add3(int a, int b, int c)
我不得不按照之前的文檔注釋格式寫一大堆的注釋……注釋的維護也是一個大問題,每次邏輯的變更,都需要去改對應的注釋,如果忘記修改,注釋和代碼邏輯的不一致會讓人更加困惑。于是注釋的維護變成了一件非常無聊的事情,大大地降低了編程體驗,而另一方面冗長繁復的注釋也降低了代碼的閱讀體驗。
// @file: 談談注釋.md
// @date: 2018-01-19 14:00
// @author: hatlonely
// @brief: 一些對注釋的理解
// @brief: 求兩個數的和
// @param a 加數
// @param b 被加數
// @return 和
int add(int a, int b) {
return a + b;
}
第三個階段,代碼即注釋。突然有一天,看到一個觀點,代碼是一種藝術,本身就是美,就像是詩歌,你見過一首詩歌里面插入了很多注釋嗎?注釋不是對代碼的翻譯,而絕大多數時候,你在考慮用一個注釋解釋一個變量的時候,往往可以通過一個好的變量名來避免這個注釋,同樣,當你要注釋某段邏輯的時候,也往往可以通過優化這段邏輯結構,使用一些可讀性更強的變量來描述某些過程。于是我去掉了所有的注釋,開始編寫可讀性更強的代碼,開始糾結每一個普通的小變量的命名,開始站在普通人的角度去思考代碼的邏輯,讓代碼更貼近自然語言,把讓沒有任何計算機基礎的人都能讀懂我的代碼作為目標。于是現在代碼看起來清爽了不少,代碼本該如此簡單。但是我滿意了嗎?并沒有。
第四個階段,必要的注釋。畢竟代碼不是詩歌,如果沒有當時的文化背景以及別人的解讀,大部分是詩歌普通人應該也是讀不懂的吧。代碼邏輯是由特定的場景決定,同一份代碼在不同的場景下面也可能是完全不同的含義,所以為什么會是這樣一個邏輯,是這個場景下特定的背景所決定的,而代碼本身并不能包含這些背景信息。比如下面這段代碼,關于ios過濾的這段邏輯,是因為目前的業務上暫時還沒有這個需求決定的,這里的注釋給了我們一些額外的信息,對我們理解這段邏輯有很大的幫助,如果沒有這段注釋,一個月后,你可能也忘記了為什么要有ios這樣一個特殊的邏輯,不敢動也不知道,久而久之這些代碼就成了謎一樣的存在。嗯,看起來很優雅,現在我滿意了!
func checkDeviceType(info DeviceInfo, deviceTypeSet map[int32]struct{}) bool {
// ios的設備類型不想android那么多,暫時還沒有定向需求
if info.platform != "ios" {
return true
}
if _, ok := deviceTypeSet[info.deviceType]; ok {
return true
}
return false
}
下一個階段是什么呢?是時候提高一下自己的表述能力了????。
轉載請注明出處
本文鏈接:http://hatlonely.github.io/2018/01/19/談談注釋/