为什么MongoDB Java驱动程序在条件中使用随机数生成器?

问题

我在this commitforMongoDB's Java Connection driver中看到了以下代码,它最初似乎是某种笑话。以下代码有什么作用?

if (!((_ok) ? true : (Math.random() > 0.1))) {
    return res;
}

(编辑:代码has been updated since发出此问题)


#1 热门回答(265 赞)

在检查了这条线的历史之后,我的主要结论是在工作中出现了一些不称职的编程。

  • 这条线是无偿的错综复杂的。一般形式一个?是的:b
     对于布尔a,b等价于简单的a || b
  • 周围的否定和过多的括号使事情进一步卷入。记住De Morgan的定律,这段代码相当于if(!_ok && Math.random()<= 0.1)是一个微不足道的观察。
      返回资源;
  • 最初引入此逻辑的提交有if(_ok == true){
      _logger.log(Level.WARNING,"服务器见过:"_addr,e);
    } else if(Math.random()<0.1){
      _logger.log(Level.WARNING,"服务器看不见:"_addr);
    }
      - 另一个不称职编码的例子,但请注意相反的逻辑:这里记录的事件是_ok或10%的其他情况,而2.中的代码返回10%的时间并记录90%的时间。因此,后来的提交不仅破坏了清晰度,而且破坏了正确性。我认为在你发布的代码中,我们实际上可以看到作者打算如何将原始if-then转换为其早期返回条件所需的否定。但后来他搞砸了,并通过扭转不平等的标志插入了一个有效的"双重否定"。
  • 除了编码风格问题之外,随机日志记录本身就是一个非常可疑的实践,特别是因为日志条目没有记录它自己的特殊行为。显然,目的是减少对同一事实的重述:服务器当前已关闭。适当的解决方案是仅记录服务器状态的变化,而不记录每个观察的变化,更不用说随机选择10%这样的观察结果。是的,这需要更多的努力,所以让我们看一些。

我只能希望通过检查三行代码而积累的所有这些无能证据,并不能完全说明整个项目,并且这项工作将尽快清理完毕。


#2 热门回答(15 赞)

https://github.com/mongodb/mongo-java-driver/commit/d51b3648a8e1bf1a7b7886b7ceb343064c9e2225#commitcomment-3315694
11小时前由gareth-rees:

据推测,这个想法只记录了大约1/10的服务器故障(因此避免大量垃圾邮件发送日志),而不会产生维护计数器或计时器的成本。 (但肯定维持一个计时器可以负担得起?)


#3 热门回答(7 赞)

添加初始化为负1的类成员:

private int logit = -1;

在try块中,进行测试:

if( !ok && (logit = (logit + 1 ) % 10)  == 0 ) { //log error

这始终记录第一个错误,然后记录每第十个后续错误。逻辑运算符"短路",因此logit仅在实际错误时递增。

如果你想要第一个和第十个ofaller,无论连接如何,使logit类静态而不是成员。

如前所述,这应该是线程安全的:

private synchronized int getLogit() {
   return (logit = (logit + 1 ) % 10);
}

在try块中,进行测试:

if( !ok && getLogit() == 0 ) { //log error

注意:我不认为抛出90%的错误是个好主意。