九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
編寫代碼注釋的最佳實踐

作者 | Ellen Spertus

譯者 | 王雪迎   

出品 | CSDN(ID:CSDNnews)

雖然有很多資源可以幫助程序員編寫更好的代碼,比如書籍或靜態(tài)分析器,但是很少有資源可被用于編寫更好的注釋。雖然度量一個程序中的注釋數(shù)量很容易,但衡量注釋的質(zhì)量卻很難,而且兩者并不一定相關(guān)。差的注釋比根本不寫注釋更糟糕。這里有一些規(guī)則可以幫助你實現(xiàn)一種折中的方法。

麻省理工學(xué)院的著名教授Hal Abelson曾說過:“程序必須寫給人們閱讀,而只是附帶地讓機(jī)器執(zhí)行?!彪m然他可能故意低估了運行代碼的重要性,但卻注意到了程序有兩種截然不同的受眾。編譯器和解釋器會忽略注釋,找出同等容易理解的所有語法正確的程序。而人類讀者則完全不同。我們發(fā)現(xiàn)有些程序比其它的更難理解,此時就會通過查看注釋來幫助我們理解這些程序。

雖然有很多資源可以幫助程序員編寫更好的代碼,比如書籍或靜態(tài)分析器,但是很少有資源可被用于編寫更好的注釋。雖然度量一個程序中的注釋數(shù)量很容易,但衡量注釋的質(zhì)量卻很難,而且兩者并不一定相關(guān)。差的注釋比根本不寫注釋更糟糕。正如Peter Vogel所述:

  1. 編寫并維護(hù)注釋是一項開銷。

  2. 編譯器不會檢查注釋,因此無法確定注釋是否正確。

  3. 另一方面,你可以保證計算機(jī)完全按照你的代碼所示運行。

所有這些觀點都是正確的,但如果走到另一個極端,即從不寫注釋,那將是一個錯誤。這里有一些規(guī)則可以幫助你實現(xiàn)一種折中的方法:

  • 規(guī)則1:注釋不應(yīng)與代碼重復(fù)。

  • 規(guī)則2:好的注釋不能成為代碼不清晰的借口。

  • 規(guī)則3:如果無法寫出一個清晰的注釋,代碼可能有問題。

  • 規(guī)則4:注釋應(yīng)該消除混亂,而不是引起混亂。

  • 規(guī)則5:在注釋中解釋不規(guī)范的代碼。

  • 規(guī)則6:提供復(fù)制代碼的原始出處鏈接。

  • 規(guī)則7:在可能提供幫助的地方引入指向外部參考的鏈接。

  • 規(guī)則8:在修復(fù)bug時添加注釋。

  • 規(guī)則9:使用注釋來標(biāo)記未完成的實現(xiàn)。

本文其余部分將逐條解釋這些規(guī)則,提供示例并說明如何以及何時應(yīng)用它們。

01

規(guī)則1:注釋不應(yīng)與代碼重復(fù)

許多初級程序員會寫太多注釋,因為他們接受了入門指導(dǎo)老師的培訓(xùn)。我曾見過計算機(jī)科學(xué)系的高年級學(xué)生為每對大括號加上一條注釋,以表示該塊結(jié)束:

if (x > 3) {} // if

我也聽說過老師要求學(xué)生對每一行代碼進(jìn)行注釋。雖然這對極為初級者來說可能是一個合理的策略,但這樣的注釋就像是訓(xùn)練輪,在大孩子騎車時應(yīng)該去掉。

不添加任何信息的注釋具有負(fù)價值,因為它們:

  • 增加視覺混亂

  • 讀寫花時間

  • 可能會過時

一個典型的壞示例為:

i = i + 1;         // Add one to i

它不添加任何信息,并切產(chǎn)生維護(hù)成本。

每一行代碼都需要注釋的策略在Reddit上都受到了相當(dāng)?shù)某靶Γ?/p>

// create a for loop // <-- commentfor // start for loop( // round bracket // newlineint // type for declarationi // name for declaration= // assignment operator for declaration0 // start value for i

02

規(guī)則2:好的注釋不能成為代碼不清晰的借口

注釋的另一個誤用是提供本應(yīng)包含在代碼中的信息。一個簡單的例子是,有人用一個字母命名一個變量,然后添加一個描述其用途的注釋:

