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

我在这个承诺中看到了下面的MongoDB的Java Connection驱动程序代码,它乍一看像是一个笑话。下面的代码做什么?

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

(编辑:代码已更新张贴这个问题)

24518 次浏览

< a href = " https://github.com/mongodb/mongo-java-driver/commit/d51b3648a8e1bf1a7b7886b7ceb343064c9e2225 commitcomment - 3315694 " > https://github.com/mongodb/mongo-java-driver/commit/d51b3648a8e1bf1a7b7886b7ceb343064c9e2225 commitcomment - 3315694 < / >

11小时前作者:gareth-rees:

大概的想法是只记录大约1/10的服务器故障(从而避免大量垃圾日志),而不会产生维护计数器或计时器的成本。(但维护一个计时器肯定是负担得起的吧?)

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

  1. 这句话莫名其妙地令人费解。一般形式

    a? true : b
    

    for boolean a, b等价于simple

    a || b
    
  2. The surrounding negation and excessive parentheses convolute things further. Keeping in mind De Morgan's laws it is a trivial observation that this piece of code amounts to

    if (!_ok && Math.random() <= 0.1)
    return res;
    
  3. The commit that originally introduced this logic had

    if (_ok == true) {
    _logger.log( Level.WARNING , "Server seen down: " + _addr, e );
    } else if (Math.random() < 0.1) {
    _logger.log( Level.WARNING , "Server seen down: " + _addr );
    }
    

    另一个不合格编码的例子,但请注意颠倒的逻辑:在这里,如果_ok或在10%的其他情况下,事件将被记录,而2。返回 10%的时间和90%的时间日志。因此,后来的提交不仅破坏了清晰度,还破坏了正确性本身。

    我认为在你发布的代码中,我们实际上可以看到作者打算如何以某种方式将原始的if-then转换为早期return条件所需的否定。但后来他搞砸了,通过颠倒不等号插入了一个有效的“双重否定”

  4. 撇开编码风格问题不谈,随机日志本身是一种相当可疑的实践,特别是因为日志条目并没有记录它自己的特殊行为。显然,这样做的目的是减少对同一事实的重述:服务器当前宕机。合适的解决方案是只记录服务器状态的变化,而不是记录它的每个观察,更不用说随机选择10%这样的观察。是的,这需要更多的努力,让我们看看。

我只能希望,从检查只有三行代码中积累的所有这些无能的证据,并不能公平地谈论整个项目,并且这一工作将尽快清理干净。

添加一个初始化为- 1的类成员:

  private int logit = -1;

在try块中,执行以下测试:

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

它总是记录第一个错误,然后每隔10个错误记录一次。逻辑运算符“短路”,因此logit仅在实际错误时递增。

如果你想要所有的第1和第10个错误,不管连接如何,将logit类设置为static而不是a成员。

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

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

在try块中,执行以下测试:

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

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

我以前见过这种事。

有一段代码可以回答来自另一段“黑盒”代码的某些“问题”。在无法回答的情况下,它会将它们转发到另一个非常慢的“黑盒”代码中。

因此,有时以前从未见过的新“问题”会出现,而且它们会分批出现,比如连续出现100个。

程序员对程序的工作方式很满意,但他希望将来能有办法改进这个软件,如果可能的话会发现新的问题。

所以,解决方案是记录未知问题,但结果是,有1000个不同的问题。日志变得太大了,加快速度没有任何好处,因为它们没有明显的答案。但每隔一段时间,就会出现一批可以回答的问题。

由于日志变得太大,而日志记录阻碍了记录真正重要的事情,他得到了这个解决方案:

只记录随机的5%,这将清理日志,同时从长远来看仍然显示可以添加的问题/答案。

因此,如果发生未知事件,在这些情况中的随机数量中,它将被记录下来。

我想这和你们在这里看到的很相似。

我不喜欢这种工作方式,所以我删除了这段代码,只记录了这些 消息到不同的文件,所以它们都存在,但没有破坏一般的日志文件