扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
根据我的经验,大多数程序的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() 方法来记录任何你觉得有助于你跟踪你的程序的信息:
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者