2010-03-14 58 views
42

是否使用断言函数参数强制执行的有效性一个很好的做法。我正在浏览Spring Framework的源代码,我注意到他们使用了很多Assert.notNull。这里有一个例子认为是好的做法?

public static ParsedSql parseSqlStatement(String sql) { 
    Assert.notNull(sql, "SQL must not be null");} 

这里是另外一个:

public NamedParameterJdbcTemplate(DataSource dataSource) { 
      Assert.notNull(dataSource, 
        "The [dataSource] argument cannot be null."); 
      this .classicJdbcTemplate = new JdbcTemplate(dataSource); 
     } 

     public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) { 
      Assert.notNull(classicJdbcTemplate, 
        "JdbcTemplate must not be null"); 
      this .classicJdbcTemplate = classicJdbcTemplate; 
     } 

仅供参考,Assert.notNull(不是assert语句)在一个实用程序类的定义如下:

public abstract class Assert { 
    public static void notNull(Object object, String message) { 
     if (object == null) { 
      throw new IllegalArgumentException (message); 
     } 
    } 
} 
+9

请注意,这不是'assert'。在这种情况下,你应该总是抛出异常。默认情况下,assert关闭。 – 2010-03-14 02:45:12

+0

我不确定这个'Assert'类用于什么。我习惯了'assert'语句:http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html – FrustratedWithFormsDesigner 2010-03-14 02:46:46

+1

你问是否有断言是好的(是的,它是)?或者assert关键字是否允许您编写断言然后关闭以进行部署,对于此目的而言更有用,那么会引发抛出异常(不确定)的“常规”if语句? – Thilo 2010-03-14 03:13:44

回答

51

原则,assertions无法从众多其他运行时checkings不同。

例如JAVA绑定-检查所有数组访问在运行时。这会让事情变慢吗?是。它有益吗?绝对!一旦出现违反规定的违规行为,就会抛出异常并提醒程序员任何可能的错误!数组访问没有被绑定检查的其他系统中的行为是非常不可预知的! (往往带来灾难性的后果!)。

断言,无论你使用的库或语言的支持,是神似。性能成本,但它是绝对值得的。事实上,断言更为重要,因为它是明确的,它传达了更高层次的概念。

使用得当,性能成本最小化和价值,既为客户(谁来抓违反合同宜早不宜迟)和开发商(因为合同是自我实施自我记录))被最大化。

另一种方式来看待它是觉得断言为“活动的意见”的。没有人认为评论是有用的,但它们是被动的;在计算上他们什么都不做。通过将一些概念作为断言而不是评论来形成,它们就变成了ACTIVE。他们实际上必须在运行时间保持;违规行为将被捕获。


参见:the benefits of programming with assertions

+4

我的印象是可以关闭断言。这不会破坏使用断言的整个目标吗? – monksy 2011-08-25 18:32:42

+2

不是100%确定这一点,但我认为这取决于应用程序的种类。我隐约记得在Code Complete中读到这个。比方说,你有一个嵌入式Java程序的医疗设备。它将在启用断言的情况下运行,因此它会崩溃而不是返回错误的读数,而您只需重新启动并再次使用它。另一方面,让我们假设它是一款游戏,而更糟糕的情况是屏幕上的像素颜色错误,您可以在生产中禁用断言。那么,至少这是我的理解。这个答案非常明显,顺便说一句。 – DPM 2011-11-30 20:18:46

+2

我忘了补充一点:那只是为了生产。通常情况下,您将在测试期间启用断言,因此,至少在您可以完全控制以启用断言的特定情况下(测试,开发),您不会失去其优势。 – DPM 2011-12-04 17:19:40

1

是的,它是一个好主意。你正在执行界面或类的合同。如果有违反合同的情况,您希望尽快发现。您等待的时间越长,结果越难以预测,诊断就越困难。

当你明确地检查这样的情况时,你还应该提供一条信息消息,在日志文件中查看时可以提供有用的上下文来帮助找到根本原因,甚至只是意识到你对合同做了错误的假设是。

