代码整洁之道 (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...

清洁代码之道:一份实用关于如何编写和维护干净整洁的好代码的的方法 The Art Of Clean Code...

Clean Code

clean code

《代码整洁之道》读后感

好文章系列——代码整洁之道