程序员突围-程序调试分析(一)
我从菜鸟进化的感悟
在说程序调试分析之前,我们还是了解一些基本的概念性的东西(在下现在从事java,因而都已java为例)
1. bug的分类
根据程序的阶段和MSDN和看过的一些书籍的分析,bug分为编译错误,运行时错误和逻辑的错误
(1) 编译错误
一般初学者犯错比较多的地方,编译错误,说白了就是程序在从java编译成.class文件时出现了问题,这个问题的现象比较明显,比如说语句写的有问题,那么对于这类问题的解决方法是什么呢,翻翻书,翻翻API(翻阅API和源码是很重要的一种能力哦)关于这方便的讲解,也就可以解决了.
(2) 运行时错误
运行时错误,就是程序在有.class文件加载到内存之后,开始运行时出现了问题,比如说,空指针异常,类转换异常,方法不存在,类找不到等等,关于这类问题的解决方法呢,这个是需要分类的,比如说采用的是框架级别,比如说公司内部框架或者第三方框架,对于这类呢,我只能说你问问公司的大牛,上网百度百度,能够搜索出来的问题都是小问题,在此呢,推荐一个比较好的国外技术网站,stackoverflow,相当专业的技术网站,,对于非框架级别,自己写的程序呢,看看日志或者控制台打印的错误的地方,一般在附近都能找到答案的,一眼看不到的呢,在报错位置的附近设置断点,看看相关联的几个变量的值
(3) 逻辑错误
什么叫逻辑错误呢,简单的说就是代码没有按照我们想要的流程往下走,现象嘛,代码编译没有问题,运行也没有问题,但是就是得不到想要的结果,经常听到别人说这样的几句话,为什么我的代码执行不到这里,为什么我的参数放进去了去不出来,为什么我修改了数据库后,数据库没有变化.
这类问题的解决方法是什么呢,先听听我下面分享的东东,大家也许就有点感悟了
2. 调试的原则
(1) 核心原则:了解需求
大家总是在听别人说,你帮我看看我这里哪里出了问题了,对于简单的demo类型,一般看看就知道是哪里出了问题,但是是复杂的问题呢,你能够在什么都不了解的情况下,直接帮别人解决bug吗,除非这些底层或者什么东西你就了然于心,我觉得在多数的情况下,我们还是要了解业务场景的,也就是这个方面的需求,需求,包括业务需求和书写代码此方法甚至此类的要实现的需求,有可能我们不需要知道业务需求,只需要知道此编码级别的需求即可,这个其实是要知道我们的业务数据流程和代码实际流程的真实走向.
(2) 核心原则: 对bug进行定位,也就是缩小排除无关代码
对于简单的bug,大家可能都知道,直接在附近debug一下就可以了,看看相关的变量,这个确实是个很通用的方法,但是对于一个大的功能模块甚至整个系统的bug呢,能够一眼看到bug吗,这就像是大海捞针一样,但是怎么能够在大海中捞针呢?运用核心原则1,我们了解需求后,我们大概对问题进行定位,就是讲业务数据流程和代码流程的整体流程中,撕开了一个口子,也就是确定了上边界和下边界的问题.
(3) 不能相信他说的此处没问题
在工作和学习中,总是能够遇到他人说这样的问题,他向你描述了一个bug的现象(完成了我们的原则1),但是他向你描述的时候,很多时候会说道这样一句话,我明明按照他的说法做了,但是就是没有出现预期的结果
此处呢,我们能相信的是什么,那就是他说的结果,什么呢,没有出现他想要的结果,那他说的前提条件可信吗,此处99%是不可信的,为什么不是完全不可信的呢,我们不可否认采用的框架中可能会有bug.为了避免我们给我们做一个错误的前提提交,我们需要将不可信的条件转为可信的条件,如何转换呢,此处可以直接采取debug的形式,在其说的没问题的地方的最后,我们设置断点,查看是否是预期的结果,如果不是的话,那么说明前提条件都是错误的,根据实际的个人经验,一般都是前提条件有问题的
3. bug的调试技巧
Bug调试技巧是要分类的,先说一下通用的,然后在将通用的进行具体实现和操作
(1) debug
debug模式大家肯定是要学习的,在程序学习的初期,大家不仅要学习如何写代码,更要学习如何debug,就是让程序停止到一个断点,不再往下进行,我们可以选择让程序一步一步执行,还是全部执行,在执行的过程中,我们还能看到相关变量的值和其变化
(2) 橡皮鸭调试法/泰迪熊调试法
这个方法也是比较常用的,其实大家平时就用过这种方式,就是在你向别人描述问题的时候,你突然就发现了问题,只不过大家没有重视这种方式而已,由于大家用的时候一般是与他人沟通,其实与他人沟通,面临一个他人是否在忙的状态,其实呢,我们是否和人沟通是不重要好的,我们是向把我们的逻辑说一遍,所以呢,我们可以选择和旁边的宠物先说一遍,具体做法呢,当你在想这只保持沉默的橡皮鸭/泰迪熊解释的过程中,你就发现你的想法,观点,思路和实际的代码偏离了,于是你就找到了代码中的bug.
一旦一个问题呗充分的描述了他的细节,那么解决方法也是显而易见的,或许你觉得这个方法太愚蠢,太弱智,但是这个是非常有效的一个方法,号称这个是Code Reviev的雏形
(3) java的debug
在说java的debug之前,大家可以对debug有一个基本的了解,debug模式,我们想看的是什么呢?数据的变化,程序的走向,数据的变化体现在哪些地方呢?就是在变量的窗口中,程序的走向呢?无非我们想控制程序是走一步,还是走多步,,走到指定的位置,以及是否进入方法中,这也就衍生出了不同的程序debug的通用模式,单步调试(单步调试分为单步调试进入方法内部,单步调试不进入方法内部),一直执行到下一个断点
Java的debug也不例外,大家可以看看相关debug的快捷键,自己写个例子,试试这种方式
要注意的是,由于java是可以多线程运行的,所以我们也可以看到多个线程同时处于debug,于是我们可以选择在哪个线程进行操作
(4) js的debug
通用在(3)中所描述的debug的一般特点,js中的debug也逃脱不了这几点,只不过快捷键不同,其实在java中经常写的system.out什么的方法在js中我们也可以alert一下,但是这种方式不建议使用,因为这样会破坏程序原来的结构
Js中有比较好用的工具是firebug,由于个人用chrome用习惯了,firebug没怎么用过,就不在这卖弄了.大家可以看看,听说是调试js的利器
(5) html的debug
大家可能要嘲笑我了,html怎么debug呢,我目前用的比较多的方法是给标签增加样式,常用的是增加边框或者背景色,由于个人使用的也不多,html的debug就介绍这么多,大家有好的方式方法请回复我,share and change!
4. 避免bug
(1) 一个方法内只做基本的操作,不做过于复杂的逻辑控制,一般一个方法的代码不超过一个屏幕的宽度,一个方法内部的代码量越大,越容易出现逻辑错误,并且方法内代码量过多,书写此方法也会浪费很多的时间
(2) 编码测试
很多人喜欢写一个大的模块之后进行测试,其实在写好一个比较关键的方法后,我们就应该测试一下,使用junit,我们可以在不破坏程序的基础上,就可以书写测试逻辑
5. 解决思路
因为bug的情况不同,我们的解决思路也是不同的,
在bug的分类中已经说到了一些bug的解决思路,这里再说一些其他的思路
(1) 控制台/日志确定bug的现象,如果日志或者控制台没有出现内容,那么这也是现象
(2) 根据现象,再根据业务需求/程序需求,有异常抛出,直接找到异常抛出的问题,对于能够看懂的异常,或者已经熟悉的异常,一般很快就能解决,对于不熟悉的异常,如果是简单的异常,那么自己找到bug的附近,梳理梳理逻辑,自己给自己讲讲这块的逻辑,试试能不能找到;如果梳理后不能找到,开启debug模式;对于仍然找不到的逻辑,如果是框架类的直接看官方文档或者搜索或者问大牛
总结:
程序调试分析的顶级核心是心态要好,心态不好的人,找问题思路是堵塞的,如果找不出来,记得出去溜达溜达,其实很多时候问题并不是在你坐在电脑前面拼命找到的bug,而是你出去溜达的时候,答案已经在你的心中(至于原因,可以看看<程序员的思维训练>)
程序员突围-程序调试分析(一) 我从菜鸟进化的感悟,布布扣,bubuko.com