读书笔记-整洁代码编写
概述
不要出现重复代码。
每一个函数,只做好一件事。每一个类,只扮演一个角色。函数与函数之间要有尽量少的依赖关系,类与类之间要有尽量少的依赖关系(独立存在)
有意义的命名
名副其实
在编写代码的时候,应该考虑到命名的重要性,牢记名副其实的原则—如果名称还需要用注释来解释,那就不叫名副其实了。当然,注释是不可缺少的,主要起到模块功能上的介绍。在编写代码时,应该想着在尽量让读者理解的情况下,如何少用注释,更多的是让代码自己解释给读者发生了什么?所谓的代码自解释性。
举例说明:
定义一个函数,如下:
注:感觉这个函数还可以啊, 不是挺好的吗?有详细的注释,有参数说明。但是去掉这些注释,你在看看,这个函数。你应该会问:这个参数data是什么鬼?咦,这个IC前缀为什么要在上面?我靠,这个函数到底要干吗,返回的又是什么东西?
如果你也想问上面提到的那些问题,那就请看看重新命名之后的函数。
看了这个新的函数名之后,你是不是发现,连注释都已经不需要了呢?
每一个概念对应一个词
在项目开发中,一般都是多人开发,如果没有一个统一命名的规定的话,我想后果应该是非常可怕的。例如,大家都表示同一个对象,表视图;小A叫它tableMenu, 小B设置为MenuView, 小C叫它tableView, 小D叫它table。现在看来,好像并没有什么太大的问题,但是放到整个项目中,效果就大大的不一样了,因此统一命名是非常重要的一件事情。
举例说明:
下面显示的两个一模一样的代码。命名不同而已。
下面是命名统一的代码:
从这两个代码中比较得出,对一个概念去统一的名字,是相当重要的一件事情!现在代码少,可能看不出来,但是到了项目多的时候,去好处就显而易见了。
函数
在我看来,一个函数,只要遵循『只做一件事』的原则,那么这个函数就是好的函数。
只做一件事
一个函数,只要做好一件事情,并且只做一件事情,那么这个函数,就是好函数。那么什么是一件事情呢,可以给他做一个定义吗?下面就是我对一件事情的定义:在同一个抽象层级上,对事件的完整描述。
举例说明:
先来一个代码:
如果一个函数中,存在上面的代码。那么这个函数是一个好函数吗?
答案当然是否定的!你想想这个函数,做了几件事情,实在是太多了。 这个函数中,包括了三个抽象层级上的事件完整描述。下面是对这三个层级结构的抽象:红色框中为两个独立的层级结构,整个函数有是一个总体的层级结构。一个层级结构中,对一件事物的完成抽象是一件事,那么这个函数一共做了三件事情。这个函数实在是太忙了,这么忙不但不易于读者理解,而且很容易出错的,bug也不容易定位。
因此我们可以对这个函数重构,下面是重构之后的函数:
我们将之前的一个函数,根据层级结构拆分成了三个函数,每一个函数,表示一个层级结构上的事件完整描述。这样子,有了一个清晰的结构。在代码量变多的时候,不会出现混乱。定位错误也比较容易。
这个时候,有人会问:那么怎么对函数进行拆分呢?下面来说说我的看法:首先,需要理解一个函数的抽象层级结构,将他的最高层次逻辑结构提炼,之后在一一提炼出他的其他结构。之后,拆分不同结构下的处理事件,并重构出在同一层级结构中的事件函数。
下面是之前那个函数的逻辑框图,和他的拆分方式:
现在逻辑框图已经拆分好了,之后要做的就是将这些分离到最简的逻辑连接起来了。连接这些逻辑,将逻辑通过代码的方式展现和连接。最后,就变成了一开始,我们重构好的代码了,这个代码,每个函数都只做一件事,并且,依序把你带到下一个函数。
小小建议
尽量让你的函数参数保持在三个或者三个以下。超过三个,函数处理起来,将不在简单,需要重构。在编写项目时,有些无脑的设置属性函数除外。不超出三个参数,意思是一个函数中存在三个参数,那么在这个函数中存在的逻辑处理会比较复杂,例如三个BOOL参数,将会带来8种不同的情况。此时,最好重构。
如何写出这样的程序
首先,你先想着什么写什么,然后在慢慢打磨。一开始,写函数时,都是陈长而且复杂的。有太多的缩进和嵌套循环。有过长的参数列表,名称也是随意取的,也会有重复的代码。然后慢慢打磨这些代码,分解函数,修改名称,消除重复,有时还要拆分类。
注释
如果编程语言有足够的表达力,那么也就不需要注释。如果你需要编写注释,那么从某种角度上说,就是你编写了烂代码。当然,有些注释也是有利于代码的理解的,仅仅只是少部分。
需要编写注释的情况:
对函数功能的说明,在编写好代码之后,对函数进行重构,在重构好的前提下,对函数进行功能上的说明,可以让读者快速了解函数功能。但是这也会带来一定风险,随着时间的推移,函数被不断重构,再造。可能会出现的问题就是,之前的注释已经不在是现在函数的功能,会误导代码读者。
在编写程序的时候,一开始需要将自己的思想都通过注释表达出来。之后,就需要看看在注释的地方,是否可以通过代码自解释的方式(例如函数的命名)进行表达。从注释方面对代码进行整理。总之一句话,能删掉注释的都删掉,不能删掉注释的通过代码自解释性替换之,不能替换注释的详细说明他的用途它。
在编写项目的时,编写一下注释,通过注释来将一个函数中的各个模块分开。通过少量此类注释,可以将函数分层,是一种比较好的方式。但是,如果需要对函数进行分层,那么就应该考虑函数的重构了,因为函数太长了。