代码之家  ›  专栏  ›  技术社区  ›  ken

是否坚持良好的实践?

  •  47
  • ken  · 技术社区  · 15 年前

    使用断言函数参数来强制它们的有效性是一个好的实践吗?我正在浏览Spring框架的源代码,发现它们使用 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;
          }
    

    FYI 断言 (不是) assert 语句)在Util类中定义如下:

    public abstract class Assert { 
       public static void notNull(Object   object, String   message) {
          if (object == null) {
              throw new IllegalArgumentException  (message);
          }
       }
    }
    
    7 回复  |  直到 9 年前
        1
  •  54
  •   kukis    10 年前

    原则上, assertions 与其他许多运行时检查没有什么不同。

    例如,Java绑定检查运行时的所有数组访问。这会使事情变慢吗?对。它有益吗?绝对!一旦发生超出限制的违规行为,就会抛出异常,并向程序员发出任何可能的错误警报!在没有绑定数组访问的其他系统中,检查的行为更加不可预测!(通常会造成灾难性的后果!).

    无论您使用库还是语言支持,断言在精神上都是相似的。有性能成本,但绝对值得。事实上,断言更有价值,因为它是显式的,并且它传达了更高层次的概念。

    如果使用得当,可以将性能成本和价值降到最低,无论是对于客户(客户会更早而不是更晚地发现违反合同的行为)还是开发人员(因为合同 自我实施 自描述 )最大化。

    另一种看待它的方法是将断言视为“积极的评论”。毫无疑问,评论是有用的,但它们是被动的;从计算上讲,它们什么也不做。通过将一些概念表述为断言而不是注释,它们变得活跃起来。它们实际上必须在运行时保持不变,否则将被捕获。


    参见: the benefits of programming with assertions

        2
  •  27
  •   Andy Stabler Phill    10 年前

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

    这里有一个区别: 断言 默认情况下不运行(必须使用 -ea 参数),而断言由 Assert 无法禁用类。

    在我看来(就其价值而言),这是一种验证参数的好方法。如果您像问题标题所暗示的那样使用了内置断言,那么我会反驳它,因为必要的检查不应该是可移动的。但这只是以下内容的简写:

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

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

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

        3
  •  18
  •   Stephen C    9 年前

    是的,这是很好的做法。

    在Spring案例中,这一点尤为重要,因为检查正在验证通常来自XML连接文件的属性设置等。换句话说,他们正在验证webapp的配置。如果您曾经进行过任何严重的基于Spring的开发,那么当您犯了一个愚蠢的配置错误时,这些验证检查将为您节省调试时间。

    但是请注意,在一个名为 Assert 和Java assert 关键字,用于定义Java断言。后一种形式的断言可以在应用程序启动时关闭,不应用于总是希望发生的参数验证检查。显然,Spring的设计者认为关闭webapp配置健全性检查是一个非常糟糕的主意…我同意。

    更新

    在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 .

        4
  •  6
  •   kiwicptn    15 年前

    基于Sun的 guide 关于断言,你应该 使用断言检查公共方法中的参数。

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

        5
  •  2
  •   nclark    9 年前

    在非常大且设计/维护不好的系统中,如果您希望提高方法的可预测性,例如,6000行长,并且公司中没有人再了解这些方法,那么使用assert关键字可以导致开发环境崩溃,从而发现错误是很有价值的。但是,如果您在生产中实现这些断言,那么您可能会短路一个补丁,尽管这个补丁的构想很糟糕,但它修复了一个问题。您希望通过在开发环境而不是生产环境中发现补丁来修复这个坏补丁。所以您将在开发时打开断言,并在生产中关闭它们。

    在开发时使用assert关键字的另一个有效方法是将有效性检查插入到算法中,这些算法必须以毫秒为单位执行,并且与不可预测或未测试的调用程序完全隔离。在这种情况下,您可能无法在生产中保留有效性检查,尽管它在开发中仍然非常有用。另一方面,如果您正在验证的参数的来源是不可预测的,或者可能是不可预测的(例如,如果部分由用户输入决定的话),那么即使在生产环境中,您也可能永远无法跳过检查,并且应该将性能损失视为业务成本。(在上一种情况下,您可能不想使用断言。)但是您应该选择断言来消除生产时间有效性检查。 只有 分析后会告诉您根本负担不起开销。

        6
  •  1
  •   cletus    15 年前

    是的,这是个好主意。您正在强制收缩接口或类。如果存在违反合同的情况,您希望尽快检测到。等待的时间越长,结果越不可预测,诊断起来就越困难。

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

        7
  •  0
  •   Dariusz Cieslak    12 年前

    我保持我的 已发布二进制文件中的断言 但使用修改后的行为:不调用Abort,但收集StackTrace。

    详细信息如下: http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/