调试代码是一种乐趣

近来连续调试了好几天的代码,乐趣无穷,:),在纯净的人和机器对话的时间中,充分的和机器不断的交流,最终共同实现功能,和同事说:“我喜爱调试代码胜过了写代码”,怎么说呢,我觉得调试代码能够充分让你将所掌握的知识发挥出来,考察自己解决问题的能力以及学习知识的能力,在这篇blog中来闲聊下调试代码。
调试代码是一种编码所需的基本能力,相信没有多少人写出来的代码能够是没有bug的,虽然传闻是有过这样的人,因此普通的我们只能通过调试代码来查找和修复代码中的问题,需要调试代码的场景有很多种,在这些场景中,也会有很多种不同的调试技巧可采用。
最典型的需要调试代码的场景是单元测试的场景,在单元测试时会碰到代码的执行不符合预期或抛出意料外的异常,在碰到抛出意料外的异常时,通常现在的高级语言都会提示是由于哪行代码造成的异常,于是首先的做法都是去看看对应的那行代码是什么个状况,然后评估大概是什么原因造成的,如果在这种推测情况下无法判断问题在哪了的话,在没有支持程序调试时,通常只能是在原始代码中输出一堆的信息到console,例如java中就是System.out.println或System.out.err,于是运行,看看console中一堆的信息,然后慢慢的来推测问题,当然,这也是一种可选的方案,甚至在某些场景中是一种不错的方案,但在各种IDE支持程序调试后,更多的时候调试都可以通过IDE来进行,发明这个的人真的太伟大了,虽然我不知道是谁,但是还是想膜拜下的,:),有些看似很小的功能,往往非常的重要,于是现在的我们可以幸福的设个断点,然后开始逐行跟踪、跳行跟踪、跟踪进入函数内部、跳出函数、跟踪变量甚至修改变量等等N多种的方式幸福的调试着代码,看着代码在运行时的状态,很容易的就让我们发现代码中的问题,这个绝对是节省了非常非常多的时间,所以我说我很佩服那些号称用记事本写代码的高手们,难道他们的代码都是零bug的?要么就是出了bug后也可以一眼判定问题所在的?那实在太强了点,对于这样的高手,确实可以不需要IDE这种现代化的武器,对于我而言,用记事本写就像停留在原始时代,而IDE差不多应该到帝王时代了,:),开玩笑,调侃下用记事本写代码的高手而言,这是单元测试中的场景和通常采用的技巧。
还有需要调试的场景通常会是集成测试场景,通常,集成测试会复杂很多,于是要用到的调试技巧会复杂一些,就像下面这样的两种场景:
1、并发程序
   并发程序向来就是最最复杂的,没有人能知道在运行时到底是怎么个执行顺序,否则就不叫并发了,:),于是,在并发程序中,N多种人脑无法想象的复杂场景就出现了,毕竟人脑的思考应该不支持并发的吧,至少我的貌似支持不了,也许是我笨,呵呵,而且通常并发程序中的错误是不一定能每次都重现的,这是最麻烦的,至于借助IDE调试,同样是不行的,因为并发程序由于断点的进入可能完全被打乱,于是,对于并发程序,通常能采用的方法,比较靠谱的方法,我觉得还是打日志,当然,你可以选择继续System.out.println、System.out.err,或者采用更加高级和优雅点的log.debug这样的方法,然后就看着时间戳来慢慢的运用自己的大脑来思考复杂的并发的问题,:),这绝对是一种挑战,但因此也会带来充分的乐趣,于是慢慢的享受这个过程吧。
   多说一句,还好现在java有了更高精度的时间戳:System.nanoTime,用System.currentTimeInMills根本就没法分析并发程序,因为它的精度不够。 
2、所依赖的程序有问题
   这种场景嘛,相对而言就复杂很多了,因为通常这个时候能做的多数是通知所依赖的程序方去查找问题,但如果手头有所依赖的程序的代码的话,多数可以采取跟入其源码的方式,尽管不一定能修复其源码,但对于查找出问题还是会提供很大的帮助,例如跟踪框架代码、jdk代码等等,对于访问的远程程序而言,则不太相同,java嘛,还好,可以支持远程调试,我相信现在的大部分语言都支持的,远程调试那是相当的重要呀,于是我们就可以在本地调试着远程某台服务器上执行时的bug,:),偷着乐吧。
