
脍炙人口的诗"春有百花秋有月,夏有凉风冬有雪",意境唯美,简明易懂。好的代码也是让人陶醉的,那么如何写出好的代码?高质量代码有三要素:可读性、可维护性、可变更性。我们的代码要一个都不能少地达到了这三要素的要求才能算高质量的代码。
代码可读性的重要性
一提到可读性似乎有一些老生常谈的味道,虽然大家一而再,再而三地强调可读性,但我们的代码在可读性方面依然做得非常糟糕。由于工作的需要,常常需要去阅读他人的代码,维护他人设计的模块。每当看到大段大段、密密麻麻的代码,而且还没有任何的注释时常常感慨不已,深深体会到了这项工作的重要。由于分工的需要,我们写的代码难免需要别人去阅读和维护的。而对于许多程序员来说,阅读和维护别人的代码常有的事,而往往在平常很少关注代码的可读性,也对如何提高代码的可读性缺乏切身体会。有时即使为代码编写了注释,也常常是注释语言晦涩难懂形同天书,令阅读者反复斟酌依然不明其意。
对于一个整体的软件系统而言,既需要宏观上的架构决策,设计与指导原则,也必须重视微观上的代码细节。在过往中,有许多影响深远的重大失败,其根源往往是编码细节出现了疏漏。
怎么理解代码可读性
可读性基本定理:代码的写法应当使别人理解它,所需要的时间最小化(让人容易阅读、理解、调试、可预料的程度)。然而我们在平时编程中,有典型的错觉,误以为越少的代码越容易让人理解,但事实上并不是代码越精简就越容易让人理解。相对于追求最小化代码行数,更好的提高可读性方法是:最小化人们理解代码所需要的时间。

表层的改进

首先来讲最简单的一层如何改进,涉及到以下几点:
1.如何命名

我们在命名变量、函数、属性、类以及包的时候,应当仔细想想,使名称更加符合相应的功能。我们常常在说,设计一个系统时应当有一个或多个系统分析师对整个系统的包、类以及相关的函数和属性进行规划,但在通常的项目中这都非常难于做到。对它们的命名更多的还是程序员来完成。但是,在一个项目开始的时候,应当对项目的命名出台一个规范。譬如,在我的项目中规定,新增记录用new或add开头,更新记录用edit或mod开头,删除用del开头,查询用find或query开头。使用最乱的就是get,因此get开头的函数仅仅用于获取类属性。
关键思想:把尽可能多的信息装入名字中。
1.选择专业的词汇,避免泛泛的名字
2.给名字附带更多信息
3.决定名字最适合的长度
4.名字不能引起歧义
选择专业的词汇,避免泛泛的名字
举例get、query等词最好是用来做轻量级的取方法的开头,严禁使用拼音和英文混合的方式,更不允许直接使用中文的方式。
给名字附带更多信息
除了选择一个专业,贴切意图的词汇,我们也可以通过添加一些前后缀来给这个词附带更多的信息。这里所指的更多的信息有三种:变量的单位、变量的属性、变量的格式。
决定名字最适合的长度
名字越长越难记住,名字越短所持有的信息就越少,如何决定名字的长度呢?总结有几个原则:
1.如果变量的作用域很小,可以取很短的名字
2.驼峰命名中的单元不能超过3个
3.不能使用大家不熟悉的缩写
4.丢掉不必要的单元
名字不能引起歧义
名字要表达意思明确,不能让人看不懂。

2.如何声明与使用变量

1.变量越多,越难跟踪它们的动向。
2.变量的作用域越大,就需要跟踪它们的动向越久。
3.变量改变的越频繁,就越难跟踪它的当前值。
相对的,对于变量的声明与使用,我们可以从这四个角度来提高代码的可读性:
1.减少变量的个数
2.缩小变量的作用域
3. 缩短变量声明与使用其代码的距离
4. 变量最好只写一次

3.如何简化表达式

有些表达式比较长,很难让人马上理解。这时候最好可以将其拆分成更容易的几个小块。可以尝试下面的几个方法:
1.使用解释变量
2.使用总结变量
3.使用德摩根定理
使用解释变量
有些变量会从一个比较长的算式得出,这个表达式可能很难让人看懂。这时候就需要用一个简短的“解释”变量来诠释算式的含义。使用一个例子:

其实上面左侧的表达式其实得出的是用户名,我们可以用userName来替换它:

使用总结变量
除了以“变量”替换“算式”,还可以用“变量”来替换含有更多变量更复杂的内容,比如条件语句,这时候该变量可以被称为"总结变量"。使用一个例子:

