魔鬼在细节中

最近一直担忧Dubbo分布式服务框架后续若是维护人员增多或变动,会出现质量的降低,
我在想,有没有什么是须要你们共同遵照的,
根据平时写代码时的一习惯,总结了一下在写代码过程当中,尤为是框架代码,要时刻牢记的细节,
可能下面要讲的这些,你们都会以为很简单,很基础,但要作到时刻牢记,
在每一行代码中都考虑这些因素,是须要很大耐心的,
你们常常说,魔鬼在细节中,确实如此。

1. 防止空指针和下标越界
这是我最不喜欢看到的异常,尤为在核心框架中,我更愿看到信息详细的参数不合法异常,
这也是一个健状的程序开发人员,在写每一行代码都应在潜意识中防止的异常,
基本上要能确保一次写完的代码,在不测试的状况,都不会出现这两个异常才算合格。

2. 保证线程安全性和可见性
对于框架的开发人员,对线程安全性和可见性的深刻理解是最基本的要求,
须要开发人员,在写每一行代码时都应在潜意识中确保其正确性,
由于这种代码,在小并发下作功能测试时,会显得很正常,
但在高并发下就会出现莫明其妙的问题,并且场景很难重现,极难排查。

3. 尽早失败和前置断言
尽早失败也应该成为潜意识,在有传入参数和状态变化时,均在入口处所有断言,
一个不合法的值和状态,在第一时间就应报错,而不是等到要用时才报错,
由于等到要用时,可能前面已经修改其它相关状态,而在程序中不多有人去处理回滚逻辑,
这样报错后,其实内部状态可能已经混乱,极易在一个隐蔽分支上引起程序不可恢复。

4. 分离可靠操做和不可靠操做
这里的可靠是狭义的指是否会抛出异常或引发状态不一致,
好比,写入一个线程安全的Map,能够认为是可靠的,
而写入数据库等,能够认为是不可靠的,
开发人员必须在写每一行代码时,都注意它的可靠性与否,
在代码中尽可能划分开,并对失败作异常处理,
并为容错,自我保护,自动恢复或切换等补偿逻辑提供清晰的切入点,
保证后续增长的代码不至于放错位置,而致使原先的容错处理陷入混乱。

5. 异常防护,但不忽略异常
这里讲的异常防护,指的是对非必须途径上的代码进行最大限度的容忍,
包括程序上的BUG,好比:获取程序的版本号,会经过扫描Manifest和jar包名称抓取版本号,
这个逻辑是辅助性的,但代码却很多,初步测试也没啥问题,
但应该在整个getVersion()中加上一个全函数的try-catch打印错误日志,并返回基本版本,
由于getVersion()可能存在未知特定场景异常,或被其余的开发人员误修改逻辑(但通常人员不会去掉try-catch),
而若是它抛出异常会致使主流程异常,这是咱们不但愿看到的,
但这里要控制个度,不要随意try-catch,更不要无声无息的吃掉异常。

6. 缩小可变域和尽可能final
若是一个类能够成为不变类(Immutable Class),就优先将它设计成不变类,
不变类有自然的并发共享优点,减小同步或复制,并且能够有效帮忙分析线程安全的范围,
就算是可变类,对于从构造函数传入的引用,在类中持有时,最好将字段final,以避免被中途误修改引用,
不要觉得这个字段是私有的,这个类的代码都是我本身写的,不会出现对这个字段的从新赋值,
要考虑的一个因素是,这个代码可能被其余人修改,他不知道你的这个弱约定,final就是一个不变契约。

7. 下降修改时的误解性,不埋雷
前面不停的提到代码被其余人修改,这也开发人员要随时紧记的,
这个其余人包括将来的本身,你要总想着这个代码可能会有人去改它,
我应该给修改的人一点什么提示,让他知道我如今的设计意图,
而不要在程序里面加潜规则,或埋一些容易忽视的雷,
好比:你用null表示不可用,size等于0表示黑名单,
这就是一个雷,下一个修改者,包括你本身,都不会记得有这样的约定,
可能后面为了改某个其它BUG,不当心改到了这里,直接引爆故障。
对于这个例子,一个原则就是永远不要区分null引用和empty值。

8. 提升代码的可测性 这里的可测性主要指Mock的容易程度,和测试的隔离性, 至于测试的自动性,可重复性,非偶然性,无序性,完备性(全覆盖),轻量性(可快速执行), 通常开发人员,加上JUnit等工具的辅助基本都能作到,也能理解它的好处,只是工做量问题, 这里要特别强调的是测试用例的单一性(只测目标类自己)和隔离性(不传染失败), 如今的测试代码,过于强调完备性,大量重复交叉测试, 看起来没啥坏处,但测试代码越多,维护代价越高, 常常出现的问题是,修改一行代码或加一个判断条件,引发100多个测试用例不经过, 时间一紧,谁有这个闲功夫去改这么多形态万千的测试用例? 长此以往,这个测试代码就已经不能真实反应代码如今的情况,不少时候会被迫绕过, 最好的状况是,修改一行代码,有且只有一行测试代码不经过, 若是修改了代码而测试用例还能经过,那也不行,表示测试没有覆盖到, 另外,可Mock性是隔离的基础,把间接依赖的逻辑屏蔽掉, 可Mock性的一个最大的杀手就是静态方法,尽可能少用。
相关文章
相关标签/搜索