《代码整洁之道》笔记第二篇

small1

上一篇文章中我们了解了整洁代码对程序的重要性,而且也了解了要写出整洁代码的最基本的一点,也就是命名。这是第二篇文章,主要讲述的是函数(方法)对于程序的作用,上一篇说到“代码命名就像一座大厦里的一块砖头”。那么我认为函数对于程序来说就行是一面墙,墙对于大厦也起着至关重要的作用,比承重墙之类的,那么我们要如何写好函数,写函数的时候要注意什么?,本篇文章就来一一解答这两个问题。

我们在平时开发工作中基本上都会去看别人写的代码和自己以前写的代码,自己写的代码能记下来还好,但是记不下来的情况下,再来看代码会多多少少会有一点迷茫,更不要说看别人的代码了,每个人有每个人写代码的风格,有的人写的代码简单,明了,逻辑性强,可读性高。有的人写的代码可能看起来比较杂乱,不知道他想要干什么。一大本分原因是因为有的代码中函数里写的代码非常多,而且非常乱,这样的代码我们看起来会觉得吃力。那么什么样函数让别人看起来会觉得非常明白呢?

函数的要短小

20世纪80年代,我们常说函数的长度不应该超过一屏,但是这话现在来看有点不太合适了,应为现在的屏幕大小,分辨率都非常的优秀。好的函数只有两三行,而且一目了然,而且每一个函数都会把你带到下一个函数里。

if else while 语句等,其中的代码里应该只有一行,这行大抵应该是一个函数调用语句。这也意味着函数不应该大到足以容纳嵌套结构,但是平时开发的时候可能达不到那么高的要求。但是还是努力的达到要求。

只做一件事

函数应该做一件事,做好这件事,只做这一件事 函数不应该很多事,执行的操作要和函数名一样,函数名字起的也要符合操作。

switch语句

写出简短switch语句很难

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public Money calculatePay(Emploee e)throws InvalidEmployeeType{
switch(e.type){
case COMMISSIONED:
return calculateCommissionrdPay(e);
break;
case HOURLY:
return calculateHourlyPay(e);
break;
case SALARED:
return calculateSalareddPay(e);
break;
default:
throws new InvalidEmployeeType(e.type);
}
}

上面switch语句其实已经很简洁,但是如果在增加几个类型会变得很长,而且违背了只做一件的事的原则,后期修改起来很麻烦,但是最麻烦的是可能到处有类似结构的函数,例如

1
isPayday(Employee e);
1
deleiverPay(Employee E);

这个时候我们应该想起工厂模式

1
2
3
public abstract class Employee{
public abstract boolean isPayday();
public abstract Money calculatePay();
1
2
3
public interface EmployeeFactory{
public Employee makeEmployee(EmployeeRecord r);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class EmployeeFactoryImpl implements EmployeeFactory{
public static Employee makeEmployee(EmployeeRecord r){
switch r.type{
case COMMISSIONED:
return calculateCommissionrdPay(e);
break;
case HOURLY:
return calculateHourlyPay(e);
break;
case SALARED:
return calculateSalareddPay(e);
break;
default:
throws new InvalidEmployeeType(e.type);
}
}
}

这样之后我们要生成雇员直接可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
但是不是所有的场景都适合这么些,也要就事论事,有的时候不会违反这些规则。
# 使用描述性的名称
函数的名字一定要明了,函数越短小,功能越集中,就越方便起名字。名字一定要符合函数里的操作。
# 函数参数
尽量使用输入函数,输出函数要当成返回值,就像Android中Matrix,有的方法中传入RectF,然后一些运算的结果也直接赋值到这个参数中,这就是输出函数。
# 多参数
两个参数参数的时候 函数名最好要明确第一个个第二个函数的区别
```equals(a,b)```调用的时候如果忘了a,b的含义和顺序,还要回来看一下,这样会耽误时间和打断思路的,但是写成```equalsFileNameAndPath(String name,String path)```这样调用的时候是不是就会很清晰明了。如果可以把二元函数改为一元函数比如```writeFile(OutPutStream out , String path)```如果可以把OutPutStream写在当前累中的成员变量里,这样就可以```outputStream.writeField(name);

如果参数是一个类的多个属性,那么就把类当作参数。

无副作用

我之前在请求网络数据的时候吧方法名起为 initData();但是在数据拉下来的时候顺便就把适配器也设置了,这设置适配器就是副作用,初始化数据,就是初始化数据,设置适配器就是设置适配器,这样以后要找设置适配器的代码会很那招到,但是也可以把方法名改为initDataAndsetAdapter();这样就不会有副作用了,只不过这样违反了只做一件事的原则

用异常来代替错误码

错误的时候的throws异常,然后在调用的时候在catch语句中区分错误类型。就不用在try中处理错误类型了 try里就是正常操作,catch就是处理错误,这样看起来就会很明了

千万别重复

这一点大家大家都应该知道了,代码重复会造成代码冗余,看起来臃肿。就不多说了。

最后的话

要写出好的函数,应该像写作文一样,要读起来有一种“理应如此”的感觉。