【问题标题】:Assertive programming with JavaScript使用 JavaScript 进行断言式编程
【发布时间】:2012-07-18 18:08:20
【问题描述】:

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

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

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

    ...parsing
}

所以,我会这样做。

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

    ...parsing
}

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

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

问题 2 如果你这么认为,Spring3框架有什么好的方法吗?

【问题讨论】:

标签: javascript assert spring-3 assertion


【解决方案1】:

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

考虑这个例子:

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;    
}

没有断言你会得到这个函数的错误结果。您将不知道为什么收到 0 而应该是 1。您必须开始逐行调试代码并了解问题所在。

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

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

【讨论】:

  • 我喜欢你的解释,但我不应该使用断言来验证数据吗?我读到我应该用断言检查参数的有效性,来自 Effective Java 这本很棒的书,所以我不确定你的答案。
  • 我的回答有点不准确。我的意思是你永远不会用断言验证任何user input 数据。
【解决方案2】:

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

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

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

一边

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

【讨论】:

【解决方案3】:

出于以下几个原因,我认为在 Javascript 中进行自信的编程并不好:

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

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

经验法则:

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

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

assertThrow(somefunc, args, YourError);

在您的代码中使用您的if (condition) error();

【讨论】:

  • +1 同意。断言非常适合单元测试,但我不相信在生产中使用它们。
  • 我不同意你的看法。断言不仅对测试有用,而且对程序员来说也是一种安全措施。经常发生的情况是,当您调试一些深层代码时,您会看到一个变量,根据您的计算,该变量永远不会为零。如果没有自信的编程,你通常会写// Is never zero。问题是,有时程序员是错的,实际上在星期五变成了零。然而,你在单元测试中得到的错误将是一些更深层次的“NullPointer 异常”,而断言器会告诉你究竟出了什么问题。此外,在 JS 中,断言应该由后处理器删除。
  • 我同意 Max。这个链接也有很好的解释stackoverflow.com/questions/4520847/…,我在做单元测试。
  • 当我还必须编写单元测试时,预处理我的代码以删除断言是一件痛苦的事情。我真的不明白为什么在开发人员搞砸的情况下需要断言验证。这种类型的框架应该委托给单元测试而不是相关方法。
【解决方案4】:

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

为什么不组合:

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;
}

实际上,仔细想想,我经常使用这种模式。

【讨论】:

  • 我喜欢这种方式,但是console 太沉默了。此外,IE 不支持console
  • 嗯,断言的一个常见做法是在某处显示一些错误并终止整个应用程序,因为通常断言失败意味着比任何可以静默跳过的东西要复杂得多。
【解决方案5】:

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

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

如果条件不满足,我会让你的断言函数重定向到错误页面,并记录它。您可以通过设置window.location.href 在Javascript 中执行此操作,并通过XHR 发布来记录您的错误。

【讨论】:

    【解决方案6】:

    你可以这样使用它:

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

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

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

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

    【讨论】:

    • 我可以理解为什么断言在某些情况下是个好主意。但是,我认为趋势是用断言代替良好的编码实践,从而将其用作拐杖。
    猜你喜欢
    • 2016-06-29
    • 2016-07-16
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    相关资源
    最近更新 更多