当布尔“if”有三个结果代码路径时,你怎么看?

时间:2008-10-22 17:02:20

标签: design-patterns conditional

QA测试人员正在阅读HTML / JS代码以编写Web表单的功能测试,并看到:

if (form_field == empty)
{
...do stuff for empty field
}
else if (form_field != empty)
{
...do stuff for non-empty field
}
else
{
...do stuff that will never be done
}

经过几次令人尴尬的尝试后,测试人员意识到他们无法触发隐藏在第三个区块中的警报字符串。

我想知道的是,如果这个问题或多或少是语言特定的问题(非JS人员可以在这里学习课程吗?)并且有正当理由代码以这种方式结束吗?

如何找到/解决问题?

13 个答案:

答案 0 :(得分:8)

虽然第三个块无法在Javascript中触发,但在所有语言中都不是这样。在T-SQL中:

declare @test as int

set @test = null

if @test = 1 
  print 1
else if not @test = 1
  print 2
else 
  print 3

这将打印3,因为NULL既不等于,也不等于任何其他值。

答案 1 :(得分:4)

如果使用设计不良的布尔值(在早期的C中没有真正的布尔类型时常见),就会发生这种情况。你仍然可以在Windows中找到这些东西。

BOOL result = SomeWindowsAPI();
if (result == TRUE)
{
    // success
}
else if (result == FALSE)
{
    // failure
}
else
{
    // wtf?
}

这里的关键是显式测试“TRUE”,它假定布尔值只有一种方式可以有一个真值。当使用整数作为布尔值时,情况并非如此。

在某些计算机上的某些语言(VMS上的Fortran)中,可能有许多不同的整数值可以解析为true,而许多不同的值会解析为false。在Windows上,HRESULT在被解释为SUCCESS或FAILURE时是相同的。

答案 2 :(得分:3)

我见过其他情况,如果曾经有过其他东西(AND / OR),而修复它的人只是'修复它'并且没有深入探测。

答案 3 :(得分:2)

静态分析会告诉你第三种情况是“死代码”

像这样的代码来自对布尔逻辑的误解,或者是不同人随着时间的多次编辑 - 或两者兼而有之; - )

这不是Javascript特有的,这种错误可以用任何具有if-else结构的语言(或其合理的传真)来实现

答案 4 :(得分:2)

  

这个问题是或多或少的语言   具体(可以非JS人学习   这里的课程?)

这是一个与语言无关的问题。在Java中编写以下代码非常容易,例如:

if(x)
{
  //do something
}
else if(!x)
{
  //do something else
}
else
{
  //never, ever, do anything
}

要记住的关键是“if(!x)”不是必需的。使一个简单的“其他”可以创建更简单的代码。

Are there legitimate reasons code ended up this way?

排序。当需要直通时,始终存在else条件的标准做法。问题是程序员没有非常清楚地认为他的“(form_field!= empty)”与简单的“else”完全相同。指出他,他应该踢自己。如果他不这样做,请质疑他在团队中的角色。

  

应该采用什么方法   找到/解决问题(代码   报道,代码审查,黑盒子   测试等。)

静态代码分析工具可以捕获此类问题。但是,我不知道任何Javascript。 JSLint可以捕获很多不好的东西,但不能解决逻辑流问题。

答案 5 :(得分:1)

我不相信这个问题是针对所有语言的。您可以用各种其他语言构造类似(有缺陷的)条件语句。

另外,我不认为条件语句以这种方式构造是有正当理由的。正如您在评论中所述,第三个块中的语句将永远不会完成。

你可能会通过代码审查最有效地发现这样的错误。但是,由于这需要至少一个开发人员花费相当多的时间,因此通过开发高质量的单元测试和检查代码覆盖率可能会更好。在这种情况下,您可能会注意到条件语句的第三部分从未使用过。

答案 6 :(得分:1)

我知道我记得在我大学的第一年或第二年之前写过一些这样的东西,然后才知道更好。但我现在看不出有理由这样做。

它甚至接近合法的唯一方法是,如果“empty”或“form_field”是一个易失性值,类似于VB的Now()函数。但在这种情况下,我不会这样写。相反,您将值捕获一次高于if块并测试捕获的值。

答案 7 :(得分:1)

也许不是在JavaScript中,而是支持多线程编程的任何语言,以这样的方式声明form_field,即在多个线程之间共享它实际上可以看到发生这种情况。

例如,Peterson's algorithm包含类似无用的双重检查:

     turn = 1;
     while( flag[1] && turn == 1 );

但这可以抵御竞争条件。生成导致它的测试仍然很难。

如果没有可能的竞争条件,那么当我与NASA签约时,这就是我们曾经开玩笑地称之为“宇宙射线检查”的那种检查。 : - )

答案 8 :(得分:0)

一般形式

if (a)
  //1
else if (!a)
  //2
else
  //3

总是可以缩减为

if (a)
  //1
else
  //2

没有副作用。

答案 9 :(得分:0)

  • 这个问题或多或少是语言特定的(非JS人员可以在这里学习课程吗?)

没有。您可以使用分支和比较以任何语言遇到这种代码。

  • 代码以这种方式结束是否有正当理由?
  • 应该使用哪些方法来查找/解决问题(代码覆盖率,代码审查,黑盒测试等)

不,不是真的。我猜这段代码的开头不是布尔比较;也许它是空的,数字的,或非数字的,或空的,1-5个字符,或超过5个字符,类似的东西。当逻辑被更改为空或非空时,应该删除第三个块 - 这通常会被同行评审或类似的事情所捕获。

根据语言的不同,某些编译器甚至可能会发现这种情况。审查会抓住它;黑盒测试不会,因为你不会检查代码,但白盒测试会(虽然你应该在看到代码之后立即注意到它,然后才能进行任何测试)。

答案 10 :(得分:0)

如果您正在测试单个条件A,则很容易发现这类问题,因为您知道您可以拥有A而不是A。

如果你有条件A和B,那也不难做。你找A,不是A和B,不是A而不是B(例如) - 你可以很容易地告诉你'已涵盖所有案件。

有时,无论出于何种原因,条件可能会被重构,然后(采取上述设计的例子),同时留下三个块,以及由此产生的WTF。

但是如果你有条件A,B,C和D怎么办?堆叠if-else的确是一种非常简单的方式,但有时这就是完成它的方式。

通过创建完整的真值表,可以轻松地在逻辑覆盖中找到“漏洞”。一个很好的方法是使用卡诺图。 Karnaugh maps上的维基百科条目是一个很好的起点(图片,甚至!)。对于软件编码,您希望完全覆盖地图而不会重叠(至少通常是这样)。

答案 11 :(得分:0)

不同的气味会出现不同的气味。

我发现Cyclomatic Complexity工具很有用。任何复杂度超过5的东西都值得仔细研究。

答案 12 :(得分:0)

这发生在我们公司,我认为第二个其他的“死代码”正在执行中最有趣的事情。 在我们的例子中,它是一个无类型指针(不要问为什么我们有那些)被错误设置并强制转换为具有布尔字段的类。

if (A = TRUE) .. else if (A == FALSE) .. else ..”已应用于布尔字段。生成的asm代码如下:

cmp al,$01
jnz +$0c
...
test al,al
jnz +$0c
...

清除 al 中的值是> 1,它落到其他..

编码器写这篇文章的事实是期待它发生是另一回事......