212

我在MongoDB 的 Java Connection driver 的这个提交中看到了以下代码,起初它似乎是某种玩笑。下面的代码有什么作用?

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

(编辑:自发布此问题以来,代码已更新)

4

4 回答 4

281

在检查了该行的历史之后,我的主要结论是工作中存在一些不称职的编程。

  1. 那条线是无端令人费解的。一般形式

    a? true : b
    

    forboolean a, b等价于简单的

    a || b
    
  2. 周围的否定和过多的括号使事情进一步复杂化。记住德摩根定律,这是一个微不足道的观察,这段代码相当于

    if (!_ok && Math.random() <= 0.1)
      return res;
    
  3. 最初引入这个逻辑的提交有

    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% 的观察结果了。是的,这需要更多的努力,所以让我们看看。

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

于 2013-05-30T10:30:06.627 回答
17

https://github.com/mongodb/mongo-java-driver/commit/d51b3648a8e1bf1a7b7886b7ceb343064c9e2225#commitcomment-3315694

11 小时前由 gareth-rees:

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

于 2013-05-30T10:05:28.010 回答
7

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

  private int logit = -1;

在 try 块中,进行测试:

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

这总是记录第一个错误,然后是每十个后续错误。逻辑运算符“短路”,因此 logit 仅在实际错误时增加。

如果您想要所有错误的第一个和第十个,无论连接如何,请将 logit 类设为静态而不是 aa 成员。

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

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

在 try 块中,进行测试:

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

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

于 2013-05-31T15:54:26.493 回答
2

我以前见过这种东西。

有一段代码可以回答来自另一个“黑匣子”代码的某些“问题”。如果它无法回答它们,它会将它们转发到另一段非常慢的“黑匣子”代码。

所以有时会出现以前看不见的新“问题”,它们会成批出现,比如连续出现 100 个。

程序员对程序的工作方式很满意,但如果可能发现新的问题,他希望将来可以通过某种方式改进软件。

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

由于日志变得太大,并且日志记录妨碍了记录他在此解决方案中得到的真正重要的事情:

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

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

我认为这与您在这里看到的相似。

我不喜欢这种工作方式,所以我删除了这段代码,只是将这些消息记录到不同的文件中,所以它们都存在,但不会破坏常规日志文件。

于 2013-06-05T10:11:57.417 回答