代碼自解釋不是不寫注釋的理由

有什么比花時間寫注釋更令人感到興奮的事情嗎?如果我沒有猜錯,你可能會說:“不好意思,所有事情都比寫注釋更令人感到興奮”。如果有人要你給代碼加上注釋,對你來說就像是一種侮辱。你的代碼寫得如此優雅,它已經足以說明它要做的事情,注釋是多余的,代碼就是一切。

無論是開源項目還是專業軟件開發,代碼注釋通常有兩種形式:要么沒有和要么毫無用處。任何領域或使用任何編程語言的程序員,無論他們來自世界的哪個地方,似乎都不喜歡給代碼寫注釋。如果你想講故事,可能會選擇不同的人生道路(比如去當作家?)。

這種不情愿甚至形成了某種范式和哲學觀點,認為代碼注釋實際上是有害的,任何試圖逃避它的人現在都可以愉快地重新討論這些主張。但是,稍微夸張一點說,我們實際上是在用這種方式破壞信息。雖然代碼注釋有時候確實會適得其反,但真正有害的是我們對它的看法。

說到底,代碼注釋就像是錯誤處理,我們很早就被告知它很重要,但卻無法理解其中的原因。我們越來越厭煩為同樣的老師、主管或煩人的隊友做這件事。但就像錯誤處理一樣,如果做得好,我們就是從中獲益最多的人。但要做到這一點,我們需要面對一些嚴酷的事實,并承認根本不存在所謂的自解釋代碼。

所以,讓我們來戳破其中的一些泡沫吧!

自解釋的代碼是不存在的

反對給代碼寫注釋的人認為,“代碼應該好到不需要任何多余的解釋”。好的代碼確實不需要注釋來描述變量或函數是干什么用的。

// bad start:int a = 4 * OFFSET;// but don't use a comment to tell what it does:int a = 4 * OFFSET; // initial foo value// instead choose a name telling it itself:int initial_foo = 4 * OFFSET;

確實,有意義的變量名根本不需要注釋,但這實際上更像是一種體面的編碼風格,而不是文檔。當這種片面的觀點變成反對使用代碼注釋的普遍理由時,問題就出現了。

問題是,即使變量、方法、類、函數、模塊的名稱是自解釋的,但這些并不能描述出代碼的全局面貌,也不一定能說明各部分代碼為什么要那么寫。當然,清晰的實現往往會讓我們產生一種錯覺,認為不需要再寫注釋了。當你花了幾個小時甚至幾天時間解決了手頭的問題,那些代碼在當下可能是完美的,然后你把它們打包、提交。

但是一個月后會怎樣?你能記住多少細節?它們還是那么有意義嗎?

軟件開發困難重重

當然,有人可能會爭辯說:“代碼就在那里,你看一下就明白了”。如果我們說的是某塊代碼是干什么用的,那么或許這么說是有道理的。但對于任何超出這個范圍的東西,深挖代碼可能是在浪費時間,就像在閱讀一本沒有索引的書,你要從頭讀起,才可能找到你需要的東西。

而且,這不僅僅是為了了解別人的代碼,或者向別人解釋你的想法。當你重新查看舊代碼或者修復錯誤時,你的腦子里是不是經常犯嘀咕,或者因為 git blame 顯示了你的名字而感到驚訝?然而,再往后,它們可能被忘得一干二凈,然后你會再次相信一切都應該是自解釋的,所有的細節都應該是明確無誤的。

無論你怎么努力,軟件本身并不會完全自解釋。這既不是你的錯,我也不是想要質疑你的能力,這與人類本身有關,我們低估了軟件的復雜性,而且人類的思維具有波動性。注釋的目的不是為了指出代碼中存在的缺陷,而是為了抵制編程語言本身存在的缺點。即使是最干凈的代碼也不可能自己解釋寫代碼的人在寫代碼時在想些什么。有可能一切都是完美的,但仍然會出錯。注釋并不是干凈代碼的替代方法,而是代碼的固有組成部分。

代碼注釋解析

在進一步討論我們的問題之前,先讓我們來看看不同的代碼注釋風格。

/*** Javadoc-style documentation comment.*/void foo(void) {if (bar \u0026gt; 10) {/* regular comment */...}}

