提供给Google Guava的Preconditions。*方法的正确错误信息是什么?

时间:2010-06-27 17:09:13

标签: java exception guava preconditions

例如,当使用Preconditions.checkArgument时,错误消息是否应该反映通过案例或相关检查的失败案例?

import static com.google.common.base.Preconditions.*;

void doStuff(int a, int b) {
  checkArgument(a == b, "a == b");
  // OR
  checkArgument(a == b, "a != b");
}

5 个答案:

答案 0 :(得分:21)

对于前置条件检查,在异常详细消息中声明要求比仅仅陈述事实更具信息性。它还可以更自然地阅读代码:

documentation提供了以下示例:

  

这允许构造如

 if (count <= 0) {
   throw new IllegalArgumentException("must be positive: " + count);
 }
     

将被更紧凑的

取代
 checkArgument(count > 0, "must be positive: %s", count);

有两点需要注意:

  • 这个例子清楚地说明了要求,而不是事实
    • 某些内容必须正确”,而不是“
  • 通过反转检查的条件,整个构造更自然地阅读

在该示例之后,更好的消息将是:

checkArgument(a == b, "a must be equal to b"); // natural!

您甚至可以更进一步,在异常消息中捕获ab的值(请参阅 Effective Java 2nd Edition,第63项:详细消息中包含故障捕获信息):

checkArgument(a == b, "a must be equal to b; instead %s != %s", a, b);

说明事实的替代方法在代码中不太自然:

checkArgument(a == b, "a != b");              // awkward!
checkArgument(a == b, "a is not equal to b"); // awkward!

请注意,在Java代码中读取一个布尔表达式后面跟一个与该表达式相矛盾的字符串是多么的尴尬。

陈述事实的另一个缺点是,对于复杂的先决条件,它可能信息量较少,因为用户可能已经知道了这一事实,但不知道违反的实际要求是什么。

相关问题

答案 1 :(得分:4)

文档提供的示例使用单词代替符号非常清楚:

checkArgument(count > 0, "must be positive: %s", count);

鉴于这些基本上只是日志(或调试会话)中的异常消息,做任何你认为会使任何看到问题的人都清楚的事情,或任何阅读代码以理解前提条件的人。

例如,您可以将上述内容重写为:

checkArgument(count > 0, "count must be positive; was actually %s", count);

答案 2 :(得分:2)

就个人而言,我认为我会写这个

checkArgument(a == b, "a (%s) must equal b (%s)", a, b);

答案 3 :(得分:0)

通常(大多数情况下)你可以使用checkArgument()方法而不用错误消息参数,也就是说,根本不提供错误消息。

要制作好的错误消息,需要了解谁将阅读该消息。它不是最终用户;如果前提条件失败,则最有可能指出代码中的错误。该文本可以解释失败的前提条件,但在大多数情况下它对最终用户没用,它应该是程序员的提示。大多数情况下,如果没有堆栈跟踪和源代码,消息本身也没有意义。事实上,在大多数情况下,堆栈跟踪和源代码正是程序员修复错误所需要的,错误消息无济于事。如果前提条件不明显,则旁边的注释是记录它的完美方式。

在没有人真正关心文本的情况下,总是需要提供错误消息,导致程序员制作无用,明显且无用的消息,这些消息只会使代码的可读性降低。

在某些情况下,当错误消息有用时,例如消息可以包含变量的实际值,但是根据我们不经常使用的经验,在这些情况下您可以使用消息。

类似的参数也适用于JUnit中的断言方法;总是提供错误信息并不是一个好主意。

此外,当您在库中使用前置条件而不是最终用户的应用程序时,可能会有所不同,因为您不知道如何使用代码。

答案 4 :(得分:0)

正如polygenelubricants所指出的那样:

  

对于前置条件检查,在简单说明事实中说明异常详细消息中的要求比提供更多信息。

虽然你可以用Guava Preconditions做到这一点,Requirements API(我创作的)可以让你在不费力的情况下获得更好的输出。

番石榴先决条件

#include "MainForm.h"
using namespace System;
using namespace System::Windows::Forms;

[STAThread]
void main(array<String^>^ args) {
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    MyProject::MainForm form;
    Application::Run(%form);
}

给你这个:

String a = "foosball";
String b = "ballroom";
Preconditions.checkArgument(a == b, "a == b");

需求API

java.lang.IllegalArgumentException: a == b
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:122)
    at Main.main(Main.java:142)

给你这个:

output

相同的输入,更好的输出。

(如果您的终端不支持颜色,则会获得文字差异)