代碼是靈魂,注釋是心聲
在以前一些關(guān)于代碼注釋的文章中,我發(fā)現(xiàn),你不需要的注釋才是***的注釋。不要急著批判,請允許我闡述一下。首先代碼應(yīng)該盡量地簡潔,盡可能地做到不需要依賴注釋就可以理解。只有那些真的沒法更易于理解的代碼,才需要我們添加注釋。
有一本非常經(jīng)典的書叫《Structure and Interpretation of Computer Programs》(《電腦程序的結(jié)構(gòu)和編譯》),最初發(fā)表于1985年,在序言中就表明其觀點:
程序必須能便于我們閱讀,讓機(jī)器執(zhí)行只是附帶的。
Knuth也在他1984年發(fā)表的經(jīng)典論文《Literate Programming》(《文學(xué)編程》)中秉持了類似的觀點:
我們應(yīng)該轉(zhuǎn)變傳統(tǒng)的思維,程序不再是告訴計算機(jī)做什么的指令,而是向人類描述如何讓計算機(jī)做事情的文字,編程像寫文章一樣。
文學(xué)編程關(guān)注的主要是展現(xiàn)精致的風(fēng)格。程序員應(yīng)該像作家一樣,認(rèn)真地選擇變量名,并解釋每個變量的意思,努力寫出易于人腦理解的程序。
如果你寫出來的代碼,既能被其他程序員理解又能成功編譯,那么需要添加注釋的地方肯定就不會很多。關(guān)于使用注釋作為輔助工具,下面就是一個頗具代表意義的例子:
這段代碼取自一個已經(jīng)使用多年、閉源了的系統(tǒng)。
- float _x = abs(x - deviceInfo->position.x) / scale;
- int directionCode;
- if (0 < _x & x != deviceInfo->position.x) {
- if (0 > x - deviceInfo->position.x) {
- directionCode = 0x04 /*left*/;
- } else if (0 < x - deviceInfo->position.x) {
- directionCode = 0x02 /*right*/;
- }
- }
上面的代碼等同于下面的代碼,但是下面的代碼可讀性更高。
- static const int DIRECTIONCODE_RIGHT = 0x02;
- static const int DIRECTIONCODE_LEFT = 0x04;
- static const int DIRECTIONCODE_NONE = 0x00;
- int oldX = deviceInfo->position.x;
- int directionCode = (x > oldX) ? DIRECTIONCODE_RIGHT : (x > oldX) ? DIRECTIONCODE_LEFT : DIRECTIONCODE_NONE;
需要注意的是,注釋的越多并不意味著代碼的理解性更強(qiáng)。當(dāng)然在本案例中并沒有涉及到這一點。上面的注釋——如果你注意到的話——使得代碼更加顯得凌亂不堪。有時候,注釋得越精簡代碼的可讀性才越高。特別是在你必須更換使用其他符號名的情況下。
雖然我們能無限次地重構(gòu)和精簡代碼以避免寫繁冗的注釋,但是表述自己的思考過程的方式卻是有局限性的。
無論***你呈現(xiàn)的代碼是有多么的簡潔和清楚,代碼也不可能完全自文檔化。但是代碼永遠(yuǎn)也不可能取締注釋的存在。正如Jef Raskin所說:
[代碼]無法解釋如此寫程序以及選擇該方法的原因。從[代碼]上我們也看不出選擇某些替代方法的理由。例如:
- /* A binary search turned out to be slower than the Boyer-Moore algorithm for the data sets of interest, thus we have used the more complex, but faster method even though this problem does not at first seem amenable to a string search technique. */
在A開發(fā)人員看來完全顯而易見的東西,可能在B眼里完全就像霧里看花一樣。所以我們在寫注釋的時候,也要考慮到這一點:
下面這個可能你一清二楚
- $string = join('',reverse(split('',$string)));
反轉(zhuǎn)字符串,但是要如何才能插入到
- # Reverse the string
Perl文件中呢?
的確,這一點都不難。歸根究底,代碼只會告訴你程序是如何工作的,但是注釋則能說明工作的原因。所以,下次你寫代碼的時候,不妨在這兩個方面給你的同事做個榜樣。
英文原文:Code Tells You How, Comments Tell You Why