代码整洁之道学习笔记

代码整洁之道读书笔记

一、有意义的命名

  1. 名副其实

表示产品A上线时间剩余天数

// 差
int d;

// 一般, 但和差一样, 不知道天数的作用
int day;

// 好
int remainDaysBeforeOnline;

获取水果订单中所有的id为4的苹果订单

// 差
List list1 = new ArrayList();
for(int[] x : theList){
    if (x[0] == 4){
        list1.add(x)
    }
}
return list1;

// 好
List appleOrders = new ArrayList();
for(int[] orderItem : allFruitOrder){
    if(orderItem[idIndex] == APPLE_ID){
        appleOrders.add(orderItem)
    }
}
return appleOrders;

// 更好
把 orderItem[idIndex] == APPLE_ID 抽离成函数
isAppleOrder()

  1. 避免误导
  • 不用非通用的缩写: ht, aix, sco
  • 不用accountList 表明账户列表,list 常有特殊意义,除非这确实是一个List类型
  • 不使用字母i,o,l 来表示变量,因为会和1,0数字混
  1. 做有意义的区分
  • a1,a2,a3无意义
  • 类Product 和 ProductInfo 和 ProductData 无区分,是意义含混的废话。只取Product
  • nameString 和 name 无区分,因为name不可能是浮点
  • Customer和CustomerObject无区分,取Customer

要区分,就要取读者能够区分的不同单词

  1. 使用读得出来的单词
// 差
class DtaRcrd102 {
    private Date genymdhms;
}

// 好
class Customer {
    privateDate generationTimestamp;
}
  1. 使用可搜索的名称

MAX_GIRL_AGE 就比 8 要好,因为前者可搜索,一般不重复,后者到处都有

  1. 类名应该是名词或名词短语如Customer, Account, Address 而不应该使用Manager Data Info
  2. 方法名应该是动词或动词短语如postPayment, deletePage,
  3. 每一个概念对应一个词

二、函数

  1. 短小

能有多小,就多小

  1. 只做一件事,做好这件事
  1. 每个函数一个抽象层级

getHtml() 较高抽象层

encodePath() 中级抽象层

appendString() 低级抽象层

同一个抽象层的东西,写到一些,不要高级中又大量混入低级。

应该是高级调用中级,中级调用低级,从上到下依次

  1. 函数参数

参数越少越好,最好的是0参数,第二好的是1参数,超过3个参数,就要反省了

  1. 标识参数
// 差
render(true);
render(false);

// 中
render(Boolean isSuite);

// 好
renderForSuite();
renderForSingleTest();
  1. 如果参数超过3个,则要考虑将参数封装为类了
  2. 动词和关键字

assertEqual(expected, actual); 使用者往往不知道参数的顺序先后。

assertExpectedEqualActual(expected, actual); 这样会更好一些,因为从函数名就可以知道参数先后。

但我觉得现在的ide已经能将参数名显示出来,那简短的名字将更好。

  1. 分隔指令与询问,函数要么做事,要么回答问题,不要即做事又回答问题。
  2. 使用异常替代返回错误码

如果使用异常替代返回错误码,那么代码分离,使代码得到简化。如果返回错误码,那得到错误码的人又得处理错误

  1. 抽离try/catch代码块
// 一般
try{
    deletePage(page);
    register.deleteReference(page.name)
        ...
}catch{
    ...
}

// 好,抽离try/cache
try{
    deletePageAndReference(page)
}catch{
   ...
}

deletePageAndReference(page){
    deletePage(page);
    register.deleteReference(page.name)
    ...
}
  1. 错误处理就是一件事
  2. 错误码,依赖磁铁,不好

就是定义错误码的类,导致其他的许多类都要导入和使用他,一但他改变,所有地方都要重新编译。而新异常可以从异常类中派生出来,无需要重新编译或重新部署。

  1. 如何写出优秀的函数

几乎没有可能一开始就写出优秀的函数,高手也是先把函数,逻辑,代码写出来,命名,规则,等都不那么完美。等写完了,再来一步一步分离,拆解,优化,重命名!!!!

三、错误处理

  1. 使用异常而非返回码
  2. 别返回null

因为返回了null,则调用者要检查返回是否为null,不然就会报空指针错误。

有错误就应该抛出异常或返回特例对象。

其实可以返回空数组,空字符串等,都比null要好。

  1. 别传递null值
  2. 把错误提取,独立处理,别混在正常业务代码中

四、边界

  1. 学习性测试

在使用第三方库时,我们没必要为第三方库写测试,测试应该由第三方库来负责。但我们又在使用他们的代码。我们可以为我们使用到的部分的第三方库代码做测试。相当于边学习,边测试。

  1. 使用尚不存在的接口

我认为其实就是把方法造出来,写一下模拟数据,进行mock,当尚不存在的接口开发好后,再接进来。

  1. 测试代码和生产代码一样重要。

当我们在程序还小的时候,不写测试代码,只是自己执行一下,看看是否有问题。

当程序大的时候,已经没办法一项一项的测试过去。我们修改了一处代码,引发了其他处代码的未知错误。

单元测试越完整,修改才越大胆和快速。不然你总是会害怕改代码。

  1. 单元测试的好处,让代码可扩展,可维护,可复用

五、类

  1. 类应该短小

系统应该由许多短小的类组成,而不是少数几个庞大的类组成。

你可能感兴趣的:(代码整洁之道学习笔记)