常規注釋就是編程語言本身定義的注釋。根據經驗,它們不應該被廣泛使用,因為它們傾向于用來解釋代碼在做什么。

另一方面,文檔注釋從外部角度描述了全局變量、函數和模塊。在函數體內部,它們基本上就是常規注釋,工具通常會忽略它們。如果在函數內部有一些值得描述的東西,看看是否可以把它們放進函數描述本身。

文檔注釋本質上就是常規注釋加上一些額外的附件,例如額外的正斜杠/// doc comment、感嘆號//! doc comment或者/*! multiline doc comment /,或者Javadoc注釋中的附加星號/* doc comment */。實際上,其他編程語言和工具也支持Javadoc,所以這里就以它為例子。

當然,你也可以使用常規注釋,并忘掉那些時髦的標簽。不過,一些文檔生成器(如 Doxygen 或 Sphinx)可以直接根據注釋創建 PDF、HTML 或手冊頁,大多數現代 IDE 為它們提供了額外的顯示支持,省得你老是進行上下文切換,而且還可以為你提供一些有用的信息。

除了注釋的后處理之外,注釋的格式并不重要,重要的是你想要表達什么。

冗余的注釋聚焦在錯誤的信息上

我們已經得出結論,即不應該記錄代碼在做什么,而是記錄為什么要這么做以及怎樣做,但這究竟意味著什么呢?

人們不喜歡寫注釋的一個常見原因是“它們只是在陳述已經很明顯的東西”,所以注釋是多余的。對于一般性的注釋,確實難以反駁,特別是在面向對象語言的封裝方面。一些簡單的函數,比如 get_temperature() 的一般性描述可能如下所示:

/*** Returns the temperature.*/int get_temperature(void) {return temperature;}

這里的注釋確實沒有增加太多的價值,它本質上只是重復了函數的名字,只是在說明這個函數的作用。這不是我們想要的,我們想要的是代碼沒有告訴我們的東西。

這個函數非常簡單,所以寫注釋是絕對沒有必要的。但話又說回來,軟件開發當中沒有什么東西是真正簡單的。如果你夠仔細,就會發現每個函數都有值得寫的東西,而這些東西并不能從它的名字甚至是簡單的一兩行代碼中看出來。

/*** Returns the temperature in tenth degrees Celsius* in range [0..1000], or -1 in case of an error.** The temperature itself is set in the periodically* executed read_temperature() function.** Make sure to call init_adc() before calling this* function here, or you will get undefined data.*/int get_temperature(void) {return temperature;}

事實證明,這個看似簡單的函數有很多額外的信息可以寫。如果只是看代碼,可能無法明顯地看出其中的信息,包括內部數據處理和程序流程。當然,深挖代碼最終會獲得同樣的信息,但這樣會浪費很多時間和腦力。

有人可能會說,我們沒辦法為這些實現細節寫注釋。為什么要這樣?為什么不詳細說明那些現細節,讓別人可以更容易地理解代碼在做什么?

每個函數都有自己的特點,至少會有一個細節、副作用、異常、限制,等等,它們都值得寫出來,這意味著你可能需要從不同的角度來看待這個函數,才能找出它們。為此,你不可避免地要沉浸在代碼隱藏的細節當中,這樣才可能發現一些之前沒有想到過的特殊情況。因此,代碼注釋不僅可以幫助讀代碼的人理解代碼,還能幫助寫代碼的人更好地了解代碼的內部細節。

如果你確實找不到有用的信息,那么應該問問自己為什么要寫這些代碼。這些代碼存在的理由是什么?而這些理由就是有用的信息。之前的例子也可以是這樣:

/*** Returns the temperature.** This is for testing purpose only and should* never be called from a real program.*/int get_temperature(void) {return temperature;}

請注意,這段代碼與之前完全相同,于是這又把我們引向了另一個問題“看似自解釋的代碼的注釋通常都很簡單”:它可能含糊不清,可能會導致錯誤的假設和潛在的缺陷。指出這些細節并消除潛在的歧義對于提升代碼質量來說至關重要,這說明注釋應該成為代碼的重要組成部分。

