日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自解释的代码根本不存在,老老实实写注释吧

發(fā)布時間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自解释的代码根本不存在,老老实实写注释吧 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者 | Sven Gregori

譯者 | 薛命燈

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

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

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

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

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

自解釋的代碼是不存在的

反對給代碼寫注釋的人認(rèn)為,“代碼應(yīng)該好到不需要任何多余的解釋”。好的代碼確實(shí)不需要注釋來描述變量或函數(shù)是干什么用的。

// 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;

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

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

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

軟件開發(fā)困難重重

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

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

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

代碼注釋解析

在進(jìn)一步討論我們的問題之前,先讓我們來看看不同的代碼注釋風(fēng)格。

/** * Javadoc-style documentation comment. */ void?foo(void)?{if?(bar >?10) {/* regular comment */...} }

常規(guī)注釋就是編程語言本身定義的注釋。根據(jù)經(jīng)驗(yàn),它們不應(yīng)該被廣泛使用,因?yàn)樗鼈儍A向于用來解釋代碼在做什么。

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

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

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

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

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

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

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

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

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

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

/** * 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; }

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

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

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

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

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

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

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

讓注釋成為代碼的一部分

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

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

打破惡性循環(huán)

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

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

?英文原文

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

總結(jié)

以上是生活随笔為你收集整理的自解释的代码根本不存在,老老实实写注释吧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。