电影《飞驰人生》中有这样一句打油诗
一顿操作猛如虎,定睛一看原地杵。
当时我看到这里,不禁笑出眼泪来,这些年来,看过多少程序员在开发中,忙着下断点,一遍又一遍运行程序,东改一句,西改一句,最终找到的却是如缺少赋值语句这种“二bi”原因,如此“暴力调试”,能找到问题都已是万幸,哪里还敢提什么工作效率,真是“你不加班谁加班”。
《飞驰人生》反映出技术工作中的一些常识,坏消息是:只要是技术性工作,复杂是其天然的属性,谁都不可避免;而好消息是:只要掌握规律,总结经验,你可以在这个领域成为顶尖高手。
为什么要用结构化方法
修复bug中,80%时间都花费在找出问题的原因上,用户(或测试人员)反馈的问题常常没有关键步骤,如“输入用户名后崩溃”,连输入的是中文还是英文都不带描述的;大型项目中,出问题的代码可能都不是你写的,这时找一个bug不单工作量巨大,甚至如进入一片荆棘丛林中,时不时地迷了路,原地打转,浪费时间,解决不了问题。因此,需要有一套流程,帮助开发者看清方向,甚至能帮助你重绘地图。
结构化调试能从两个维度提高你的工作效率:
- 减少时间
- 减少工作量
结构化调试法是什么
结构化调试是指在分析解决问题时,以一定的规则、流程顺序进行,首先以假设为出发点,对问题进行正确的判定,假设并罗列问题构成的要素,其次对要素进行合理分类,排除非关键问题,对重点原因进行分析,寻找出针对根本原因的修复方法。
结构化调试法概念看起来有些抽象,其实对开发者来说并不陌生,可能你一直在用它,只不过你并没有意识到而已。
比如说,你出门时,发现找不到钥匙了。这个时候,“钥匙在哪里”就是你要解决的问题。你会从分析钥匙的来源、丢钥匙的可能时间、地点、丢钥匙的影响等等各种因素中,列出各种可能的解决方案再开始找钥匙吗?当然不会,相反,你一定是先找出自己昨天穿的衣服,在口袋里摸一摸,如果有,那问题就解决了,你就拿好钥匙出门。如果没有,再找找最可能有钥匙的地方在哪里,比如是不是在书房抽屉里。
也就是说,你先假设钥匙在哪,再去验证有没有,按找钥匙这个方法,修复bug的过程是这样的:
找钥匙的方法
如果你已能有意识地这样去找bug,说明你已经是有经验的开发者了,但这还不够,如果漫无目的的提出各种假设,验证的过程将枯燥漫长,还有可能顾此失彼,本文接下来将进一步细化这个流程,通过一些实例,给出在各个步骤中需要做的具体工作,防止在调试过程中出现“只见树木不见森林”的情况,并列出一些常见的调试误区。
完整的结构化调试过程
结构化调试法分解问题
实际调试时,由于最初的问题都过于模糊,无法提出可验证的假设,我们需要拆解最初问题,将问题分为几个子问题。
分解问题要遵循两个原则:
1. 相互独立:
独立原则要求在分析问题时,列出的各个子问题互不包含,各自代表系统的一个切面。
2. 穷尽大问题:
这条原则要求,各个子问题综合起来,能代表大问题,若子问题有解,则大问题就有解。
这时要注意,穷尽问题必须以最初问题为导向,用“二分法”从结果倒推,
以“输入用户名后崩溃”这个总问题为例:
网友评论