曾經我對“一份好的代碼裡注釋至少要占到一半的份量”這樣話深信不疑,我也不厭其煩的給每一個函數都加上javadoc,對此,我深感自豪;而對于别人寫代碼不加注釋的“壞習慣”,我深表遺憾。然而當我讀完Robert的“注釋”一節,我已經懊惱不已,并且我已經開始對我的代碼進行稽核,再次優化。我已經開始遵守“别給糟糕的代碼加注釋–重新寫吧”這條準則。
也許你是一個好人,會對代碼進行不斷的優化改進,然而你經常會把注釋忽略掉,就如同下面這樣:
/**
* 集合競價.
*
* @param orderFromClient
* @return
*/
private Message callAuction(SelfOrder orderFromClient, long b, JadeInfo jadeInfo) {
方法參數已經改變了,然而javadoc的注釋中依然隻有一個參數。
我個人已經深深地被Robert影響了,代碼才能最忠誠的告訴它在做什麼,而不是注釋。但是我們很多人,包括在看這本書之前的我,認為寫得一手好注釋的程式員才是好程式員,當然這不包含那些隻會寫糟糕代碼的人。
用代碼來闡述
我們來比較一下這兩種代碼:
public void pause() {
if (isNotAction()) {
return;
}
}
/**
* 節假日或當天無交易商品,伺服器不執行操作
*/
private boolean isNotAction() {
if (isHoliday || !hasTradingJade) {
return true;
}
return false;
}
public void pause() {
// 節假日或當天無交易商品,伺服器不執行操作
if (isHoliday || !hasTradingJade) {
return ;
}
}
我認為第一種更好,因為節假日以及無交易商品,就說明伺服器當日不需要運作,那麼用isNotAction來表明會更好。
好注釋
對意圖進行解釋
/*
* 按照使用者id對資金變化量進行排序,進而保證在多線程同時更新資金字段時,不發生死鎖
*/
@Override
public int compareTo(VarialMoneyUser o) {
return this.getUid().compareTo(o.getUid());
}
這樣的注釋,我認為還不錯,說明了使用compare的意圖。
TODO注釋
有的時候,我們的需要做一些事情,而我們暫時沒有做,那麼就可以使用TODO,這樣IDE就會管理到這些TODO,當然還有FIXME标記,表明我們有些問題暫時不知道怎麼優化、改善。
trade.setDjzj(BigDecimal.valueOf(0));// FIXME 當機資金待實作
// TODO 計算賬戶的盈虧,根據風險控制等級,标示次日需要提醒、限制交易、強制平倉的賬戶
但是需要注意,定期的回頭檢查,eclipse提供以下圖檔的功能,你要删除那些無用的TODO
壞注釋
喃喃自語
public void dailyUpdateSystemData() {
// 每日更新時進行一次會員資訊更新
AllMembercoes.init();
以上的注釋毫無必要。
多餘的注釋
/**
* @Description: 擷取指定日期的行情日報
*/
public QuotationDailyReport getQuotationReportByDateAndScode(QuotationDailyReport report);
/**
* @Title: addQuotationReport
* @Description: 添加行情日報
* @param tradeReport
* @return
*/
public int addQuotationReport(QuotationDailyReport tradeReport);
/**
* @Title: getLastQuotationReport
* @Description: 擷取指定商品上一次的行情日報資訊
* @param map
* @return
*/
@SuppressWarnings("rawtypes")
public QuotationDailyReport getLastQuotationReport(Map map);
這些注釋比沒有注釋還可怕,其實看方法名稱,都知道要做什麼,加上注釋後反倒浪費時間。
ps:我之前非常喜歡加這種注釋,我恨不得在每一個方法上面加上注釋,但是自從我明白了,方法名本身就應該代表了方法要做什麼以後,我深惡痛絕自己以前荒唐的行為。
誤導性注釋
這個非常的可怕,很多時候,注釋和代碼表達的意思完全相反,或者牛頭不對馬嘴,總之很容易讓人迷惑。
// 12點後設定isreload為true,重新加載配置,
private void updateReloadStatusTrue() {
這個注釋在本意上應該是非常友好的,提示這個方法是在12點以後執行的,但是我上下文翻看,壓根找不到任何12點的資訊。
這樣會好一點
/**
* 設定isreload為true,表明配置服務、商品服務可以重新加載了
*/
private void updateReloadStatusTrue() {
reload = true;
ConfigService.isReload = reload;
JadeInfoService.isReload = reload;
}
循規蹈矩的注釋
哦,這種注釋多發生在方法上,我曾經就非常熱衷于這樣的注釋,現在我才知道其可怕之處。
/**
* @Title: updateQuotation
* @Description: 修改指定商品的行情資訊
* @param quotation
*/
public void updateQuotation(Quotation quotation) {
this.quotationMapper.updateQuotation(quotation);
}
title、param的注釋有兩種壞處
非常多餘,難道方法本身不能告訴我嗎?
阻礙重構,當方法名、參數名需要重構或者添加參數時注釋是不會緊随變更的。
日志式注釋
以前我們特别喜歡在代碼裡加上以下這樣注釋
// start update by maweiqing
// 如果能夠接收到消息,說明用戶端已經進行操作了,那麼就更新session的時間
data = CryptUtil.encrypt(data, SessionManager.getSession(getSession().getSessionId())
.getEncryptKey());
// end update by maweiqing 2015-05-27
看到Robert的建議後,我真的才恍然大悟,這樣的代碼還要SVN的代碼管理器幹嘛?SVN在送出的時候自然會讓你輸入你的修改理由、以及自動顯示署名、日期的。
廢話注釋
// 辨別列
private Integer id;
// 使用者id
private Integer userId;
// 使用者名
private String userName;
這樣的注釋完全沒有必要,你認為有嗎?
/**
* @return the id
*/
public Integer getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(Integer id) {
this.id = id;
}
還有利用IDE生成的這種bean注釋,我真後悔自己當初為什麼會這樣想,加上這樣的注釋讓自己顯得專業嗎,顯然适得其反。
位置标記
雖然我暫時沒有在自己的代碼中找到,但是之前我這樣做過。
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//aaaaaaaaaaaaaaaaaaaa
注釋掉的代碼
哦,顯然我又中招了,之前我特别喜歡把那些所謂還有作用的代碼留在代碼裡,及時壓根就是錯誤的。但是自從我看到Jeff的部落格後,我就開始删掉了那些注釋掉的代碼,今天再看到Robert的文章,感覺這些偉大的程式員他們都會有這樣相似的真理。
如果你的代碼中還有這樣的注釋,請盡快删掉吧,危害太大。
總結:我覺得Robert的文章越來越深入的影響着我,讓我改變了很多陋習。