大家都知道,在软件开发这条路上,代码写好不好懂非常重要。代码可读性不只是让现在的开发团队协作更顺溜,对以后软件的维护和升级也有很大影响。可以说,把代码可读性弄好,那就是朝着优质代码的方向迈出了关键一步。
下面,我们可以从下面几个方面提高代码的可读性。
名副其实
糟糕的代码
publlic List<int[]> getThem(){
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
上面的代码过于模糊,导致难以理解和修改。
好的代码
publlic List<Cell> getFlaggedCells(){
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
避免误导
提防使用不同之处较小的名称。例如区分XYZControllerForEfficientHandingOfStrings和XYZControllerForEfficientStorageOfStrings需要花很长时间。
做有意义的区分
糟糕的代码
public static void copyChars(char a1[], char a2[]) {
for (int i=0; i< a1.length; i++) {
a2[i] = a1[i];
}
}
这段代码只是对编译器有意义,但代码的阅读者来说会制造麻烦。
好的代码
public static void copyChars(char[] source, char[] destination) {
for (int i=0; i< source.length; i++) {
destination[i] = source[i];
}
}
使用读得出来的名称
如果名称读不出来,讨论的时候就会像个傻鸟。“哎,这个,鼻涕阿三喜摁踢( bee cee arr three cee enn tee)”
糟糕的代码
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";
}
使用可搜索的名称
在阅读代码的时候,会在不同类、函数、参数之间跳转。使用可搜索的名称,可以加快搜索的速度和准确性。
糟糕的代码
for (int j=0; j <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; j++) {
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}
使用描述性的名称
长而具有描述性的名称,要比短而令人费解的名称好。长而具有描述性的名称,要比描述性的注释好。例如从testAbleHtml改为SetupTeardownIncluder.rederer,因为这个函数名较好的描述了函数做的事情。在比如isTestable改为includeSetupAndTeardownPages。
命名方式要保持一致,使用与模块名一致的短语、名词和动词进行命名。例如不要既用userDetail和userInfo表示用户的详细信息。
避免使用编码
静态语言Java不需要类型编码。对象是强类型的,编译器会检测类型错误。
建议不要在接口名称前加大写字母I。可以在接口实现类后面加Impl。
避免思维映射
不应该让阅读者在脑中把你的名称翻译为他们熟知的名称。这种问题经常出现在选择使用问题领域术语还是解决方案领域术语。也会出现在名词从中文翻译为英文的情况。
明确是王道。
类名用名词
方法用动词
每个概念对应一个词
避免双关语
避免同一个单词用于不同目的。
使用解决方案领域名称
只有程序员才会读你的代码。
使用有意义的语境
设想你有名为firstName、lastName、street、houseNumber、city、state和zipcode的变量。如果它们在一块,很明确是构成一个地址。如果在某个方法中只有一个state变量,则无法推断这是地址的一部分。这时可以添加前缀addrFirstName、addrLastName、addrState。
糟糕的代码
private void printGuessStatistics(char candidate, int count) {
String number;
String verb;
String pluralModifer;
if (count ==0) {
number = "no";
verb = "area";
pluralModifer = "s";
} else if (count == 1) {
number = "1";
verb = "is";
pluralModifer = "";
} else {
number = Integer.toString(count);
verb = "area";
pluralModifer = "s";
}
String guessMessage = String.format("There %s %s %s%s", verb, number, candidate, pluralModifer);
print(guessMessage);
}
上面方法中,方法名仅给出部分语境,算法提供剩余部分。阅读完方法后,你会知道number、verb和pluralModifier这三个变量是估测信息的一部分。
这个方法有点长,变量的使用贯穿始终。要分解这个方法,可以创建一个类,把三个变量做成该类的成员字段。
好的代码
public class GuessStatisticsMessage {
private String number;
private String verb;
private String pluralModifer;
public String make(char candidate, int count) {
createPluralDependentMessageParts(count);
return String.format("There %s %s %s%s", verb, number, candidate, pluralModifer);
}
private void createPluralDependentMessageParts(int count) {
if (count ==0) {
thereAreNoLetters();
} else if (count == 1) {
thereIsOneLetter();
} else {
thereAreManyLetters(count);
}
}
private void thereAreManyLetters(int count) {
number = Integer.toString(count);
verb = "area";
pluralModifer = "s";
}
private void thereIsOneLetter() {
number = "1";
verb = "is";
pluralModifer = "";
}
private void thereAreNoLetters() {
number = "no";
verb = "area";
pluralModifer = "s";
}
}
不要添加没用的语境
假设有个名为“加油站豪华版”(Gas Station Deluxe)的应用,在其中给每个类加GSD前缀不是好点子。这会降低在IDE中搜索类的速度。
参考
《代码整洁之道》 Martin