private static Node getBestChildNode(Node node) {    Node n; // best child node candidate    for (Node node: node.getChildren()) {        // update n if the current state is better        if (n == null || utility(node) > utility(n)) {            n = node;        }    }    return n;}

通過更好的變量命名,可以不需要再做注釋:

private static Node getBestChildNode(Node node) { Node bestNode; for (Node currentNode: node.getChildren()) { if (bestNode == null || utility(currentNode) > utility(bestNode)) { bestNode = currentNode; } } return bestNode;}

正如Kernighan和Plauger在編程風(fēng)格要素一書中所寫,“不要注釋糟糕的代碼 — 重寫它?!?/p>

03

規(guī)則3:如果無法寫出一個清晰的注釋,代碼可能有問題

Unix源代碼中最臭名昭著的注釋是“你不希望理解它”,它出現(xiàn)在一些恐怖的上下文切換代碼之前。Dennis Ritchie后來解釋說這是故意為之:“本意是想表達(dá)'這不會出現(xiàn)在考試中’,而不是作為一種厚顏無恥的挑戰(zhàn)?!辈恍业氖牵Y(jié)果發(fā)現(xiàn)他與合作者Ken Thompson自己也理解不了,后來不得不重寫。

這讓人想起了Kernighan定律:

調(diào)試在一開始就比編寫程序困難一倍。因此,按照定義,如果你的代碼寫得非常巧妙,那么你就沒有足夠的能力來調(diào)試它。

警告讀者遠(yuǎn)離你的代碼就像打開汽車的危險警示燈:承認(rèn)你正在做知法犯法的事情。相反,把代碼重寫成你充分理解的東西,或者更進(jìn)一步,直截了當(dāng)?shù)剡M(jìn)行解釋。

04

規(guī)則4:注釋應(yīng)該消除混亂,而不是引起混亂

如果沒有Steven Levy的 黑客:計算機(jī)革命的英雄 中的這個故事,任何關(guān)于負(fù)面注釋的討論都是不完整的:

[Peter Samson]拒絕在源代碼中添加注釋來解釋他在特定時間所做的事情,使其特別晦澀難懂。在一個分發(fā)良好的程序中,Samson繼續(xù)編寫了數(shù)百條匯編語言指令,其中只有一條包含1750數(shù)字的指令帶有注釋。注釋是RIPJSB,人們絞盡腦汁研究它的含義,直到有人發(fā)現(xiàn)1750年是巴赫去世的那一年,而Samson寫的注釋是Rest In Peace Johann Sebastian Bach(安息吧,約翰·塞巴斯蒂安·巴赫)的縮寫。

雖然我和別人一樣欣賞一個好的黑客,但這種注釋不可效仿。如果你的注釋引起混亂而不是消除混亂,刪除它。

05

規(guī)則5:在注釋中解釋不規(guī)范的代碼

注釋掉其他人可能認(rèn)為不需要或冗余的代碼是個好主意,比如來自App Inventor的代碼(我所有的正面示例均源于此):

final Object value = (new JSONTokener(jsonString)).nextValue();// Note that JSONTokener.nextValue() may return// a value equals() to null.if (value == null || value.equals(null)) {    return null;}

如果沒有注釋,有人可能會“簡化”代碼或?qū)⑵湟暈橐粋€神秘但必不可少的咒語。寫下為什么需要這些代碼,可以節(jié)省未來讀者的時間并解除他們的焦慮。

需要對是否注釋代碼做出判斷。在學(xué)習(xí)Kotlin時,我遇到了Android教程中的代碼:

if (b == true)

我立即想到是否可以用以下代碼取代:

if (b)

就像在Java中一樣。經(jīng)過一點研究,我了解到可以為null的布爾變量會顯式地與true進(jìn)行比較,以避免出現(xiàn)難看的null檢查:

if (b != null && b)

我建議不要為常見的語法添加注釋,除非專門為新手編寫教程。

06

規(guī)則6:提供復(fù)制代碼的原始出處鏈接

如果你像大多數(shù)程序員一樣,有時會使用網(wǎng)上找到的代碼。包含對源代碼的引用,可使將來的讀者能夠獲得完整的上下文,例如:

  • 解決了什么問題

  • 誰提供了代碼

  • 為什么推薦此解決方案

  • 評論者怎么看

  • 是否仍然有效

  • 如何改進(jìn)

例如,考慮此注釋:

/** Converts a Drawable to Bitmap. via https://stackoverflow.com/a/46018816/2219998. */

點開鏈接,給出了以下信息:

  • 代碼的作者是Tomá? Procházka,他在Stack Overflow上排名前3%。

  • 一個評論者提供了一個優(yōu)化,已經(jīng)納入repo資源庫。

  • 另一位評論者提出了一種避免邊緣情況的方法。

將其與下面的注釋對比(稍作修改以防止侵權(quán)):

// Magical formula taken from a stackoverflow post, reputedly related to// human vision perception.return (int) (0.3 * red + 0.59 * green + 0.11 * blue);

任何想要理解這段代碼的人都必須搜索公式。粘貼到URL要比以后查找引用快得多。

有些程序員可能不愿意表明他們自己并沒有編寫代碼,但是重用代碼是一個明智的舉動,它可以節(jié)省時間并讓你獲得更多關(guān)注。當(dāng)然,永遠(yuǎn)不要粘貼不懂的代碼。