15

是的,这是很好的做法。

在Spring情况下,因为检查验证属性设置等是通常从XML文件接线未来尤为重要。换句话说,他们正在验证webapp的配置。如果你曾经做过任何严肃的基于Spring的开发,那么当你犯了一个愚蠢的配置错误时,这些验证检查将为你节省数小时的调试时间。

但请注意,名为Assert的库类与用于定义Java断言的Java assert关键字之间存在巨大差异。后一种形式的断言可以在应用程序启动时关闭,不应该用于您始终想要发生的参数验证检查。显然,Spring设计者认为关闭webapp配置完整性检查是一个非常糟糕的主意......我同意。

UPDATE

在Java 7(和更高)的java.util.Objects类提供了一个方便requireNonNull方法来测试是否一个参数是null和产生异常。您可以使用这样的:

SomeType t = ... 
SomeType tChecked = Objects.requireNonNull(t); 

SomeType tChecked = Objects.requireNonNull(t, "t should be non-null"); 

但是请注意,这种方法带来了NullPointerException而非IllegalArgumentException

25

这些断言是由库提供的,与内置的assert关键字不同。

这里有一个区别:assert s默认情况下不运行(它们必须使用-ea参数启用),而Assert类提供的断言不能被禁用。

在我看来(对于它的价值),这与任何验证参数一样好。如果你使用内置断言作为问题标题所暗示的话,那么我就会反驳它,因为必须检查不应该被移除。但这种方式只是简写:

public static ParsedSql parseSqlStatement(String sql) { 
    if (sql == null) 
     throw new IllegalArgumentException("SQL must not be null"); 
    ... 
} 

...这是在公共方法中总是很好的做法。

断言的内置样式对条件始终为真的情况或私有方法更有用。 language guide introducing assertions有一些很好的指导方针,基本上我刚刚描述过。

5

基于Sun的guide声明,你应该而不是使用断言参数检查公共方法。

参数检查通常是方法发布的规范(或契约)的一部分,无论断言是启用还是禁用,都必须遵守这些规范。

+6

这就是'assert'关键字 - 而不是Commons Lang和Spring框架提供的Assert。*。 – 2012-09-07 09:09:02

0

我让我的断言在发布二进制但修改行为:中止不叫,但堆栈跟踪收集。

更多细节在这里:http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/

+0

这种方法对于生产似乎很有意思,但有人必须不时地检查日志文件,同时用户可能遇到了作为失败断言症状的错误。如果断言立即中止,则一些错误永远不会发生......越快失败越接近导致问题的原因。 – 2012-10-29 13:42:53

+0

我决定在客户的质量检查报告“assert crash”案例后,从**中删除异常终止。我鼓励开发人员使用断言,即使其中一些可能是错误的 - 开发人员确信他们不会因为一个错误的断言而破坏整个应用程序。 – 2013-04-14 15:10:50

2

在非常大的,设计不当/维护系统,如果你正在寻找改进的方法预测是,比方说,6000线长,没人在公司了解他们了,使用assert关键字导致开发环境爆炸,揭示错误可能是有价值的。但是,如果你在生产中执行这些断言,你可能会缩短一个补丁,尽管可怕的构思,但修复了一个问题。您想通过在开发环境中发现而不是在生产环境中修复那个不好的补丁。所以你可以在开发时打开它,并在生产中关闭它们。

另一个有效的利用在开发时assert关键字的是插入有效性检查到必须在亚毫秒时间执行并不够好,不可预知的或未经测试的呼叫者绝缘算法。在这种情况下,您可能无法负担得起生产中的有效性检查,尽管它在开发中仍然非常有用。另一方面,如果您正在验证的参数的来源是不可预知的或者可能会变得如此(例如,如果部分由用户输入确定),则即使在生产中也可能不会跳过检查,并且应该将业绩击中作为做生意的成本。 (在最后这种情况下,你可能不希望使用一个断言。)但你应该选择断言,以消除生产时间有效性检查只有分析告诉你后,你根本无法承受的开销。

相关问题