是否主张良好的做法?

发布于 2024-08-25 01:10:58 字数 1019 浏览 5 评论 0原文

对函数参数使用 Assert 来强制其有效性是一个好习惯吗?我正在查看 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 语句)在 util 类中定义如下:

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

Is it a good practice to use Assert for function parameters to enforce their validity. I was going through the source code of Spring Framework and I noticed that they use Assert.notNull a lot. Here's an example

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

Here's Another one:

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, The Assert.notNull (not the assert statement) is defined in a util class as follows:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

横笛休吹塞上声 2024-09-01 01:10:58

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

例如,Java 在运行时对所有数组访问进行边界检查。这会让事情变得更慢吗?是的。有好处吗?绝对地!一旦发生越界违规,就会引发异常,并警告程序员任何可能的错误!在其他系统中,数组访问未进行绑定检查的行为更加不可预测! (通常会带来灾难性的后果!)。

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

使用得当,可以最大限度地降低性能成本,并为客户(他们会尽早发现合同违规行为)和开发人员(因为合同是自我执行自记录),被最大化。

另一种看待它的方式是将断言视为“主动评论”。毫无疑问,评论是有用的,但它们是被动的;在计算上他们什么也不做。通过将一些概念表述为断言而不是注释,它们就会变得活跃。它们实际上必须在运行时保持;违规行为将被抓获。


另请参阅:使用断言进行编程的好处

In principle, assertions are not that different from many other run-time checkings.

For example, Java bound-checks all array accesses at run-time. Does this make things a bit slower? Yes. Is it beneficial? Absolutely! As soon as out-of-bound violation occurs, an exception is thrown and the programmer is alerted to any possible bug! The behavior in other systems where array accesses are not bound-checked are A LOT MORE UNPREDICTABLE! (often with disastrous consequences!).

Assertions, whether you use library or language support, is similar in spirit. There are performance costs, but it's absolutely worth it. In fact, assertions are even more valuable because it's explicit, and it communicates higher-level concepts.

Used properly, the performance cost can be minimized and the value, both for the client (who will catch contract violations sooner rather than later) and the developers (because the contract is self-enforcing and self-documenting), is maximized.

Another way to look at it is to think of assertions as "active comments". There's no arguing that comments are useful, but they're PASSIVE; computationally they do nothing. By formulating some concepts as assertions instead of comments, they become ACTIVE. They actually must hold at run time; violations will be caught.


See also: the benefits of programming with assertions

阳光的暖冬 2024-09-01 01:10:58

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

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

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

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

... 这始终是在公共方法中进行的良好实践。

内置样式的断言对于条件应始终为 true 的情况或私有方法更有用。 介绍断言的语言指南有一些很好的指南这基本上就是我刚才所描述的。

Those asserts are library-supplied and are not the same as the built-in assert keyword.

There's a difference here: asserts do not run by default (they must be enabled with the -ea parameter), while the assertions provided by the Assert class cannot be disabled.

