12

我知道为什么断言式编程很好,所以我想将它与 JavaScript 一起使用。但是,我不想向用户显示错误框,这是不寻常的事情。忽略它并让他们重试可能会更好。

例如,此代码将生成一个错误框并中断用户。

function getDomainFromURL(url) {
    assertTrue(url, 'URL should not be null');

    ...parsing
}

所以,我会这样。

function getDomainFromURL(url) {
    if (!url) return;

    ...parsing
}

我认为第二个有利于可用性,第一个有利于开发。因此,IMO 最好将这些结合起来并assert在生产代码中消失。

问题1 你认为是吗?或者有什么不同的想法?

问题2 如果你这么认为,有没有什么好的方法可以用Spring3框架来做呢?

4

6 回答 6

8

断言不应用于验证任何类型的用户输入数据。它们也不应该用于错误检查。断言是在测试失败时使程序员更容易调试的方法。这也是一种使您的代码更易于理解的方法。

考虑这个例子:

function calculateSomeCrazyFormula(a,b,c) {
    var d = a+b+c;
    ....
    k = (x + y)*2;

    assert(k != 0);
    l = d/k;        
    ....
    return x;
}

我的公式根据它的规范确保k 永远不会是 0。在这里,我几乎使用 assert 作为我代码中的注释。它不验证逻辑 - 它完全相反。通过断言,我可以验证我对复杂逻辑的实现是否正确。后来,当我回到我的代码并看到l = d/k当 k 为 0 时我不会怀疑会发生什么,因为我看到我assert在那里并且明白这0不应该发生。

此外,如果某处出现错误并且0确实发生了,您通常会看到一些更深层次的错误。例如:

function otherFormula(a,b,c) {
    var x = calculateSomeCrazyFormula(a,b,c);

    var y = doSomeStuff(x);
    var z = doOtherStuff(y);
    return z;    
}

如果没有断言,您将得到此函数的错误结果。您将不知道为什么在应该为 1 时收到 0。您将不得不开始逐行调试代码并了解哪里出了问题。

但是,使用断言,您会立即注意到“断言失败”错误,并会立即缩小查找问题的范围。

断言在包括 Javascript 在内的任何编程语言中都很有用,但是它们不应该出现在 Live 环境中。因此,一些后处理器系统应该在发布之前从您的代码中删除所有断言。

于 2011-07-14T13:23:58.860 回答
4

我不认为第二个特别好。如果你从一个总是期望返回某些东西的方法中返回任何内容,那么代码可能会在其他地方失败,而不是接近实际问题所在的位置,即在getDomainFromURL函数内。

另一方面,如果此方法在参数为空时不返回任何内容是完全可以的,那么添加断言就没有意义了。

就个人而言,我会在开发和生产中到处使用第一种形式。如果断言在生产中失败,那么您将获得有关问题原因的非常有用的反馈(在浏览器、日志等中)。如果你删除断言,你仍然会有一个错误,但它会更难追踪

在旁边

这种编程风格——检查前置条件——是所谓的基于契约的编程的一部分。我以前从未听说过“断言式编程”这个词。

于 2011-07-14T13:06:17.757 回答
2

我认为在 Javascript 中进行自信的编程并不好,原因如下:

  1. 我不喜欢这样的错误检查应该在生产环境中进行。
  2. 人们专门为此目的开发了单元测试框架(JsUnit)
  3. 这个断言语句会增加代码大小,从而增加下载时间和执行时间。

最好的方法是编写单元测试。这样,您可以确保您的代码在更新时不会中断,这也意味着断言不会出现在您的生产代码中。当然,您可能需要拥有诸如if (condition) error();这些条件可能取决于用户而不是开发人员之类的东西。这些将是不可避免的,您将需要手动编码。

经验法则:

  • if (condition) error();当条件取决于用户时使用
  • 如果条件取决于开发人员,请编写单元测试。

最后,通过单元测试,您可以检查您的代码是否正确错误。我不太确定 JsUnit,但在你的测试中你可能会做这样的事情:

assertThrow(somefunc, args, YourError);

配合你if (condition) error();的代码

于 2011-07-14T13:00:13.883 回答
2

在处理异步和用户驱动的数据时,总是需要条件错误处理。它发生了。用户和网络搞砸了。这就是人生。您最好的选择是,当且仅当可以合理地预期数据可能损坏时,至少要有第二个示例。如果负责提供您正在测试的数据,那么您需要事先确保数据是有效的。

为什么不组合:

function getDomainFromURL(url) {
    if( !assert( url != undefined, 'URL should not be null.' ) ) 
        return ''; 
    // '' is optional, but I don't like returning null if I expect a value.
    /* blah blah blah */
}

// as lightweight a function as you can have.
function assert( val, msg )
{
    if( !val )
    {
        console.log( msg );
        return false;
    }
    return true;
}

实际上,想想看,我经常使用那个确切的模式。

于 2011-07-14T13:08:04.380 回答
1

忽略它并让他们重试可能会更好。

默默地失败不是一个好主意。从可用性的角度来看,即使在出现错误的情况下,用户也应该对他们的操作立即进行反馈。当您的代码中发生异常情况时,您应该显示一个简单的错误页面。这里的想法是,快速失败

如果不满足条件,我会让您的断言函数重定向到错误页面,并记录它。您可以在 Javascript 中执行此操作,方法是使用XHRwindow.location.href设置和记录您的错误。

于 2011-07-14T13:04:58.440 回答
1

你可以像这样使用它:

function getDomainFromURL(url) {
   assert(url != null, "url is null");
   if (!url) return;
    ...parsing
}

有些人会不同意,但我会尝试找到一种方法来删除生产代码中的断言语句,可能通过使用预处理器或作为混淆步骤的一部分,如果你有的话。这可以提高性能和代码大小,但您需要确保从断言中调用的代码不会改变程序的状态。这也可能很棘手。我的结论是,用 javascript 编写大型而健壮的程序需要纪律。

作为奖励,看看可以在这里找到的断言:

http://aymanh.com/9-javascript-tips-you-may-not-know/

于 2012-07-18T10:08:20.967 回答