人們從Stack Overflow的問題和答案中復(fù)制大量代碼。這些代碼要求歸屬于知識共享許可下。引用注釋滿足該要求。

同樣,你應(yīng)該引用一些有用的教程以便再次找到它們,并且感謝它們的作者:

// Many thanks to Chris Veness at http://www.movable-type.co.uk/scripts/latlong.html// for a great reference and examples.

07

規(guī)則7:在可能提供幫助的地方引入指向外部參考的鏈接

當(dāng)然,并非所有引用都指向Stack Overflow??紤]:

// http://tools.ietf.org/html/rfc4180 suggests that CSV lines// should be terminated by CRLF, hence the \r\n.csvStringBuilder.append('\r\n');

到標(biāo)準(zhǔn)或其它文檔的鏈接可以幫助讀者理解代碼正在解決的問題。雖然這些信息可能出現(xiàn)在設(shè)計文檔中的某個地方,但一個適當(dāng)位置的注釋會在最需要它的時間和地方為讀者提供標(biāo)識。本例中,點開鏈接可以看到RFC 4180已經(jīng)由RFC 7111更新了有用的信息。

08

規(guī)則8:在修復(fù)bug時添加注釋

不僅應(yīng)該在最初編寫代碼時添加注釋,修改代碼時,特別是修復(fù)bug時,也應(yīng)該添加??聪旅孢@個注釋:

  // NOTE: At least in Firefox 2, if the user drags outside of the browser window,  // mouse-move (and even mouse-down) events will not be received until  // the user drags back inside the window. A workaround for this issue  // exists in the implementation for onMouseLeave().  @Override  public void onMouseMove(Widget sender, int x, int y) { .. }

注釋不僅有助于讀者理解當(dāng)前方法和引用方法中的代碼,而且有助于確定是否仍然需要這些代碼以及如何測試它們。

注釋還可以幫助參考問題跟蹤程序:

// Use the name as the title if the properties did not include one (issue #1425)

雖然 git blame 可以用來查找添加或修改行的提交,但提交消息往往很簡短,最重要的更改(例如,修復(fù)問題#1425)可能不是最近提交(例如,將方法從一個文件移動到另一個文件)的一部分。

09

規(guī)則9:使用注釋來標(biāo)記未完成的實現(xiàn)

即使代碼中有已知的限制,有時還是有必要檢查它。雖然不分享代碼中已知的缺陷很有誘惑力,但最好將這些明確化,例如使用TODO注釋:

// TODO(hal): We are making the decimal separator be a period,// regardless of the locale of the phone. We need to think about// how to allow comma as decimal separator, which will require// updating number parsing and other places that transform numbers// to strings, such as FormatAsDecimal

對此類注釋使用標(biāo)準(zhǔn)格式有助于衡量和解決技術(shù)負(fù)債問題。更好的辦法是,在跟蹤系統(tǒng)中添加一個問題,并在注釋中引用該問題。

10

總結(jié)

我希望上面的例子已經(jīng)表明,注釋不能成為差代碼的借口或修復(fù)差代碼;它們通過提供不同類型的信息來補(bǔ)充好的代碼。正如Stack Overflow聯(lián)合創(chuàng)始人Jeff Atwood所寫,“代碼告訴你怎么做,注釋告訴你為什么?!?/p>

遵守這些規(guī)則可以節(jié)省你及其隊友的時間,減少挫折感。

即便如此,我確信這些規(guī)則并不是詳盡無遺的,并期待著在評論中看到補(bǔ)充建議。

參考資料:

  • https://www.reddit.com/r/ProgrammerHumor/comments/8w54mx/code_comments_be_like/

  • https://www.reddit.com/r/ProgrammerHumor/comments/bz35nh/whats_a_comment/

  • https://geekandpoke.typepad.com/geekandpoke/2011/06/code-commenting-made-easy.html

  • https://geekandpoke.typepad.com/geekandpoke/2008/07/good-comments.html

  • https://www.commitstrip.com/en/2016/09/01/keep-it-simple-stupid/?

  • https://www.commitstrip.com/en/2013/07/22/commentaire-de-commit/?

  • https://geekandpoke.typepad.com/geekandpoke/2009/07/

  • https://geekandpoke.typepad.com/geekandpoke/2010/11/architecture.html

原文鏈接:https://stackoverflow.blog/2021/07/05/best-practices-for-writing-code-comments/

聲明:本文由CSDN翻譯,轉(zhuǎn)載請注明來源。 

-End-

最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
代碼質(zhì)量隨想錄(一):可讀是王道
第二章 代碼注釋
Javascript[0x06] -- 基于Javascript范疇代碼風(fēng)格和規(guī)范的總結(jié)
sentinel 基本概念
基于 abapGit 和 abaplint 的 ABAP 持續(xù)集成的一個例子
自定義 ESLint 規(guī)則,讓代碼持續(xù)美麗
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服