** 写在前面 **
本文论述了软件开发中关于 Release 模式和 Debug 下如何调试跟踪程序的原则和方法,以及才有作者所叙述的方法对软件开发流程的影响,随后作者给出了在 C# 中的具体实现。
** 入门简介 ** ** **
VS.Net 提供了两种机制来帮助开发人员诊断和纠正程序中的错误 . 一个是 debug 类 , 另一个是 trace 类 . 这两个类都有了一个 assert 函数 . Assert 在很多 情况下 可以用来检验变量 ** , ** 比如检验一个指针在调用了某一个系统的 API 之后是不是为空。即使是使用 try-catch 块,我们也要面对下面两种情况,其一是我们要抓取系统的 API 抛出的异常,但是我们无法简单的得到 API 失败时的返回值,我们只好来处理“异常 ” ,,这会使编程变得复杂 . 其二,我们往往要生成两个版本-测试版和发布版,这也使开发变得复杂。
如果你是一个从来没有使用过 assert 和 trace 的程序员 , 你大可以读到这儿为止了 , 因为下面我要讲的东西可能没有一点会减轻你编程工作的强度 , 也不会减少开发费用 , 也不能给你正在测试的程序一些好的建议 .
** 这是我在实际开发中亲身经历的一个例子 ** ** **
好几年以前 , 我还是一个多线路视频监视系统的开发组长 , 我们的视频系统可以通过 RS-232 线接收多达 64 个摄像机 . 这些摄像机直接或者通过专线或者通过拨号连接到视频系统上来 . 这是一个复杂的系统,我在这儿就不多说了。
** 实现跟踪的手段之一 ** ** : ** ** 跟踪日志 ** ** (Trace logs) **
在每一个项目的开始 , 我们通常要记录下面的事情 :
1. 所有与 GUI 有关的事件 : 选择菜单 , 选择按钮等等 .
2. 所有内部的消息 ( 我们使用消息体系来调用没有个功能的实现 )
3. 所有状态的变化 .
_ _
对于上面的实现方法 , 我们输出一个调试日志来报告与消息相关的事件 , 消息和当前的状态 .
** 实现跟踪的手段之二 ** ** : ** ** 断言 ** ** (assert) **
我们也才有用 assert 来检验所有函数的参数和他们的返回值 . 当触发一个 assert 的时候 , 我们会把与这个相关的信息写的调试日志中 . 这时候 , 就会关闭调试日志 , 显示一个错误信息 , 并且中止程序的运行 .
** 不配合的质量评估人员 ** ** **
在开发过程中 , 质量评估部门会测试不同的模块 . 最初 , 我们与质量评估部门的关系是敌对的 , 我们使用了先前的调试手段 , 而我们却发现 , 质量评估部门正好测试到我们不让他们那么实现的情况 ( 他们只想引起管理层的注意 ). 当我们纠正了各种不同的观念之后 , 质量评估部门的工作开始作的非常好 . 有一个问题 , 对于任何测试人员 , 当你问他具体作了些什么 , 他们会非常安心的对你说 , 我点击了 X, 然后是 Y, 接下去是 Z. 而事实上 , 他们点击的是 A,B,C. 有了我们上面对于 GUI 的实现手段 , 我们没有必要去问测试人员他们作了些什么 , 我们自己完全可以从日志文件中看的出来 .
** 实地测试( ** ** Field Testing ** ** ) ** ** **
因为内部测试与实际使用有很大的出入 , 我们会选择一些用户 , 提供一个 beta 版本给他们测试 , 这些版本中我们打开了我们前面所讲的调试手段 . 这可以显示一些问题 , 多数是因为硬件的不同 , 而这个我们在内部测试中并没有发现 .
** 回归测试( ** ** Regression Testing ** ** ) ** ** **
最后 , 用于我们前面说的调试手段已经做到 GUI 中 , 所有我们可以记录和回放我们的测试教本 . 所以我们可以实现回归测试 , 这个测试是用来测试我们的新代码对以前的东西有没有影响 .
** 开发测试( ** ** Development Testing ** ** ) ** ** **
不必多说 , 上面的调试手段对我们自己的开发测试也是非常有用的 ( 特别是有了版本控制以后 , 它可以允许我们退回到旧版本上 , 测试相同的事件序列 .)
** 提前发布产品 ** ** **
管理层因为上一个项目的原因非常恼火 , 因为他们要应付客户的发火 , 所以这次分配了三个月的事件用来测试 ( 以前从来没有听说这么长的时间 , 我们的编码仅用了六个月 , 而测试在编码过程中就已经开始了 !), 由于我们的调试手段 , 质量评估部门仅用一个月的时间就没有办法再发现新的问题了 , 所以我们的产品提前发布 .
** 发布版本 ** ** VS ** ** 测试版本 **
由于我们得调试手段非常深入 , 出于性能的原因 , 我们在发布版本中关闭了跟踪的语句 , 但是我们在发布版本中保留了 assert. 这是因为在实地工作中 , 我们的程序会连续不断的运行 , 会使日志文件非常大 . 此外 ,assert 语句会报告一个非常有价值的消息 , 为什么会处罚这个 assert, 因为在质量评估部门必然会有东西会出错 , 特别是由于世界各地不同的硬件产品 .
我认为这是一个非常好的体系 , 发布一个不带调试手段的版本给我们的客户 . 如果客户那儿持续有问题 , 并且想和你一起来解决这个问题 , 你可以给他一个带有全部调试手段的版本 . 除此之外 , 使用正确的 assert 控制 , 你可以显示一个非常漂亮的出错信息给你的客户 . 我比较喜欢 IE6 的出错信息 , 就象这样 ” 对此使用引起的不方便表示道歉 , 我们发现一个问题等等 ”. 你可以用这个机会自动重新启动你的程序 . 从一个用户的观点来看 , 这好像是被发生事故是被安全气囊划伤了一下子 , 却不是直接撞在挡风玻璃上 , 这就是进步 . 如果客户可以接入互联网 , 那么你的程序可以把错误信息发送给你 , 这就是为什么么在发布版本中保留 assert 的原因 , 你可以得到除了错误发生地址 , 栈的信息 , 寄存器和内存映象以外更多的信息 .
** 调试( ** ** Debug) ** ** 和跟踪 ** ** (Trace) **
在 C# 中 , debug 和 trace 类都提供了这些功能 , 但是它们都可以被关闭 . 缺省情况下 , 在调试 (Debug) 模式下它们是可用的 . 在发布 (release) 模式下 ,dubg 的功能是关闭的 , trace 仍然可以使用 . 它们两个都支持 assert 和 trace. 通常的使用方法这样 . Debug.Assert 来使用 assert 功能 , Trace.Write 来使用 trace 功能 .
<SPAN lang=ZH-CN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: Ver