You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 15 | 编写规范代码的检查清单
通过前面十几讲的学习,我们已经把代码“规范”篇的内容学习完了。今天,我们一起把前面讨论到的观点总结一下,并探索一下编写规范代码时的最佳实践检查清单。一份有效的检查清单,可以帮助我们记忆、遵循和执行代码的一系列规范。
## 标准与指南
在讨论编码规范之前,我们首先要认识什么是标准,什么是指南,以及它们各自的局限性。这样我们就能知道,什么可以做,什么不可以做。
标准是既定的做事方式,它定义了一个事物如何始终如一地达到同样水准的细节。标准的特征在于,它既是必需的,也是强制的。
然而,在现实实践中,能够标准化的东西是有限的。所以就有了指南,它是标准的补充。
指南告诉我们应该采取的总体方向和最佳实践,它是一个指导原则,是建议,不强制执行。用户可以根据具体情况,决定是否遵循相关的条款。
我们所说的编码规范,实际上通常是指导原则。虽然不具备强制性,但我们也有必要区分对不同建议条款的态度,比如对使用“强烈推荐”这样字眼的建议来说,我们就应该格外重视。这样,可以避免不必要的争执,降低复杂性。
## 为什么需要编码规范?
**1.提高编码的效率**
在不损害代码质量的前提下,效率可以节省我们的时间和成本。这种节省不仅仅停留在编码阶段,更体现在整个软件的生命周期里。我在第四篇已经详细解释了这一点。
**2.提高编码的质量**
代码的质量在于它和预期规范的一致性。一致、简单、规范的代码易于测试。相反,复杂的代码会加大测试的难度,难以达到合适的测试覆盖率。另外,代码的复用也意味着质量的复用,所以代码的问题会随着它的复用成倍地叠加,提高了软件的使用或者维护成本。
**3.降低维护的成本**
代码的维护要求代码必须能够修改,增加新功能,修复已知的问题。如果代码结构的清晰、易于阅读理解,那么问题就容易排查和定位。
**4.扩大代码的影响**
要想让更多的人参与,就需要一致的编码风格,恰当地使用文档。要方便他们阅读,便于解释。
使用编码规范可以让一个程序员减少出错,避免不必要的困扰。另外,编写规范的代码也是一种专业、成熟的体现。
## 编码规范的心理因素
编码风格最原始的依赖因素是人的行为习惯和心理学基础。通过了解一些基本的心理学原理,我们可以更好地理解编码风格的的基本规则。
* 两种思维模式
我们有两种思维模式,自主模式(快系统)和控制模式(慢系统)。自主模式的运行是无意识的、快速的、不怎么耗费脑力;控制模式需要集中注意力,耗费脑力,判断缓慢,如果注意力分散,思考就会中断。
自主模式在熟悉的环境中是精确的,所作出的短期预测是准确的,遇到挑战时,会第一时间做出反应。然而,它存在成见,容易把复杂问题简单化,在很多特定的情况下,容易犯系统性的错误。比如说,第一印象、以貌取人,就是自主模式遗留的问题。
当自主模式遇到麻烦时,控制模式就会出面解决,控制模式能够解决更复杂的问题。但刻意掌控会损耗大脑能量,而且很辛苦。处于控制模式中太长时间,人会很疲惫,丧失一部分动力,也就不愿意去做启动控制模式了。比如,很多人害怕数学,多是因为控制模式确实很吃力。
自主模式和控制模式的分工合作是高效的,损耗最小,效果最好。快速的、习惯性的决断交给勤快省力的自主模式,复杂的、意外的决断由耗时耗力的控制模式接管。
编码规范中很大一部分内容,是增加共识、减少意外,扩大自主思维模式覆盖的范围,减少控制模式必须参与的内容。熟练掌握编码规范可以逐渐让这一套规则存在于人们的下意识中,这样编码的时候就像我们使用筷子一样,简单又自然。
* 识别模式
我们能够在这个世界上存活下来,依靠的不是识别完整的情景,也不是从头开始分析每一个情景,而是通过既定的可识别模式,来匹配这个世界。正常期望以外的模式,常常会让我们感到吃惊和困惑,甚至是生气。
模式识别的认知是一柄双刃剑,既是福音也是祸害。它可以帮助我们毫不费力地使用经验,但习惯一旦养成就很难改变,我们不愿意打破旧模式,去学习新模式和接受新技术。
程序员很容易理解和自己编码风格类似的代码。如果编码风格和自己的大相径庭,就会感到焦躁和烦恼。编码风格一旦形成,就难以更改,转变很痛苦。幸运的是,一旦努力转换成新习惯,我们就会喜欢上新的编码风格。
一份好的编码规范,刚开始接受会有些困难。我们甚至会找很多借口去拒绝。但是,一旦接受下来,我们就成功地改进了我们的识别模式。
* 猜测模式
对于既定模式的识别,是通过猜测进行的。对于每一个新场景,大脑立即会把它起始部分当作一个线索,然后通过拟合所有已知模式的起始部分,来预测模式的其余部分,猜测“言外之意”。我们掌握的信息越少,就越有可能犯错误。比如,在医院看到穿白大褂的,我们默认他们是医护人员。但医护人员的判断标准并不是白大褂。
所以在编写代码时,我们要有意识地提供足够的线索和背景,使用清晰的结构,加快模式的识别,避免造成模式匹配过程中的模糊和混淆带来的理解障碍。
* 记忆模式
我们的记忆模式有四种,包括感官、短期、工作和长期记忆。
感官记忆是对我们感官体验的记忆,非常短暂(大约三秒钟),比如我们刚刚看到的和听到的。
短期记忆是我们可以回忆的,刚刚接触到的信息的短暂记忆。短期记忆很快,但是很不稳定,并且容量有限。如果中途分心,即便只是片刻,我们也容易忘记短期记忆的内容。
工作记忆是我们在处理认知任务时,对信息进行短暂存贮并且执行操作的记忆。工作记忆将短期记忆和长期记忆结合起来,处理想法和计划,帮助我们做出决策。
长期记忆涵盖的记忆范围从几天到几十年不等。为了成功学习,信息必须从感官或短期记忆转移到长期记忆中。和短期记忆相比,长期记忆记忆缓慢,但是保持长久,并且具有近乎无限的容量。
我们在组织代码时,不要让短期记忆超载,要使用短小的信息快,方便阅读;要适当分割需要长期记忆和短期记忆的内容,比如接口规范和代码实现,帮助读者在工作记忆和长期记忆中组织和归档信息。
* 眼睛的运动
当我们看一样东西的时候,我们不是一下子就能看清它的全貌。事实上,我们的眼睛一次只能专注于一个很小的区域,忽视该区域以外的内容。当然,我们可以意识到还有更大的区域,然后快速跳转到其他区域。
有时候,我们需要反复研读一段代码。如果这段代码可以在一个页面显示,我们的眼睛就很容易反复移动,寻找需要聚焦的目标。如果这段代码跨几个页面,阅读分析就要费力得多。
当我们阅读时,我们的眼睛习惯从左到右,从上到下移动,所以靠左的信息更容易被接受,而靠右的信息更容易被忽略。
但是,当我们快速阅读或者浏览特定内容时(比如搜索特定变量),眼睛就会只喜欢上下移动,迅速跳过。聚焦区域小,眼睛倾向于上下移动,这就是报纸版面使用窄的版面分割,而不是整幅页面的原因之一。
在编码排版时,要清晰分块,保持布局明朗,限制每行的长度,这样可以方便眼睛的聚焦和浏览。
## 编码规范的检查清单
下面的这个清单,是我看代码的时候,通常会使用的检查点。如果有检查点没有通过,阅读代码的时候,就要格外留意;编写代码的时候,还要想想有没有改进空间;评审代码的时候,要问清楚为什么这么做,给出改进的建议。
你也可以参考一下。
* 代码是按照编码指南编写的吗?
* 代码能够按照预期工作吗?
* 文件是不是在合适的位置?
* 支撑文档是不是充分?
* 代码是不是易于阅读、易于理解?
* 代码是不是易于测试和调试?
* 有没有充分的测试,覆盖关键的逻辑和负面清单?
* 名字是否遵守命名规范?
* 名字是不是拼写正确、简单易懂?
* 名字是不是有准确的意义?
* 代码的分块是否恰当?
* 代码的缩进是否清晰、整洁?
* 有没有代码超出了每行字数的限制?
* 代码的换行有没有引起混淆?
* 每一行代码是不是只有一个行为?
* 变量的声明是不是容易检索和识别?
* 变量的初始化有没有遗漏?
* 括号的使用是不是一致、清晰?
* 源代码的组织结构是不是一致?
* 版权信息的日期有没有变更成最近修改日期?
* 限定词的使用是不是遵循既定的顺序?
* 有没有注释掉的代码?
* 有没有执行不到的代码?
* 有没有可以复用的冗余代码?
* 复杂的表达式能不能拆解成简单的代码块?
* 代码有没有充分的注释?
* 注释是不是准确、必要、清晰?
* 不同类型的注释内容,注释的风格是不是统一?
* 有没有使用废弃的接口?
* 能不能替换掉废弃的接口?
* 不再推荐使用的接口,是否可以尽早废弃?
* 继承的方法有没有使用Override注解
* 有没有使用异常机制处理正常的业务逻辑?
* 异常类的使用是不是准确?
* 异常的描述是不是清晰?
* 是不是需要转换异常的场景?
* 转换异常场景,是不是需要保留原异常信息?
* 有没有不应该被吞噬的异常?
* 外部接口和内部实现有没有区分隔离?
* 接口规范描述是不是准确、清晰?
* 接口规范有没有描述返回值?
* 接口规范有没有描述运行时异常?
* 接口规范有没有描述检查型异常?
* 接口规范有没有描述指定参数范围?
* 接口规范有没有描述边界条件?
* 接口规范有没有描述极端状况?
* 接口规范的起草或者变更有没有通过审阅?
* 接口规范需不需要标明起始版本号?
* 产品设计是不是方便用户使用?
* 用户指南能不能快速上手?
* 用户指南的示例是不是可操作?
* 用户指南和软件代码是不是保持一致?
## 小结
虽然说编码规范不是强制性的标准,但是如果你能尽可能遵守相同的规范,就会让工作更简单、更高效。
需要特别强调的是,认为写好代码只有一种方法是愚蠢的。虽然编码规范的指导原则是通用的,但是其中的具体细节则依赖于具体的环境,因具体的需求而变化。所以,除了遵循编码规范外,你还要做好随时重审、调整编码规范的准备,保持编码规范的活力,跟得上实际情况的变化。
希望你根据自己的实际情况,不断完善、丰富上面的清单,使这份清单更直观、更容易遵循,保持长久的活力,让它更适合你自己。
## 一起来动手
正像我们讨论到的,不同的场景,检查清单也不一定相同。如果让你列一个你自己实际工作中需要的编码规范检查清单,会是什么样子的? 你可以在我上面的清单上加减检查点,或者新做一个列表。欢迎在留言区公布你的检查清单,我们一起来讨论、学习。
另外,推荐一本书《清单革命》。清单能够起到的作用,常常被忽视。这本书告诉我们清单这个小东西,能给我们的工作带来多么巨大的帮助。
如果你觉得这篇文章有所帮助,欢迎点击“请朋友读”,把它分享给你的朋友或者同事。