In my opinion (for what it's worth), this is as good a method as any for validating parameters. If you had used built-in assertions as the question title implies, I would have argued against it on the basis that necessary checks should not be removable. But this way is just shorthand for:

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

... which is always good practice to do in public methods.

The built-in style of asserts is more useful for situations where a condition should always be true, or for private methods. The language guide introducing assertions has some good guidelines which are basically what I've just described.

智商已欠费 2024-09-01 01:10:58

是的,这是很好的做法。

在 Spring 的情况下,这一点尤其重要,因为检查会验证通常来自 XML 接线文件的属性设置等。换句话说,他们正在验证 web 应用程序的配置。如果您曾经进行过任何认真的基于 Spring 的开发,那么当您犯下愚蠢的配置错误时,这些验证检查将为您节省数小时的调试时间。

但请注意,名为 Assert 的库类与用于定义 Java 断言的 Java assert 关键字之间存在很大差异。后一种形式的断言可以在应用程序启动时关闭,并且不应该用于您始终希望进行的参数验证检查。显然,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

Yes it is good practice.

In the Spring case, it is particularly important because the checks are validating property settings, etc that are typically coming from XML wiring files. In other words, they are validating the webapp's configuration. And if you ever do any serious Spring-based development, those validation checks will save you hours of debugging when you make a silly configuration mistake.

But note that there is a BIG difference between a library class called Assert and the Java assert keyword which is used to define a Java assertion. The latter form of assertions can be turned off at application launch time, and should NOT be used for argument validation checks that you always want to happen. Clearly, the Spring designers think it would be a really bad idea to turn off webapp configuration sanity checks ... and I agree.

UPDATE

In Java 7 (and later) the java.util.Objects class provides a requireNonNull convenience method to test if an argument is null and raise an exception. You use it like this:

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

or

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

However, note that this method raises NullPointerException rather than IllegalArgumentException.

哭泣的笑容 2024-09-01 01:10:58

根据 Sun 关于断言的指南,您应该在公共方法中使用断言进行参数检查。

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

Based on Sun's guide on assertions, you should not use assertions for argument checking in public methods.

Argument checking is typically part of the published specifications (or contract) of a method, and these specifications must be obeyed whether assertions are enabled or disabled.

知你几分 2024-09-01 01:10:58

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

在开发时断言关键字的另一个有效用途是将有效性检查插入到必须在亚毫秒时间内执行的算法中,并且能够很好地与不可预测或未经测试的调用者隔离。在这种情况下,您可能无法在生产中保留有效性检查,尽管它在开发中仍然非常有用。另一方面,如果您正在验证的参数的来源是不可预测的或可能变得如此(例如,如果它部分地由用户输入确定),那么您可能永远无法跳过检查,即使在生产中也是如此,并且应该将性能损失视为开展业务的成本。 (在最后一种情况下,您可能不想使用断言。)但是您应该选择断言来消除生产时有效性检查在分析告诉您您根本负担不起之后开销。

In very large and poorly designed/maintained systems, if you're looking to improve predictability in methods that are, say, 6000 lines long and nobody in the company understands them anymore, it can be valuable to use the assert keyword to cause development environments to blow up, revealing bugs. But were you to implement those assertions in production, you might shortcircuit a patch that, though horribly conceived, fixed a problem. You want to fix that bad patch by discovering it in the dev environment, not production. So you would turn asserts on at development time, and turn them off in production.

Another valid use of the assert keyword at development time is to insert validity checks into algorithms that must execute in sub-millisecond times and are well enough insulated from unpredictable or untested callers. You may not be able to afford to preserve the validity check in production in such a case, though it's still very useful in development. On the other hand, if the source of the parameters you're validating is unpredictable or could become so (if it's determined partly by user input, for example), you can probably never afford to skip the check, even in production, and should take the performance hit as a cost of doing business. (In this last case, you probably wouldn't want to use an assert.) But you should opt for asserts to eliminate a production-time validity check only after profiling tells you you simply can't afford the overhead.

冷夜 2024-09-01 01:10:58

是的,这是个好主意。您正在强制执行接口或类的契约。如果存在违反合同的情况,您希望尽快发现。等待的时间越长,结果就越难以预测,诊断也就越困难。

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

Yes it's a good idea. You're enforcing the contracting of the interface or class. If there is a contract violation you want to detect it as soon as possible. The longer you wait the more unpredictable the results can be and the harder it can be to diagnose.

When you explicitly check like this you should also provide an information message that when viewed in a log file can give useful context to help find the root cause or even just to realize you've made a wrong assumption about what the contract is.

薯片软お妹 2024-09-01 01:10:58

我将我的断言保留在已发布的二进制文件中,但行为进行了修改:不调用中止,但收集堆栈跟踪。

更多详细信息请参见:http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/< /a>

I'm keeping my assertions in released binaries but with modified behavior: abort is not called but stacktrace is collected.

More details here: http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文