软件命名随处可见,包括变量,函数,参数,类和包的命名,以下为“取个好名字”的几条简单规则:
1、名副其实:
变量,函数或者类的名称已经答复了所有的大问题,它该告诉你,它为什么存在,它做什么事,应该怎么用。如果名称8注释来补充,那就不算是名副其实。
举例一:
----------------------------------------不规范的代码------------------------------------------
int d;//消逝的时间,以日计(名称d什么也没有说明,没有引起时间消逝的感觉,更别说以日计。)
---------------------------------------规范的代码----------------------------------------------
int elapsedTimeDays;//这些名称更能让程序员易于理解和修改代码
int daysSinceCreation;
int daysSinceModification;
int fileAgeDays;
举例二:
----------------------------------------不规范的代码-------------------------------------------
/**list是什么类型的东西?list零下标项的意义是什么?4的意义是什么?怎样使用返回的list?**/
public List<int[]> getThem(){
List<int[])> list1 = new ArrayList<int[]>();
for (int[] x : list) {
if(x[0] == 4) {
list1.add(x);
}
}
}
---------------------------------------规范的代码----------------------------------------------
/**只要简单改一下名字,就轻易地知道发生了什么,这就是选用好名称的力量**/
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<Cell>();
for (int cell : gameBoard) {
if(cell[STATE_VALUE]=FLAGGED) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
---------------------------------------规范的代码----------------------------------------------
/**更进一步,不用int数组表示,而是用类来表示**/
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard) {
if(cell.isFlagged()) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
2、避免误导
1)必须避免留下掩藏代码本意的错误线索。应当避免使用与本意相悖的词。
如:别用accountList来指称一组帐号,除非它真的是List类型,即便它就是个List,最好也别在名称中写出容器类型名。可以用accountGroup,bunchOfAccounts,甚至直接用accounts都会好些。
2)防止使用相似的名称。
如:想区分模块中某处的XYZActionForEfficientHandingOfSettings和XYZActionForEfficientStorageOfStrings,容易区分吗?是不是要瞪大眼睛去看?
3、做有意义的区分
不要说废话,废话都是冗余,废话就是一种没有意义的区分。譬如:
1)Variable一次永远不应当出现在变量中,Table一次永远不应当出现在表明中。
2)NameString会比Name好吗?难道Name会是一个float不成?如果是这样,就触犯了关于误导的规则。假如有个名为Customer的类,还有一个名为CustomerObject的类,区别何在呢?哪一个是表示“客户”的最佳途径呢?(名称虽然不能,意思却无区别)。
举例一:
----------------------------------------不规范的代码------------------------------------------------
public static void copyChars(char a1[], char a2[]){
for ( int i=0; i<a1.length; i++){
a2[i] = a1[i];
}
}
//如果参数名改为source和destination,这个函数会像样得多
举例二:
----------------------------------------不规范的代码------------------------------------------------
getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();
// 程序员怎么能知道该调用哪个函数呢?
// 总之:如果没有明确的规定,accountInfo,accountData和account就没区别,要区分名称,就要以读者能鉴别不同之处的方式来区分
4、使用读得出来的名称
如果名称读不出来,讨论的时候就像个傻鸟。不要自造傻乎乎的自造词,而非恰当的英文词。
举例:
----------------------------------------不规范的代码-------------------------------------------
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint=”102”;
/*………..*/
}
---------------------------------------规范的代码---------------------------------------------
class Customer {
private Date generationTimestamp;
private Date modificationTimestamp;
private final String recordId=”102”;
/*………..*/
}
5、使用可搜索的名称
单字母名称变量或者数字常量,很难在一大段代码中搜索出来。单字母名称仅仅用于短方法中的本地变量,名称长短应与其作用于大小相应。若变量或常量在代码中多处使用时,应赋其以便于搜索的名称。
举例:
----------------------------------------不规范的代码------------------------------------------------
for(int j=0;i<34;j++) {
s+=(t[j] * 4) / 5;
}
---------------------------------------规范的代码---------------------------------------------
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK =5;
int sum = 0;
for ( int j=0;j<NUMBER_OF_TASKS;l j++) {
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK );
sum += realTaskWeeks;
}
6、避免使用编码
1) 不要使用类型标记法:Java语言不需要类型编码,对象是强类型的,Eclipse可以在编译开始前就侦测到类型错误,所以类型编码纯属多余,反而增加了修改变量、函数或类的名称或者类型的难度,增加了阅读代码的难度,同时制造了让编码系统误导读者的可能性。
举例:
----------------------------------------不规范的代码------------------------------------------------
PhoneNumner phoneString; //类型变化时,名称不变化!
2)不要用前缀来标明成员变量:代码读得越多,最终就会严重无前缀,前缀就成了不入法眼的废料,旧代码的标志。
举例:
----------------------------------------不规范的代码-----------------------------------------------
public class Part {
private String m_dsc;// The textual description
void setName(String name){
m_dsc = name;
}
}
---------------------------------------规范的代码----------------------------------------------
public class Part {
String description;
void setDescription(String description) {
this.description = description;
}
}
7、避免思维映射
不要让读你代码的人在脑中把你的名称翻译为他们熟知的名称,程序员通常都是聪明人,聪明人有时会接脑筋急转弯炫耀其聪明。假如你记得r代表代表不包含host和schema的url的话,你真是太聪明了。总而言之,明确就是王道。
8、类名
类名和对象名应该是名词或名词短语,如Customer、Account和AddressParser,避免使用Manager、Processor、Data或者Info这样的类名。类名不应当是动词。
9、方法名
1)方法名应当是动词或动词短语,如postPayment、deletePage或save。
2)属性访问器,修改器应该根据其值命名,并依据JavaBean标准加上get、set和is前缀。
3)重载构造器时,使用描述了参数的静态工厂方法名通常好于直接用构造器。例如:
Complex fulcrumPoint = Complex.fromRealNumber(23.0);
Complex fulcrumPoint = new Complex(23.0);
可以考虑将相应的构造器设置为private,强制使用这种命名手段。
10、别卖萌
如果名称太萌了,那就只有同代码编写者一般有幽默感的才记得住,而且还是他们记得那个笑话的时候才行。宁可明确,毋为好玩。言到意到,意到言到。例如:别用gotoHell()来表示kill()方法。
11、每个概念对应一个词
给每个抽象概念选一个词,并且一以贯之。例如,使用get、fetch和retrieve来给多个类中的同名方法命名。怎么记得住那个类中是哪个方法呢?函数名称应当独一无二,而且要保持一致,对于那些会用到你代码的程序员,一以贯之的命名法简直就是太幸运了。
12、别用双关次
同一术语用于不同概念,基本上就是双关语了。避免将同一单词用于不同目的。比如,在多个类中都有add方法,该方法通过增加或者连接两个现存值来获得新值。假设要写个新类,该类中有一个方法,把单个参数放到Collection中,该把整个方法叫做add吗?这样做貌似和其他add方法保持一致,但实际上语义却不同,应该用insert或append之类的次来命名才对。把该方法命名为add,就是双关语了。
Codders应尽力写出易于理解的代码。尽力把代码写得让别人能一目尽览,而不必殚精竭虑地去研究。
13、使用解决方案领域名称
只有程序员才会读你的代码。所以,尽管用计算机科学方面的术语,算法名,模式名,数学术语吧。程序员要做太多技术性工作,给这些事取个技术性的名称,通常是最靠谱的做法。有哪个程序员不知道JobQueue的意思呢。
14、使用源自业务领域的名称
如果不能用熟悉的CS(Computer Science)术语来给手头工作命名,就采用业务领域的名称。至少,负责维护代码的程序员可以请教做业务的。与业务领域更为贴近的代码,应当采用源自业务领域的名称。
15、添加有意义的语境,不要添加无用的语境
只要段名称足够清楚,就要比长名称好。别给名称添加不必要的语境。例如,对于Address类的实体来说,AccountAddress和CustomerAddress都是不错的名称,不过用在类名上就不太好了,Address是个好类名。如果需要与MAC地址,端口地址和WEB地址相区分,可考虑使用PostalAddress、MAC和URL。这样的名称更为精确,而精确正式命名的要点。