将断言放入我们的代码有什么意义?断言式编程有什么好处?
private void WriteMessage(string message)
{
Debug.Assert(message != null, "message is null");
File.WriteAllText(FILE_PATH, message);
}
例如,我们可以检查消息变量并在此处抛出异常。为什么我在这里使用断言?或者这是一个看到断言好处的错误例子?
将断言放入我们的代码有什么意义?断言式编程有什么好处?
private void WriteMessage(string message)
{
Debug.Assert(message != null, "message is null");
File.WriteAllText(FILE_PATH, message);
}
例如,我们可以检查消息变量并在此处抛出异常。为什么我在这里使用断言?或者这是一个看到断言好处的错误例子?
他们还支持快速失败的哲学,Jim Shore在这篇文章中对此进行了解释。
有些人会写:
/*
* This can never happen
*/
写起来更实用:
assert(i != -1);
我喜欢使用断言,因为它们很容易通过一个简单的编译时间常数关闭,或者可以用来做其他事情,比如准备错误报告。在发布某些内容时,我通常不会打开断言(至少,不是以通常的方式)。
使用它们使我免于在其他人的计算机上犯非常愚蠢的错误.. 那些喜欢测试我的 alpha 代码的勇敢灵魂。使用它们加上 valgrind 之类的工具有助于确保我在提交之前发现了一些可怕的东西。
要考虑的一个重要区别是您希望使用断言捕获哪些类型的错误。我经常使用断言来捕获编程错误(例如,调用带有空参数的方法)和处理验证错误的不同机制(例如,传递错误长度的社会安全号码)。对于断言捕获的编程错误,我想快速失败。对于验证错误,我希望反应不那么激烈,因为数据中出现错误可能是正常的(例如,用户进行某种数据输入)。在这些情况下,正确的处理可能是将错误报告给用户并继续运行。
如果该方法有一个指定的前提条件来采用非空消息参数,那么您希望程序在前提条件不成立时立即失败,然后必须修复错误的根源。
我相信在开发安全关键型软件时,断言更为重要。当然,您更愿意在正式指定软件时使用断言。
有关断言(以及与代码构造相关的许多其他主题)的精彩讨论,请查看Steve McConnel 的Code Complete。他用一整章的时间来有效地使用断言。
我使用它们来验证是否为我提供了有效的依赖类。例如,在构造函数 DI 中,您通常接受某种外部类,您依赖这些类来提供某些操作或服务。
所以你可以断言(classRef !- null,"classRef 不能为 null"); 而不是等待您将消息传递给 classRef 并获得其他一些异常,例如异常:访问冲突或同样模棱两可的东西,可能不会立即从查看代码中明显看出。
测试我们的假设非常有用。断言不断确保不变量成立。简而言之,它用于以下目的,
有时,当我们不想使用 try/catch/throw 时,我倾向于使用 assert_return()。
private void WriteMessage(string message)
{
assert_return(message != null, "message is null"); // return when false
File.WriteAllText(FILE_PATH, message);
}
我建议 assert_return() 通过在测试构建中报告错误来停止应用程序。然后在生产系统中,它应该记录和错误并从函数返回,说它不能这样做。