同樣,如果不深入研究代碼,就無法發現每個函數的特點。當然,在這些不起眼的細節中,總有一些比另外一些更值得我們注意,并不是說函數所涉及的東西都會很有趣。認知偏差的范圍很廣,有些東西在這個時刻對你來說是顯而易見的,并不意味著對于其他人來說也是這樣——包括未來的你。

讓注釋成為代碼的一部分

現在我們來看看另一個人們不喜歡寫代碼注釋的原因:當代碼發生改變時,注釋會過時。但其實這只是一個偷懶的借口,在寫代碼時通常不會考慮將來會不會再去修改代碼,一旦代碼被提交并合并,就是確定和完美的,并永遠保持原樣。

代碼注釋的另一個更大的問題是,它們被視為獨立于代碼的東西,完全與代碼相分離。但如果我們將其視為代碼的組成部分,或者一種補充實體,那么只要代碼發生變化就會很自然地去調整注釋。

打破惡性循環

沒有人喜歡糟糕的代碼注釋,但排斥寫注釋對解決這個問題并沒有任何幫助。修復開發人員和代碼注釋之間的不正常關系是改善這種狀況的唯一方法,而將注釋視為代碼的組成部分是改善這種關系的第一步。

毫無疑問,在形成這種思維方式之前需要進行練習。從長遠來看,這對提升代碼質量來說是有益而無害的。

英文原文:

https://hackaday.com/2019/03/05/good-code-documents-itself-and-other-hilarious-jokes-you-shouldnt-tell-yourself/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275490.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275490.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275490.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux匯編中的注釋,Linux 匯編器:對照 GAS 和 NASM

Linux 匯編器:對比 GAS 和 NASM轉自 http://www.ibm.com/developerworks/cn/linux/l-gas-nasm.html#ibm-pcon與其他語言不同,匯編語言要求開發人員了解編程所用機器的處理器體系結構。匯編程序不可移植,維護和理解常常比較麻煩,通…

你可能不知道的package.json

大家好,我是若川。最近組織了源碼共度活動:1個月,200人,一起讀了4周源碼,參與的小伙伴都表示收獲很大。如果感興趣可以點擊鏈接掃碼加我微信 ruochuan12。今天推薦一篇相對簡單的文章。前言在上一篇npm init vitejs/ap…

基于上下文的rpn_構建事物-產品評論視頻中基于上下文的情感分析

基于上下文的rpnThe word “Social” has taken a whole new meaning in today’s digital era. Simply going out to enjoy is no longer the only “social” criteria. Social now is — giving a peek in your personal and professional life to your connections. Facebo…

可愛的 Python: 使用 mechanize 和 Beautiful Soup 輕松收集 Web 數據

可愛的 Python: 使用 mechanize 和 Beautiful Soup 輕松收集 Web 數據 使用 Python 工具簡化 Web 站點數據的提取和組織 David Mertz, Ph.D., 開發人員, Gnosis Software, Inc.從 2000 年開始,David Mertz 就一直在為 developerWorks 專欄 Charming Python 和 XML M…

廣西工學院c語言試題答案,廣西工學院的C語言考試試題

廣西工學院鹿山學院 2005 — 2006 學年第 2 學期課程考核試題 考核課程 《C語言程序設計》 (A卷)考核班級 學生數 印數 考核方式 閉卷 考核時間 120 分鐘一、選擇題(每題2分,共40分)1. 一個C語言的源程序中, 。A.必須有一個主函數2. 下列數據…

JavaScript 斷點調試技巧

大家好,我是若川。最近組織了源碼共度活動:1個月,200人,一起讀了4周源碼,參與的小伙伴都表示收獲很大。如果感興趣可以點擊鏈接掃碼加我微信 ruochuan12。之前推薦過很多次調試文章,說明調試的重要性&#…

大學生電子設計大賽案例分析_為大學生設計問答平臺—案例研究

大學生電子設計大賽案例分析Dealing with academic-related questions like picking a course, fulfilling a major requirement can be tedious and ineffective when you have to simultaneously balance school work, social activities, and focus on personal growth and …

最新最詳細最簡潔Eclipse調試PHP配置詳解(Xdebug,Zend Debugger)