最后一种最痛苦的大家最想调试的场景,就莫过于生产环境了,估计有N多人都想直接在生产环境中调试,看看生产环境中的问题是怎么产生的,但生产环境嘛,是不太可能拿来调试玩的,而有些时候线下要模拟也不是什么简单的事,说到这,又要天马行空的瞎扯下了,记得在云风的blog上以前有写过一篇游戏中对于出错场景的记录以及回放的功能,这功能听着是相当的帅呀,好,继续回到正题,在自己的代码还没有如此强大的错误记录和回放功能时,也许能做的选择就是在代码中多写一点log.debug了,在生产环境有问题时,则打开相应的日志的debug项,然后继续靠人肉分析了,这个时候还是体现了log.debug的强大作用滴,根据这点可以看出,在代码中还是有必要写些合适的log.debug的,除了为了自己外,对于其他使用的人调试bug也是可以給予很大的帮助的。

嗯,没想到稍微扯了下,也写了不少,从这稍微写的内容中,其实也能看出,调试可不是闹着玩的事,绝对需要相当完整的知识体系,这也难怪张银奎的《软件调试》写了三年,而且那么的厚,看来还是值得看看的,:),小广告,大家别在意。
而且这里还没说到,通常需要调试的时候,多数都是出问题的时候,那么这个时候还会面临很大的压力,怎么样在紧急的时间内还冷静的做好人肉分析的工作,这可是相当的考验抗压能力、技术基本功、逻辑分析能力和学习能力的过程,想想,要能在短时间内查出问题的原因,通常需要对代码运行的场景做出冷静的分析,进而需要具备从头到尾的知识,例如所采用的框架、java包、甚至到JVM、操作系统、硬件,实在不行的话,还得临时学习下这些知识,这样才能在短时间内解决,因此想来想去,越来越觉得如果在面试的时候让面试者现场调试段程序貌似还是挺靠谱的,更有助于全方位的考察,貌似只有很少数的几家公司会这么干,当然,这有客观条件的原因,但要克服貌似也不是很难。

posted on 2008-11-18 23:49 BlueDavy 阅读(6146) 评论(4)  编辑  收藏 所属分类: Java

评论

# re: 调试代码是一种乐趣 2008-11-19 01:44 Oasis Feng

如果是调试写的比较烂的代码,那恐怕就很难体会到乐趣了。只有编码中充分考虑了调试需求,并且对执行期异常有高度前瞻性的日志才能创造一种充满乐趣的代码调试体验。

关于并发,我尽量不在自己写的代码中引入过多需要考虑并发的处理和机制,理想的情况是让基础库或编程框架为你代劳那些并发需要周全考虑的事情。

程序依赖的问题其实还是涉及到编码中的一条准则:模块边界的不信任原则,尤其针对协作开发。无论是集成测试和是运行期检查,只有以这个原则出发完善必要的调试辅助工作,才有助于快速准确的定位问题的直接源头。  回复  更多评论   

# re: 调试代码是一种乐趣 2008-11-24 11:43 brokendoor

看来 BlueDavy 同学最近的生活悠闲了,开始发掘生活和工作中细微之处的乐趣。

帮着闲扯几句:
并发是这世界的本源,人脑也是并发的,机器比较笨,让人脑模拟机器的笨并发,自然是没办法了。

所以,还是要靠人脑Debug,而不是机器。  回复  更多评论   

# re: 调试代码是一种乐趣[未登录] 2008-12-18 17:52 null

用记事本也需要debug的,没听说过jdb???  回复  更多评论   

# re: 调试代码是一种乐趣 2008-12-22 20:45 zhuxin

因为所做课题的关系看了你写的大作《OSGi实践》,并跟踪到了你的博客,看了你的很多文章,感觉你知识面很广,特别有奉献精神。非常感谢你的分享和付出。
你的好几篇文章,都很有趣,让人觉得你很年轻,也让我对以后的工作有了更多的期待~  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

公告

 









feedsky
抓虾
google reader
鲜果

导航

<2008年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

统计

随笔分类

随笔档案

文章档案

Blogger's

搜索

最新评论

阅读排行榜

评论排行榜