這篇文章是由José M. Aguilar在他卓越的博客中以西班牙語的形式首發(fā),其后Timm Martin在獲得Aguilar先生的授權(quán)下,對該文章進(jìn)行翻譯、修改,并且在DevTopics上發(fā)布。
以下13個(gè)小技巧可以使得你的代碼在長時(shí)間內(nèi)依然能夠保持容易理解和維護(hù)。
1. 對不同級別的代碼進(jìn)行注釋
對于不同級別的代碼塊,要使用統(tǒng)一的方法來進(jìn)行注釋。例如:
* 對于每一個(gè)類,需要包含一段簡明扼要的描述,作者和上一次修改的時(shí)間
* 對于每一個(gè)方法,需要包含這個(gè)方法的用途,功能,參數(shù)以及返回結(jié)果
當(dāng)你在一個(gè)團(tuán)隊(duì)里面的時(shí)候,采用一套注釋的標(biāo)準(zhǔn)是非常重要的。當(dāng)然,使用一種大家都認(rèn)可的注釋約定和工具(例如C#的XML注釋和Java的Javadoc)在一定程度上能推動這項(xiàng)任務(wù)。
2. 使用段落注釋
首先把代碼塊分解成多個(gè)“段落”,每一個(gè)段落都執(zhí)行單一的任務(wù);然后在每一個(gè)“段落”開始之前添加注釋,告訴閱讀代碼的人接下來的這段代碼是干什么用的
// 檢查所有記錄都是正確的
foreach (Record record in records)
{
if (rec.checkStatus()==Status.OK)
{
. . .
}
}
// 現(xiàn)在開始進(jìn)行處理
Context ctx = new ApplicationContext();
ctx.BeginTransaction();
. . .
3. 對齊注釋行
對于那些在行末寫有注釋的代碼,應(yīng)該對齊注釋行來使得方便閱讀
const MAX_ITEMS = 10; // maximum number of packets
const MASK = 0x1F; // mask bit TCP
有些開發(fā)人員使用tab來對齊注釋,而另外一些人會用空格來對齊。由于tab在不同的編輯器和集成開發(fā)環(huán)境中會有所不同,所以最佳的方法是使用空格來對齊注釋行。
4. 不要侮辱閱讀者的智慧
要避免沒用的注釋,例如
if (a == 5) //如果a等于5
counter = 0 //把counte設(shè)為0
這不單把時(shí)間浪費(fèi)在寫沒用的注釋上面,同時(shí)也在分散讀者的注意力。
5. 要有禮貌
應(yīng)當(dāng)避免沒有禮貌的注釋,例如“要注意一些愚蠢的用戶會輸入一個(gè)負(fù)數(shù)”,或者“修正由菜鳥工程師寫的愚蠢得可憐的代碼而導(dǎo)致的副作用”。這樣的注釋對于代碼的寫注釋的人來說并沒有任何好處,同時(shí)你永遠(yuǎn)都不會知道將來這些注釋會被誰來閱讀,你的老板,一個(gè)客戶或者是剛才被你數(shù)落的愚蠢得可憐的工程師。
6. 直截了當(dāng)
不要在注釋里面寫過多的廢話。避免在注釋里面賣弄ASCII藝術(shù),寫笑話,作詩和過于冗長。簡而言之就是保持注釋的簡單和直接。
7. 使用統(tǒng)一的風(fēng)格
有些人覺得注釋應(yīng)該讓非程序員也能看懂。另外一些人覺得注釋需要面對的讀者只是程序員。無論如何,正如Successful Strategies for Commenting Code中所說的,最重要的是注釋的風(fēng)格需要統(tǒng)一,并且總是面向相同的讀者。就自己而論,我懷疑非程序員是否會去讀代碼,所以我覺得注釋應(yīng)該面向程序員來寫。
8. 在內(nèi)部使用特殊的標(biāo)簽
當(dāng)你在一個(gè)團(tuán)隊(duì)里工作的時(shí)候,采用一組一致的標(biāo)簽?zāi)軒椭煌某绦騿T溝通。例如,很多團(tuán)隊(duì)會采用“TODO”標(biāo)簽來表示一段尚未完成的代碼
int Estimate(int x, int y)
{
// TODO: implement the calculations
return 0;
}
標(biāo)簽注釋并不會解釋代碼,它們尋求注意或者是傳遞信息。但是如果適當(dāng)?shù)厥褂眠@種技術(shù),要記住跟進(jìn)這段代碼并且完成該標(biāo)簽傳遞的任務(wù)。
9. 在寫代碼的同時(shí)添加注釋
當(dāng)你在寫代碼而且記憶猶新的同時(shí)就添加注釋。如果等到項(xiàng)目后期才添加注釋,會讓你事倍功半。“我沒有時(shí)間寫注釋”,“我的時(shí)間很緊迫”和“項(xiàng)目已經(jīng)延遲了”,這些都是不寫注釋的常見借口。有些工程師覺最佳的解決方法是“注釋先行”。例如:
public void ProcessOrder()
{
// Make sure the products are available
// Check that the customer is valid
// Send the order to the store
// Generate bill
}
10. 把自己想象為注釋的讀者(事實(shí)上就是如此)
當(dāng)你正在給代碼寫注釋的時(shí)候,不僅僅為日后維護(hù)你的代碼的開發(fā)者考慮,同時(shí)也設(shè)想一下如果自己就是注釋的讀者。Phil Haack曾經(jīng)說過:
“一旦一行代碼被敲到文件中, 你就已經(jīng)要開始維護(hù)那一行代碼了!
所以,我們自己就是好(或者壞)注釋的第一個(gè)受益者(或者受害者)。
11. 更新代碼的時(shí)候要更新注釋
如果注釋沒有隨著代碼的修改而更新,那么這些注釋將是毫無意義的。代碼和注釋需要同步,否則注釋只會讓維護(hù)代碼的開發(fā)者更加痛苦。需要特別注意的是,一些重構(gòu)的工具會自動更新代碼,但是卻沒有自動更新注釋,那么注釋就自然而然地過期作廢了。
12. 良好可讀性代碼是注釋的金科玉律
對于很多開發(fā)者來說,一個(gè)基本的原則就是:讓代碼自己描述自己。雖然有人懷疑這是由不喜歡寫注釋的程序員所倡導(dǎo)的一場運(yùn)動,但是無需解釋的代碼有很大的好處,這些代碼更加容易理解甚至讓注釋變得沒有必要。例如,在我的文章Fluid Interfaces中就給大家展示了什么是清晰的無需解釋的代碼。
Calculator calc = new Calculator();
calc.Set(0);
calc.Add(10);
calc.Multiply(2);
calc.Subtract(4);
Console.WriteLine( “Result: {0}”, calc.Get() );
在這個(gè)例子里面,注釋就像是違反了第4條技巧那樣,變得毫無必要。要寫出可讀性好的代碼,你需要使用適當(dāng)?shù)拿绞剑ㄔ诮?jīng)典的Ottinger’s Rules中有闡述),保證恰當(dāng)?shù)目s進(jìn),并且采用編碼風(fēng)格指導(dǎo)。如果代碼不遵守這條技巧,那么注釋看起來就好像是為自己不好的代碼的寫道歉信一樣。
13. 跟你的同事分享這些技巧
雖然從第10條技巧中我們已經(jīng)知道了自己就是好注釋的得益者,但是這些技巧對于所有的開發(fā)者來說都是很有幫助的,尤其是整個(gè)團(tuán)隊(duì)都有相同共識的情況下。因此,大方地跟你的同事去分享這些技巧,讓我們寫出更加容易理解和維護(hù)的代碼。