OO编程基本功(3) 注释
1. 避免依赖注释来逃避重构
注释在code中可以使得代码更容易理解,可是相当多的情况下,它会使得程序员过于“依赖”注释而容许代码的自我说明程度降低。
需要注释?是否代码名称不够清晰,或者代码的抽象层次混乱,还是代码的动机不够明确导致需要注释来做额外说明?合格的代码本身一般是不需要额外注释的。
例如:
//newPasswordMUST at least 6 digits
User.Password= newPassword ;
可以重构为:
privateconst string PASSWORD_MIN_LENGTH = 6;
publicvoid ChangePassword(string newPassword){
Assert.IsTrue(newPassword.Length>= PASSWORD_MIN_LENGTH );
User.Password= newPassword;
}
再如:
//Employeeis eligible to retire
if(Employee.Age> 65 && Employee.Payed){
...
}
重构为:
if(Employee.EligibleToRetire){
}
privatebool EligibletoRetire{
get{
returnthis.Age > 65 && this.Payed;
}
}
什么时候使用注释
既然重构是使得code更加清晰的主要手段,那么什么时候使用注释?
1. 公司版权的说明
// Copyright (C) 2003,2004,2005 by XXX. All rightsreserved.
2. sample
var date = new Date("dd-MM-yyyy"); // sample: 10-11-2014
3.一些必要的注解说明
例如
if(...){
return 0 ;
}
return 1 ; // 1: eligible 2 :non-eligible
再如在单元测试中,测试性能
for(var i = 0;i < 1000/*并发一千个线程来模拟高并发情况*/; i++){
}
再如,还是多线程情况(提醒共享资源环境下,别忘了对多线程访问的考虑):
//do not forget take care of multi-thread scenarios
var resource = new ShareResource();
4.TODO
例如:
User.Login();
//TODO : finish order logic
不必要的注释
1. 以注释来逃避代码不完善的理由
try {
LoadFiles();
}
Catch(IOException exp){
//Do nothing
}
如果swallow这个异常,那么为什么要捕捉这个异常?更没有必要用一个注释来作为什么都不做的理由。
2. 啰嗦的注释
//1.Student Age > 6
//2.Region is valid
public void IsEligible(Student student){
...
}
注释完全没有必要把代码的实现逻辑写在函数头。可以用注释来引导自己去写代码的实现,但是实现之后建议及时清理掉以免代码逻辑修改后造成与代码不同步形成误导。毕竟,代码是唯一不会说谎的。(软件UI,文档,注释都会“说谎”)
3. 没必要为每个property , member都写一个说明
/**
* The Manager implementation with which this Containeris
* associated.
*/
protected Manager manager = null;
/**
* The cluster with which this Container is associated.
*/
protected Cluster cluster = null;
/**
* The human-readable name of this Container.
*/
protected String name = null;
显然,如果为每个字段,属性,方法都写注释,看上去很统一,却严重影响了代码的可读性。代码本身应该具备自我解释的能力,如果发现需要注释来弥补,则应考虑重构。
4. 不必要的日志注释
例如:
* Changes (from 11-Oct-2001)
* --------------------------* 11-Oct-2001 :Re-organised the class and moved it to new package
* com.jrefinery.date (DG);
* 05-Nov-2001 : Added a getDescription() method, andeliminated NotableDate
* class (DG);
* 12-Nov-2001 : IBD requires setDescription() method,now that NotableDate
* class is gone (DG); Changed getPreviousDayOfWeek(),
* getFollowingDayOfWeek() and getNearestDayOfWeek() tocorrect
* bugs (DG);
* 05-Dec-2001 : Fixed bug in SpreadsheetDate class(DG);
* 29-May-2002 : Moved the month constants into aseparate interface
* (MonthConstants) (DG);
* 27-Aug-2002 : Fixed bug in addMonths() method,thanks to N???levka Petr (DG);
* 03-Oct-2002 : Fixed errors reported by Checkstyle(DG);
* 13-Mar-2003 : Implemented Serializable (DG);
* 29-May-2003 : Fixed bug in addMonths method (DG);
* 04-Sep-2003 : Implemented Comparable. Updated theisInRange javadocs (DG);
* 05-Jan-2005 : Fixed bug in addYears() method(1096282) (DG);
这种注释看上去好像很整齐,当前好多公司都在follow,其实完全没有必要,因为source control已经为我们做了同样的事情,这种注释只会降低代码的可读性,长时间以后提供的信息也完全没有人会去看。
5. 噪音注释需要屏蔽
/**
* Default constructor.
*/
protected Student() {
}
谁不知道这是默认构造函数呢?
再如:
/**
* Returns the day of the month.
*
* @return the day of the month.
*/
public int getDayOfMonth() {
return dayOfMonth;
}
这样的注释如果是一种规范,那么完全没有必要和意义。
6. 避免署名注释
//added by Richard
和日志注释一样没有必要,source control 工具已经为我们做了同样的事情。
7. 避免“暂时注释掉”的代码
InputStreamResponse response = newInputStreamResponse();
response.setBody(formatter.getResultStream(),formatter.getByteCount());
// InputStream resultsStream =formatter.getResultStream();
// StreamReader reader = newStreamReader(resultsStream);
//response.setContent(reader.read(formatter.getByteCount()));
往往由于“不舍得”删而暂时放在那里,以后可能会用到?果断拿掉吧,sourcecontrol 会帮你存好的,为了其它coder阅读起来舒服,避免造成误导。