代码整洁之道 (clean code) 读后感
Posted BBinChina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码整洁之道 (clean code) 读后感相关的知识,希望对你有一定的参考价值。
第二次读代码整洁之道(Clean Code)了,在少许开发经验加持下,没有第一次那么晦涩后,整体对本书也有了共鸣,这本书应该作为指导手册,平时可以多翻一翻,说不定会有新的不同感悟,当然了,书中的条例并不需要你照本宣科地按着做,那样没意义。
首先,代码就像书稿,在完成一件作品之前,我们需要不停地对作品进行推敲,所以重构是贯穿这个代码的生命周期,在这个过程中,隐含着一个工作前提:测试用例。
单元测试
本书用了一大章节来讲单元测试,但核心就一句话,测试驱动开发(TDD)的编程思维,这只是一个方法论,并不是什么规范。
例子
我们可以先写以下的测试代码,再定义User 以及 UserService的逻辑
@Test
void test() {
User user = User.build();
userService.create(user);
};
方法论在于,无论任何方式,比如采用postman编写http请求也可以进行测试,但通过硬代码更大的优势在于测试用例靠近于使用端,便于传阅查看。
ps:不写测试的代码就像上大号不洗手
代码结构
垂直分隔
上文讲到测试用例靠近于使用端,在我们进行阅读时,也是习惯性自上而下阅读,当变量或者函数在被调用附近所定义时,也即垂直距离更近时,更方便阅读。
类成员
面向对象编程时,类成员变量的访问通常来说都应该由实体进行操作,所以我们经常性会提供get set方法,如以下
class test {
private int i;
public int getI() {
return i;
}
}
先声明成员变量,再声明函数的方式,便于阅读。而早期学习c++的时候,通常煞有其事地是 先声明函数,再声明变量,反而每次跳转查看类时,需要先定位到底部。
函数
输出参数
以前写c++时(c03),为了减少拷贝,经常采用引用参数的方式,如下所示:
void GenOrder(Goods goods, Order& order);
通过函数名可以确定该函数的职能是生成订单,所以应该调整为
void Order GenOrder(Goods goods) {
Order order = new Order;
return std::move(order);
}
现在c++11 通过编译优化后,可以临时的创建复制,而在java等其他语言中,无非就是一次引用计数。
老生常谈的单一职责
比如 GenOrder该函数,一看便知是生成订单,通常的规范要求API 采用 动词 + 名称的方式,因为api一般都是描述对象的行为方式。
未避免过度封装,可以采用描述性行为,比如 检测订单时
public boolean checkOrderValid() {
if (money) {
}
if (count) {
}
}
不需要将金额,数量等检测细节过度封装成函数,除更复杂的逻辑外。
什么情况下需要拆分呢,当if 或者switch可以用多态时,比如计算不同雇员的薪水时:
public Money calculatePay(Employee e) {
switch(e.type) {
case:
return calA();
case:
return calB();
}
}
这里处理为
A implements Employee {
pay();
}
B implements Emplyee {
pay();
}
不同雇员的薪水根据雇员的身份进行多态计算
java 的枚举可以拥有方法和字段,所以我们也可以采用以下方式重构:
public enum HourlyPayGrade {
A {
public double pay() {
}
},
B {
public double pay() {
}
};
public abstract double rate();
}
使用异常替代返回错误码
在写c++时,本身追求的是c++的高性能,所以经常会有规范是禁止是用exception,在编译时关闭exception可会让程序减少exception的成本,比如大小或者速度,那取而代之的是setError、getError的方式。
但其实,本着工程化,且不需要压榨最后一丁点cpu或者内存时,我们还是希望使用Exception的方式,在可预知出现Exception的地方把问题处理掉,可以让我们的程序更加健壮,毕竟可用性可比性能在大部分场合的重要性更大。
而且通常需要我们抽离Try/Catch代码块
void test() {
try {
func();
}catch() {
xxxx
}
}
本身 异常的处理 xxx 部分就是一件单独职责的事情,不应该跟func的逻辑耦合在一起,看看自己的tryCatch代码部分,第一眼感觉如何呢?
null值不是合理值
查看下自己的代码,你是否会经常检测null的存在呢?
那既然不是合理值,那就应该进行错误提示,比如NotFind,或者是特例化对象,或者是空数组等“合理值”,让调用者更加舒服的处理,而往往我们又可能是那个调用者,让自己以后更舒服的码代码不好嘛。
返回不能是null值,接收值也不应该是null值,当我们无法百分之百信任调用方时,那就是不能信任,必须禁止传入null值。
以上是关于代码整洁之道 (clean code) 读后感的主要内容,如果未能解决你的问题,请参考以下文章
清洁代码之道:一份实用关于如何编写和维护干净整洁的好代码的的方法 The Art Of Clean Code...