web-dev-qa-db-ja.com

MongoDB Javaドライバーが条件付きで乱数ジェネレーターを使用するのはなぜですか?

this commit for MongoDB's Java Connection driver で次のコードを見ましたが、最初はなんらかの冗談のように見えます。次のコードは何をしますか?

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

(編集:コード 以降更新されています この質問の投稿)

207
Monstieur

その行の歴史を調べた後、私の主な結論は、仕事でいくつかの無能なプログラミングがあったということです。

  1. その行は不必要に複雑です。一般的な形式

    a? true : b
    

    for boolean a, bは単純な

    a || b
    
  2. 周囲の否定と過剰な括弧は、物事をさらに畳み込みます。心に留めて De Morganの法則 これは、このコードが

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

    —別の不適切なコーディングの例ですが、 reversed logic に注意してください。ここでは、_okまたは他の10%の場合にイベントがログに記録されます。 returns 10%の時間と90%の時間を記録します。したがって、後のコミットは明快さだけでなく、正確さ自体も台無しにしました。

    あなたが投稿したコードでは、著者が元のif-thenを文字通り初期のreturn条件に必要な否定に変換する意図を実際に見ることができると思います。しかし、その後、彼は台無しにし、不平等記号を反転させることにより、効果的な「二重否定」を挿入しました。

  4. コーディングスタイルの問題は別として、確率的ロギングはそれ自体で非常に疑わしい習慣です。特に、ログエントリには固有の動作が記録されていないためです。意図は、明らかに、サーバーが現在ダウンしているという同じ事実の修正を減らすことです。適切な解決策は、サーバー状態の changes のみを記録することであり、それぞれの観測値ではなく、そのような観測値の10%のランダムな選択はもちろんです。はい、それはもう少し努力が必要ですので、いくつか見てみましょう。

わずか3行のコードを検査して蓄積されたこの無能の証拠がすべて、プロジェクト全体を公平に語らないこと、そしてこの作品ができるだけ早くクリーンアップしました。

273
Marko Topolnik

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

gareth-reesによる11時間前:

おそらく、アイデアは、サーバー障害の約1/10のみをログに記録することです(したがって、ログを大量にスパム送信することは避けます)。 (しかし、確かにタイマーを維持することは手頃な価格でしょうか?)

16
msangel

マイナス1に初期化されたクラスメンバーを追加します。

  private int logit = -1;

Tryブロックで、テストを行います。

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

これは常に最初のエラーを記録し、その後10番目ごとにエラーを記録します。論理演算子は「短絡」しているため、logitは実際のエラーでのみ増加します。

allエラーの最初と10番目が必要な場合は、接続に関係なく、メンバーではなくlogitクラスを静的にします。

すでに述べたように、これはスレッドセーフである必要があります。

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

Tryブロックで、テストを行います。

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

注:エラーの90%を捨てることは良い考えだとは思いません。

7
tpdi

私は以前にこの種のものを見たことがあります。

別の「ブラックボックス」コードから生じる特定の「質問」に答えることができるコードがありました。それらに答えられなかった場合、それは本当に遅い「ブラックボックス」コードの別の部分にそれらを転送します。

そのため、以前は見えなかった新しい「質問」が表示されることがあり、それらが100個連続して表示されるなど、一括して表示されます。

プログラマはプログラムの動作に満足していましたが、可能であれば新しい質問が発見された場合、将来ソフトウェアを改善する方法を望んでいました。

そのため、解決策は不明な質問をログに記録することでしたが、判明したように、1000の異なる質問がありました。ログが大きくなりすぎたため、明らかな答えがなかったため、これらを高速化するメリットはありませんでした。しかし、時々、答えられる質問のバッチが表示されます。

ログが大きくなりすぎており、ログがこのソリューションで得た真に重要なことを記録する方法を妨げていたためです。

ランダムな5%のみをログに記録します。これによりログがクリーンアップされますが、長期的には追加できる質問/回答が表示されます。

そのため、これらのケースのランダムな量で未知のイベントが発生した場合、ログに記録されます。

これはここで見ているものに似ていると思います。

私はこの作業方法が気に入らなかったので、このコードを削除し、単にこれらのメッセージを別のファイルに記録しましたでしたので、それらはすべて存在しましたが、一般的なログファイルを壊しませんでした。

1
Jens Timmerman