上面这条判断语句所判断的是:“用户id是否相等”。我们可以使用一个总结性的变量isEqual来替换它:

德摩根定理:
当我们条件语句里面存在外部取反的情况,就可以使用德摩根定理来做个转换。使用例子:


4.如何让代码具有美感

在读过一些好的源码之后我有一个感受:好的源码往往都看上去都很漂亮,很有美感。这里说的漂亮和美感不是指代码的逻辑清晰有条理,而是指感官上的视觉感受让人感觉很舒服。这是从一种纯粹的审美的角度来评价代码的:富有美感的代码让人赏心悦目,也容易让人读懂。
为了让代码更有美感,采取以下实践会很有帮助:
1.选择一个有意义的顺序
2.把代码分成"段落"
3.保持风格一致性
4.不要编写大段的代码

5.如何写注释

注释是每个项目组都在不断强调的,可是依然有许多的代码没有任何的注释。为什么呢?因为每个项目在开发过程中往往时间都是非常紧的。在紧张的代码开发过程中,注释往往就渐渐地被忽略了。注释的目的是尽量帮助读者了解得和作者一样多。在你写代码的时候,在脑海中可能会留下一些代码里面很难体现出来的部分:这些部分在别人读你的代码的时候可能很难体会到。而这些“不对称”的信息就是需要通过以注释的方式来告诉阅读代码的人。


控制流和逻辑的改进

控制流在编码中占据着很重要的位置,它往往代表着一些核心逻辑和算法。因此,如果我们可以让控制流变得看上去更加“自然”,那么就会对阅读代码的人理解这些逻辑甚至是整个系统提供很大的帮助。
那么都有哪相关实践呢?
1.使用符合人类自然语言的表达习惯
2.if/else语句块的顺序
3.使用return提前返回
4.代码不能写死
5.预测可能发生的变化
1.使用符合人类自然语言的表达习惯

写代码也是一个表达的过程,虽然表现形式不同,但是如果我们能够采用符合人类自然语言习惯的表达习惯来写代码,对阅读代码的人理解我们的代码是很有帮助的。条件语句中参数的顺序:首先比较一下下面两段代码,哪一个更容易读懂?

大家习惯上应该会觉得code1容易读懂。还有条件语句中的正负逻辑:在判断一些正负逻辑的时候,建议使用if(result)而不是if(!result)。

2.if/else语句块的顺序

在写if/else语句的时候,可能会有很多不同的互斥情况(好多个else if)。那么这些互斥的情况可以遵循哪些顺序呢?
先处理掉简单的情况,后处理复杂的情况:这样有助于阅读代码的人循序渐进地地理解你的逻辑,而不是一开始就吃掉一个胖子,耗费不少精力。
先处理特殊或者可疑的情况,后处理正常的情况:这样有助于阅读代码的人会马上看到当前逻辑的边界条件以及需要注意的地方。

3.使用return提前返回

在一个函数或是方法里,可能有一些情况是比较特殊或者极端的,对结果的产生影响很大(甚至是终止继续进行)。如果存在这些情况,我们应该把他们写在前面,用return来提前返回(或者返回需要返回的返回值)。
这样做的好处是可以减少if/else语句的嵌套,也可以明确体现出:“哪些情况是引起异常的”。

4.代码不能写死


5.预测可能发生的变化



代码组织的改进


关于代码组织的改进,以下三种方法:
1.抽取出与程序主要目的“不相关的子逻辑”
3.借助自然语言描述来将想法变成代码
一个函数里面往往包含了其主逻辑与子逻辑,我们应该积极地发现并抽取出与主逻辑不相关的子逻辑。类似于工具方法的函数其实是脱离于某个具体的需求的:它可以用在其他的主函数中,也可以放在其他的项目里面。

结语:
遵循一些简单的规定(规范化指导)能使代码将更容易阅读(从而进一步理解、维护和扩展)。个人认为这一点是最重要的,好的程序员都是有强迫症的,他们会严格要求自己,通过不断的学习来提升自己的技术最终成为大神级别的程序员。如果不能以高标准来要求自己,即使看再多的如何写出高质量代码,懂再多的代码规范,也是没有用,最终还是会写出低质量代码。但是,提高自我要求是一种改变,一般来说,改变都不是一蹴而就的,需要一步一步来。所以,改变最好从小事做起,慢慢积累,最终蜕变。先从代码规范开始,熟悉代码规范,遵循规范写代码,直到成为习惯,然后再学习其它方法,最终写出高质量代码,让我们一起坚持,且一起行动。
- END -





