2.4 变量与函数
变量与函数是一个程序中核心的部分,过于复杂的函数会导致代码阅读性的下降,因此,我们需要尽可能的复用经常使用的函数,对过于复杂的函数进行拆分,来提高代码的可读性以及稳定性。
变量
强制:当变量表示选项时,必须使用枚举替代
在Java开发中,我们通常使用int常量来表示枚举的选项,这会降低整个代码的可读性,因此,需要使用枚举来进行替换。
// 不能使用int来表示性别
× int sex;
// 使用枚举来表示性别
Sex sex;
例外:在序列化的场景中,由于工具库的限制,往往不能直接使用枚举来进行序列化,因此,可以使用int来代替枚举,但是在使用该数据类型时,必须先转换成支持枚举的数据类型。
禁止:传递参数或者返回时使用字面量
在传递参数或者返回时,如果需要一个定值,应当使用常量或者枚举来进行替代,禁止在传递参数或者返回时使用字面量。这很容易导致代码发生更改时遗漏,从而导致代码的异常,且在重构时也不容易进行追踪。
这种字面量我们通常称之为魔法值,这种存在会极大的破坏代码的完整性,应当在实际项目中禁止。
常量与枚举
常量一般用于存储配置项的内容,或者事先约定的特殊值。在项目中,一般用常量表示服务器的路径、端口、颜色以及长度等。
禁止:使用常量类存储常量
使用常量类(Constant)来统一存储常量,是经常使用的一种习惯。然而,将常量与实际的代码剥离,是一种不合理的事情,因为常量仅仅用于存储不变的量而已,常量类也没有具体的业务逻辑。
dart是可以支持顶层变量与函数的,因此,我们不需要单独创建一个常量类来进行表示。
我们需要根据实际的逻辑来确定常量存储的位置:
- 配置项的内容存储在以
Config结尾的类中。(比如服务器地址、开发模式等) - 和主题、格式或者样式的常量存储在主题有关的类中。
- 和选项有关的常量,使用枚举来进行代替。
尽量保持常量与具体的功能模块结合,避免使用单独的常量类存储常量。这容易导致代码修改或者重构时涉及多个文件的内容。
函数
强制:当条件表达式的判断项超过(包含)3时,或者存在复合式时,需要提取成一个单独的函数
当一个条件表达式过于长时,会严重降低其可读性,同时,随着代码的迭代,这个部分会更加的难以维护,因此,我们需要将其提取成一个单独的函数,来提高代码的阅读性。
推荐:使用短路的逻辑,来代替多分支的判断
多分支的判断往往只有一个会包含核心的逻辑,其他的往往是判断条件或者检查的逻辑,推荐将核心的代码放在最后,并在之前提前使用return来结束整个函数。
同时,如果确实存在多分支的业务逻辑时,推荐使用策略模式来进行拆分,尽量不要在一个函数中包含多种逻辑的代码。
推荐:一个函数只有能一个输出点
一个函数的输出应当是单一的,我们不能即返回值,又去修改参数,这会降低代码的可读性。
- 若函数返回非void,那么在函数内部不能修改参数。
- 若函数返回void,你只能修改函数第一个变量的参数。
推荐:不涉及变更的函数保持幂等
当一个函数不涉及变更时,应当保持函数的幂等性,即多次调用该函数时,函数的输出或者结果应当与调用一次该函数时保持一致。
强制:条件表达式后续的语句块必须使用{}
例外:当条件表示式只有if的分支,并且后续的语句块可以写在同一行时,不需要使用{}
错误与异常
强制:使用Error表示错误,使用Exception表示异常
在dart中,我们通常使用Error表示错误,即程序集异常,当出现该类错误时,往往表示代码存在错误,需要及时修正。而Exception通常表示运行时异常,表示意料之外的情况发生。异常可以减少很多判断的逻辑,让一个函数可以将更多代码注重于业务点,因此,如何合理的使用异常来进行处理也是非常有必要的。
禁止:尝试捕获Error或者任何子类
Error指程序类错误,这种情况下往往是代码编写不规范导致的,我们不能捕获这类异常,而是要进行及时的修复,捕获这类异常容易导致程序无法按照预期运行,并可能导致更多错误的发生。
强制:使用on来捕获特定的异常
捕获特定的异常缩小了异常处理的范围,当其他的异常或者错误发生时,可以及时的检查出异常,并对此进行更正。
例外:当需要使用异常捕获机制来捕获应用的异常,方便后续的维护时,可以捕获所有的异常并将其上报。
强制:当捕获的异常需要重新抛出时,使用rethrow语句
使用rethrow语句可以保存最新的堆栈,方便后续的排查和追踪。