(点击
www.cnblogs.com/lovesqcc/p/9271781.html
路线图
常见代码问题
常见的潜在代码问题是其时直接会导致BUG、毛病或许产品功用不能正常作业的类别。
空值
空值恐怕是最简单呈现的当地之一。 常见过错有: a. 值为NULL导致空指针反常; b. 参数字符串含有前导或后缀空格没有Trim导致查询为空。 导致以上成果的原因首要有: 无此记载、有此记载但因为SQL拜访反常而没查到、网络调用失利、记载中有脏数据、参数没传。
准则上,关于任何反常, 希望能够打印出详细的过错信息,依据过错信息很快了解是什么原因, 而不是一个 null ,还要在代码里去琢磨为什么为空。这样咱们有必要识别出程序中或许的null, 并及时检测、捕获和抛出反常。
关于空值,最好的防护是“防护式编程”。当获取到目标之后, 运用之前总是判别是否为空,并恰当抛出反常、打过错日志或做其它处理。 有的人嫌检测为空的 if 句子充满在代码里会损坏代码的可保护性, 对此我的主张是:
-
空值检测必定要有, 有胜于无。
-
在空值检测总是存在的前提下, 能够优化空值检测的办法和存在办法。 比方会集于一个类 NullChecker 中办理,并与体系的全体过错处理规划保持共同。会集办理和处理共同性准则能够作为体系规划的一个准则。 这样主流程中只需添加一行调用即可, 既能够天网恢恢疏而不漏地检测目标为空, 也不会让代码显得丑陋。
class NullChecker {
public static void checkNull(Object obj, Error error) {
if (obj == null) { throw new BizException(error); }
}
}
-
在参数入口处共同做 trim。 假如在事务逻辑里做 trim , 就会导致有的事务逻辑做了 trim , 有的没做, 表现在产品上就会有令用户困惑的作业发生。 比方查找和导出事务, 查找能查找出来, 导出却没有。
未捕获潜在的反常
第二个简单犯错的当地是未捕获潜在的反常。调用API接口、库函数或体系服务等,只顾着享用便当却不做防护,常导致因为部分失利而影响全体的功用。最好的防护依然是“防护式编程”。 要么在其时办法捕获反常并回来适宜的空值或空目标,要么抛给高层处理。
切不可静静”吞掉过错和反常”。 假如这样做了, 出问题了等着加班和消耗许多脑细胞吧!
在CodeReview的时分必定要细心问询:这儿是否或许会抛出反常?假如抛反常会怎样处理?是否会影响全体服务和回来成果?
低功用
低功用会导致产品功用不好用、不可用,乃至导致产品失利。
常见状况有:a. 循环地逐一调用单个接口获取数据或拜访数据库; b. 重复创立简直完全相同的(开支大的)目标;c. 数据库拜访、网络调用等服务未处理超时的状况; d. 多重循环关于大数据量处理的算法功用低;e. 许多字符串拼接时运用了String而非StringBuilder.
关于 a,最好供给批量接口或批量并发获取数据; 关于 b, 将可复用目标抽离出循环,一次创立屡次运用; 关于 c,设置合理的超时时刻并捕获超时反常处理; 关于 d,运用预排序或预处理, 结构适宜的数据结构, 使得算法均匀功用在 O(n) 或 O(nlogn) ; 关于 e, 记住: 少数字符串拼接运用String, 许多字符串拼接运用 StringBuilder, 一般不会运用到 StringBuffer.
影响规划过大
对多个模块依靠的公共函数的修正,简单构成影响规划超越其时事务改动,无意识地损坏依靠于该公共函数的其他事务。要特别稳重。牢靠的办法是:先检查该公共函数的调用, 假如只要自己的事务用,可恰当斗胆一些; 假如有多个当地依靠,抽离一个新的函数,抽离原函数里的可复用部分,然后依据可复用部分构建新的函数。修正准则遵从“开闭”准则,才干尽或许使改动影响降低到最小化。
基类及实例字段和办法也归于公共函数的领域。 尽量不要修正基类的东西。
单测问题
单测是确保工程质量的第一道重要防地。单测问题一般包含: a. 单测未悉数经过; b. 重要事务逻辑缺少单测; c. 缺少反常单测; d. 代码改变或BUG修正缺少单测。
单测悉数经过应当是提交代码到代码库以及代码Review的前提条件。代码提交者应当确保单测悉数经过。没有捷径可走。仅当单测悉数经过才提交到代码库, 能够经过东西主动化完成。 关于 maven 办理的工程, 只需一个指令: mvn test git push origin branch_name 。 单测应当更重视质,而非单纯寻求掩盖率。
缺少单测的重要事务逻辑就像裸露在空气中的电线相同,虽然能跑起来,却是很简单“触电”的。 办法: 添加掩盖比较全面的单测。
缺少反常单测也是代码提交者常疏忽的问题。 反常也是一种实践的事务场景,反映体系的健壮性和友好性。反常应该有相应的单元测验掩盖。创立条件使之抛出反常,并判别反常是否是指定反常;若没有抛出反常或许不是指定反常,则应该 AssertFailed 而不是经过。
关于代码改变和BUG修正,假如其时因为时刻紧而没有写,后续应当补上。关于每个代码改变和BUG,都能够抽离出相应的代码部分, 并有相应单测掩盖,并注明原因。
与原有事务逻辑不兼容
改动针对其时需求是合理的,却与原有事务逻辑不兼容,也是常见的问题。比方添加一个查找条件, 却不能与原有条件联合查询。
与原有事务不兼容, 一般呈现在:
-
1对1与一对多的改变。 比方本来的联系是一个订单对应一个物流信息, 后来改变为一个订单或许对应多个物流信息; 本来的逻辑是一个订单显现多个物流信息能够更改,后来要求一个订单只展现最近一次的物流信息能够修正。
-
事务逻辑的兼容问题一般表现在体系的复用性和可扩展机制上。杰出的体系可复用性和可扩展功用够更简单地做到事务逻辑兼容。 首要有如下几种等级:
-
主动兼容。 添加一种类型, 仅仅 biz_type 的值多了一种, 体系主动将已有功用适配给新的 biz_type;
-
一点改动。添加一个分支句子, 对 biz_type 的某个特性进行扩展;
-
一些改动。 需求见缝插针地添加一个独自的分支判别和逻辑处理模块, 对全体可扩展性没有影响, 但会构成部分的杂乱化;
-
一部分功用改动。 只需求对其间一个功用模块做个扩展;
-
-
难以改动。 需求深化到功用模块内部做困难的修正, 并要确保原有功用不受影响。
怎么应对呢?
-
针对相相关系, 在项目之初, 能够问询清楚: 将来在产品上是否有可扩展的改变? 及早预留空间, 或许确认产品上的对策; 在代码完成上, 统筹考虑1对1到一对多,或一对多到1对1的相关改变。比方运用列表来表达单个信息, 运用索引从列表中获取单个信息。
-
针对事务组合, 清晰各事务的中心部分, 抽离出事务的可复用的部分,构成 API ; 考虑组合形式和装修器形式来进行扩展。
中心不变, 外围定制化。
缺少必要日志
关于重要而要害的实例状况、代码途径及API调用,应当添加恰当的INFO日志;关于反常,应当捕获并添加Error日志。缺少日志并不会影响事务功用,但呈现问题排查时,就会十分不方便,乃至失去极名贵的时机(不易重现的状况特别如此)。此外,缺少日志也会导致可控性差,难以做数据计算和剖析。
过错码不契合标准
过错码自身不算是代码问题,不过依据整个安排和工程的可保护性来说,能够将过错码不契合标准作为一种过错加以防止。办法: 对过错码进行可控的办理和遵从标准运用。能够运用公共文档保护, 也能够开发过错码办理体系来防止相同的过错码。
参数检测缺少或缺少
参数检测是对事务处理的第一层重要过滤。假如参数检测缺少够,就会导致脏数据进入服务处理,轻则导致反常,重则刺进脏数据到数据库,对后续保护都会构成许多保护本钱。办法: 选用“契约式编程”,规则前置条件,并运用单测进行掩盖。
关于杂乱的事务运用, 高雅的参数检测处理尤为重要。 依据 “会集办理和处理共同性准则”, 能够树立一个 paramchecker 包, 规划一个可复用的微结构来对运用中所有的参数进行共同会集化检测。参数检测首要包含: (1) 参数的值类型, 能够依据不同值类型做根底的检测; (2) 参数的事务类型, 有根底非事务参数, 根底事务参数和详细事务参数。 不同的参数事务类型有不同的处理。 将参数值类型与参数事务类型结合起来, 结合共同性的反常捕获处理, 就能够完成一个可复用的参数检测结构。参数检测既能够选用一般的分支句子,也能够选用注解办法。选用注解办法更可读,不过单测编写更具技巧。
引证过错
关于动态言语, 因为缺少强壮的静态代码检测,修正了类引证的当地特别要注意,很或许导致依靠的其他事务犯错; 特别是修正重名引证时。有线上毛病经验。PHP工程中含有两个 Format 类, 一个根底的一个事务相关的, 被改动的类文件里开端没有指明引证,默许选用了根底 Format 类的完成, 然后提交者在改动文件头添加了对事务 Format 的引证, 导致依靠于根底Format类的其他事务不能正常作业。防止引证过错的办法: 当要在文件里添加新的类引证时, 先在文件里查找是否有重名类的引证。假如有, 就要分外当心了。
细节过错
比方数组越界、JSON解析犯错、函数参数传递犯错、API 版别不对、运用网上复制的未经测验的代码、不成熟的算法、传值与传引证、持平性比较等。
关于数组越界过错, 一般要对空数组、针对数组巨细的鸿沟值+1和-1写单测来防止; 运用网上复制的代码,固然可节省时刻,也必定要加工一下并用单测掩盖; 传值和传引证可经过单测来防止过错; 目标的持平性比较切忌运用等号=。
多重条件
相似 if ((!A || !B) C || (D E)) 的多重条件要细心琢磨。办法: 最好拆分红多个有意义变量。 isNotDelay = !A || !B ; isNormal = C ; isAllow = D E ; cond = isNotDelay isNormal || isAllow 。
文不符实
文不符实是一种或许导致线上毛病的过错。比方一个 getXXX 的函数,成果里边还做了 add, update 的操作。对问题排查、产品运维等都有十分大的杀伤力。因而命名必定要用本质内容相符,除非是成心搞损坏。
跨言语或跨体系交互
稍具规划的互联网创业公司一般会选用多言语开发,比方PHP作为前端,Java作为后台服务。当动态类型言语与静态类型言语交互时,会有一些问题发生。比方PHP的目标一般是一个Map, 假如是空目标就会写成 [], 但是 [] 会被 Java 解析成列表。这样, 假如数据库的值是经过 PHP 写入,那么这个值既有或许是JSON目标字符串,也或许是空数组字符串, Java 来解析就有点为难了。 相同,当 Java 调用 PHP 接口时, 不标准的PHP接口既或许回来列表,也或许回来 true or false , Java 解析回来成果也会比较为难。 因而, 在跨言语交互的鸿沟处,要特别注意这些类型转化的差异。
跨体系交互则首要是接口规划与约好的问题。同一个项目里不同事务团队之间的事务接口规划与约好, 不同企业里敞开接口的规划与约好, 要在开始深思熟虑,一旦敞开,在后期很少有接口规划改动的空间。敞开接口规划要契合小而美、正交的特性, 命名要恰当共同, 参数取值要指明束缚,枚举参数要给出列表, 成果回来要标准共同,能够选用通用的 {“code”:200, “msg”: “success”, “data”: xxx} 。跨体系交互也要共同对术语和接口的了解的共同。
① 留言格局:
【投稿】+《 文章标题》+ 文章链接
② 示例:
【投稿】《不要自称是程序员,我十多年的 IT 职场总结》:http://blog.jobbole.com/94148/
③ 最终请附上您的个人简介哈~