搬家注:該日志寫于2011 年 04 月 07 日,Eclipse,PHP等版本號很多,更新也比較快,請注意文章中的版本。本文不一定幫您解決問題,但能給您一些解決問題的思路及一些概念。 最近開始做SRTP項目WebOS&#xff0c…

按鍵精靈易語言c,求助(把按鍵精靈的源碼轉為易語言的)

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓MoveTo 1203,673IfColor 1203,673,"252489",2 ThenMoveTo 417, 242Delay 10072LeftDown 1LeftClick 1LeftUp 1MoveTo 982, 551Delay 7660LeftDoubleClick 1Delay 10Delay 30LeftUp 1LeftUp 1LeftUp 1MoveTo 1102, 709Del…

入門前端學習路線圖【送書】

大家好,我是若川。記得點上方音頻聽小姐姐配音,超級好聽。華章圖書又贊助了書籍送福利給大家。本次送4本書的抽獎方式是:截止到9月6日(周一)20:00,在留言區留言任意內容。我會在留言區抽取「1位」關注我公眾…

單選按鈕設置為被選中狀態_為什么要設置錯誤的按鈕狀態

單選按鈕設置為被選中狀態當正確的方法出錯時 (When the right way goes wrong) Let’s say you want to create a click effect on an HTML button. The first idea that many people get is to do something that reproduces the feeling of the sound emitted by a real but…

「娃娃分享」-常見自校檢分析實例.

自校檢是許多軟件的保護手段之一,對軟件加個簡單的殼再增加自校檢在一定程序上可以抵擋住一大部分新手,不過,對許多人來說,這個保護已經很弱了。。下面講幾種常見的解決自校檢方法,寫的粗略,希望大家補充。…

用VC和MinGW導出dll的def和lib(a)文件

為什么80%的碼農都做不了架構師?>>> 原文地址:http://zhangyafeikimi.iteye.com/blog/404580 有了dll文件需要導出def文件: pexports zlib1.dll > zlib1.def 有了dll和def文件,需要導出MinGW的.a文件:…

51中斷編程c語言,[新人求指教]51C語言編程可否用中斷令循環結束提早結束

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓C51_C語言編程控制流水燈硬件電路 p0 接 led 8 個,P33 接按鍵使用中斷2開機燈按1~8逐位閃爍,并循環按鍵后改為 兩燈亮 的流水燈下面寫了個程序#include #include #define uchar unsigned char#define uint u…

產品設計美學案例分析_美學在產品設計中的重要性

產品設計美學案例分析重點 (Top highlight)In one of my previous jobs, I had really interesting debates with the CEO regarding whether we should spend more time improving the way our app looks and feels. ‘How could he not care that the design is outdated?! …

即將到來的ECMAScript 2022標準

大家好,我是若川。周末分享一篇相對簡單的文章。最近組織了源碼共度活動:1個月,200人,一起讀了4周源碼,參與的小伙伴都表示收獲很大。如果感興趣可以點擊鏈接掃碼加我微信 ruochuan12。另外:昨天的推文入門…

c語言中二叉樹中總結點,C語言二叉樹的三種遍歷方式的實現及原理

二叉樹遍歷分為三種:前序、中序、后序,其中序遍歷最為重要。為啥叫這個名字?是根據根節點的順序命名的。比如上圖正常的一個滿節點,A:根節點、B:左節點、C:右節點,前序順序是ABC(根節…

動態庫的創建與使用

1、動態庫文件的創建 (1)編寫源文件 (2)編譯生成動態庫 g -fPIC -shared -o libfile_operation.so file_operation.cpp 此編譯過程分為兩步,等同于下面的兩個命令: g -c -fPIC file_operation.cpp …

ux設計中的各種地圖_UX寫作中的移情

ux設計中的各種地圖Demetri Martin is a master of comedic situations. If you’ve never seen Demetri Martin是喜劇情境的大師。 如果你從未見過 him before, he has a sort of dry brand of observational humor, relying more on anecdotes than full stories, and often…

字符串搜索。HOJ1530 Compound Words。

stl set實現字符串搜索。。效率一般。(附二分搜索。) Compound WordsTime limit:1sec.Submitted:233Memory limit:32MAccepted:81Source: Waterloo ACM Programming Contest Sep 28, 1996 You are to find all the two-word compound words in a dictionary. A two-word compo…