首页 > 开发 > 综合 > 正文

六种快速修理C# Bug的方法(zt)

2024-07-21 02:22:11
字体:
来源:转载
供稿:网友
运用由来已久的技术更快地得到高质量的代码。
by bill wagner
.net framework中包含许多工具可以用来更快、更容易地编写正确的程序。但我们得面临这样的情况:出现bugs。不管程序多么简单,程序员都可能出错。根据我的经验,大多数程序的bugs出现在程序员之间的接口:当一个程序员编写的代码被另一个程序员调用时。不知何故,调用者破坏了代码编写时做的假设。是谁的过错呢?这并不要紧,更重要的是你能多快修好它?下面这些技巧将帮你在程序投入使用前更快地发现并解决这些问题。最终,这些技巧会帮你诊断任何的确在使用中出现的问题。

测试假设条件
测试假设条件是构建正确的程序最重要的一个方法。在你写一个函数时,你应该考虑并确定你对那个函数做了什么样的假设。你应该问自己以下这些问题:

1. 当这个函数被调用时,这个对象必须是怎样的(对象初试化,某个内在变量值)?  
2. 当这个函数存在时,这个对象将会怎样(仍是#1,但包括该函数的副作用)?
3. 该函数的任何参数必须是怎样的(允许空值吗,输入值的范围是什么)?
4. 返回值必须是怎样的?  


一旦你问了自己这四个问题并作出回答后,把答案放到代码中。在c#中,用system.diagnostics.debug类的assent方法来表示:public bool processiterations (int
    numiters)
{
    debug.assert (numiters > 0,
    "processiterations.",
    "iterations must be more than 0");
    // more code...



该代码片段执行了numiters参数必须大于零这样一个假设。如果你用一个无效的参数调用processiterations,该assert被触发。这时候,程序停止运行并通知用户出现的错误。声明(assertions)只被编译到debug 版本中的程序,所以它们不影响生产情况中的性能。

为什么用这种方法? 运用这种技巧可以确保很快地发现对你的类的方法未预料地使用。然后,或者调用者修改他的代码,或者要求在你的类的行为(behavior)中修改。

验证完整性
一个c# 程序中的大多数函数都是一个对象上的实例方法。对任何对象的有效状态都有暗示的假设。当一个公有的方法被调用时,你应该确保那些暗示的假设经过了测试。c# 的条件编译特征使这一点很容易实现。

首先,写一个私用的函数来测试对象的完整性。你在这么做时,将该方法标为“conditional”:[conditional ("debug")]
private void imok ()
{
    debug.assert (this != null,
        "testing object state",
        "this cannot be null");
    // more here.
}




然后,在每个公有的方法中,调用imok方法:public bool processiterations (int
    numiters)
{
    imok ();
    debug.assert (numiters > 0,
    "processiterations.",
    "iterations must be more than 0");




在发布(release)版本中,编译器自动取消对imok 的调用。

为什么用这种方法?运用该技巧,你可以快速发现任何你的对象状态变得无效的情况。

运用debug 和trace 输出
打印诊断消息可以帮你确定你的程序是怎么出错的。你需要知道当触发一个assert时,发生了什么情况;你也通常需要知道在这之前发生了什么。知道这些的最好的方式就是运用你的代码,这样你就可以很容易地看到在出现bug前,调用了什么函数。

在生成调试输出时,.net framework有一些新的功能可以用。system.diagnostic.debug类可以让你格式化调试输出,并能很容易地创建不同的类或级别的调试输出。下面是我喜欢用的一些指导方针。

首先,在你的程序中为每个类建一个traceswitch对象:public class myclass
{
    private static traceswitch
        myclassswitch = new traceswitch
        ("myclassswitch", "controls the         debug output of myclass");




然后,用writeif() 和 writelineif() 方法来记录任何你觉得有助于你跟踪你的程序的信息:public bool processiterations (int
    numiters)
{
    writelineif
        (myclassswitch.traceinfo,
        "entering processiterations",
        "calltrace");
    imok ();
    debug.assert (numiters > 0,
    "processiterations.",
    "iterations must be more than 0");

我更喜欢用writelineif(),它可以打印出错误消息以及错误种类。第一个参数包含一个用于调试开关的值,可以让你控制打印什么级别的输出

system.diagnostics.trace 的运用同debug的用法完全一样。 不同的地方是,debug只编译到debug版本中,而trace语句编译到debug和release版本中。因此,运用trace语句应更谨慎。将trace语句用到可以在编程实战中帮你发现bugs或捕获使用特征的代码中。

为什么用这种方法? 运用这些方法可以让你知道代码执行的顺序。这有助于你确定在程序出错前有何动作(actions)。

动态地控制输出
这些新的.net framework类的最大的好处是通过编辑一个配置文件,你可以改变任何跟踪开关(trace switch) 的级别。在应用程序目录中建一个xml文件,该文件的名字与你的程序的名字相同,扩展名为“.config”。例如,如果你的程序是myapp.exe,就建一个myapp.exe.config。你可以用这个文件来设置你的跟踪开关的值。比如下面的文件:<?xml version="1.0"?>
<configuration>
    <system.diagnostics>
        <switches>
            <add name="myclassswitch"
                value="4" />
        </switches>
    </system.diagnostics>
</configuration>




该文件把myclassswitch的值设置为4,符合“info”的设置。仅通过编辑这个config文件,你就可以改变你的程序中任何开关的级别。

为什么用这种方法?通过运用多个开关和创建适当的config文件,你可以改变记录输出,集中精力到你关心的那些元素上。

设置你的listeners
.net framework有一个代表接收debug、assert和trace输出的对象的listeners集合。默认情况下,你的应用程序有一个单一的defaulttracelistener。这个listener忽略debug和trace输出,显示一个assert消息的对话框。你可以添加项目到这个集合,或从这个集合中删除项目。已为你创建好的两项是textwritertracelistener和eventlogtracelistener。textwritertracelistener把消息写到一个流(stream)中,eventlogtracelistener把消息写到一个eventlog中。eventlog可以让你把你的程序的调试和跟踪消息写到系统事件日志记录中。

我喜欢为所有程序建一个调试日志文件:static void main ()
{
    debug.listeners.add (
        new textwritetracelistener
        ("mylog.log");
    // etc.




为什么用这个方法? 该技巧可以让你控制在哪里用调试和跟踪语句。

在你发现bugs时,用这些技巧
坦白地说,在开始写代码时,没有人用所有这些技巧。实际上,当我们努力想发现那些重大bugs的原因时我们通常添加这些语句。在你陷入那种困境时,尝试以下方法:

1. 当你创建类时,通常为每个类建一个跟踪开关。  
2. 通常为每个类建一个验证函数。  
3. 当你要诊断错误的行为时,添加其它的跟踪和调试语句。确信把这些变化保留在代码中。我发现的最常见的错误之一就是:当程序员想找到bugs时,他们添加许多跟踪和调试语句来发现错误。然后,一旦他们找到了他们查找的错误,他们就把这些语句删掉。


这些工具会帮你发现并修理bugs,就看你用不用它们了。


关于作者:
bill wagner 是srt solutions的创始人和顾问,专门研究.net 开发。他是the c# core language little black book一书的作者。 十多年来,他一直从事软件开发与教学工作。他是visual studio magazine的专栏作家,并在许多关于改进软件开发习惯的会议上做演讲。他从事的软件程序的范围很广,从儿童游戏到生物信息学研究。联系方式:[email protected]。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表