一、整洁代码
1、什么是整洁的代码
代码逻辑直接了当,尽量减少依赖关系,使之便于维护;依据某种分层战略完善错误处理代码,把性能调至最优,整洁的代码只做好一件事。
2、简单代码重要性排序
a、能通过所有测试。
b、没有重复代码。
c、体现系统中的全部设计理念。
d、包括尽量少的实体,比如:类、方法、函数等。
二、有意义的命名
1、类、函数、变量都要注意命名,而且一旦发现更好的名称就换掉旧的。虽然选个好名字会花费时间,但省下来的时间比花掉的更多。一个好的命名能让人更加容易理解代码。
反例:
public List<int[]> getThem(){
List<int[]> list1=new ArrayList<int[]>();
for(int[] x:theList){
if(x[0]==4) {
list1.add(x);
}
}
return lits1;
}
问题点:
a、theList中是什么类型的东西。
b、theList零下标条目的意义是什么?
c、值4的意义是什么?
d、我怎么使用返回的列表?
改进:以扫雷为例
public List<Cell> getFlaggedCells(){
List<Cell> flaggedCells=new ArrayList<Cell>();
for(Cell cell:gameBoard){
if(cell.isFalgged()){
flaggedCells.add(cell);
}
}
return flaggedCells;
}
2、尽量避免误导
程序员必须避免留下掩藏代码本意的错误线索。应避免使用与本意相悖的词。例如hp、aix、sco都不该做变量名,因为他们都是UNIX平台或类UNIX平台的专有名称。
别用accuntList来指称一组账号,除非它真的是List类型。List一词对程序员有特殊的意义。如果宝娜账号的容器并非真是List,就会引起错误的判断。
3、类名、方法名
类名和对象应该是名词或名词短语,如Customer、Account,避免使用Manager、Prcessor、Data这样的类名。
方法名应该是动词或动词短语:如:postPayment、deletePage等。属性访问器、修改器、和断言应该根据其值来命名。
4、添加有意义的语境
很少有名称是能够自我说明的—多数不能。因此,需要用良好命名的类、函数或名称空间来放置名称,给读者提供语境。
假如有名为firstName、lastName、street、houseNumber、city变量,这的确很明确看出是地址。可是只若看到state呢?此时添加前缀addrFirstName、addrLastName、addrState等,一次提供语境。
三、函数
1、原则:函数代码要尽量短小,每个函数应该只做一件事。
2、一元函数普遍形式
向函数传入单个参数有两种普遍性形式。
就像boolean fileExists(“MyFile”)中那样,可能是操作该参数,将其转换为其他什么东西在输出。例如:InputStream fileOpen(“MyFile”)把类型的文件名转换为InputStream类型的返回值会更符合函数形式。
在函数事件(event)中尽量少使用void passwordAttemptFailedNtimes(int attempts)形式,因为他会使读者不能清楚了解他是个事件。
3、参数对象
如果函数看来需要两个、三个或以上参数,就说明其中一些参数应该被封装为类。
例如:
Cricle makeCricle(double x,double y,double radius);
Cricle makeCricle(Point center,couble radius);
4、函数应该只做一件事,但有时还是会做其他被隐藏起来的事。有时,他会对自己类中的变量做出未能预期的改动。有时,它会把变量搞成向参数传递的参数或是系统全局变量。无论哪种情况,都可能会导致时序性耦合和顺序依赖。
public class UserValidator{
private Crypttographer crypttographer;
public boolean checkPassword(String userName,String password){
User user=UserGateway.findByName(userName);
if(user!=User.NULL){
String codePhrase=user.getPhraseEncodedByPassword();
String phrase=crypttographer.decrypt(codedPhrase,password);
if("Valid Password".equals(phrase)){
Session.initialize();
return true;
}
return false;
}
}
}
问题在于对Session.initialize()的调用。checkPassword函数是用来检查密码的。但该名称并未按时它会初始化该次会话。所以,可能在调用者调用时有冒抹会话数据风险。
5、抽离try/catch代码块
try/catch代码块会搞乱代码结构,把错误处理与正常流程混为一谈。最好把try/catch代码块的主体抽离出来,形成函数。
public void delete(Page page){
try{
deletePageAndAllReferences(page);
}catch(Exception e){
logError(e);
}
}
private void PageAndAllReferences(Page page) throw Exceptin{
deletePage(page);
registrydeleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
private void logError(Exception e){
logger.log(e.getManage());
}
6、结构化编程
每个函数、函数中的每个代码块都应该有一个入口、一个出口。这意味着,每个函数只能有一个return语句,循环中不能有break和continue语句。在写代码时,一开始都会冗长而复杂,有太多缩进和循环,有过长的参数列表,名称也会随意取。这时,需要我们结合单元测试打磨这些代码,分解函数、修改名称、消除重复。、