MongoDB Java sürücüsü neden koşullu olarak rasgele sayı üreteci kullanıyor?


211

MongoDB Java Bağlantı sürücüsü için bu taahhütte aşağıdaki kodu gördüm ve ilk başta bir şaka gibi görünüyor. Aşağıdaki kod ne işe yarar?

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

(DÜZENLEME: kod bu soruyu yayınladıktan sonra güncellendi )


13
Hangi kısmı sizi şaşırtıyor?
Oliver Charlesworth

4
bence kafa karıştırıcı. bu kod bir catch bloğunda yürütülür!
Proviste

11
@MarkoTopolnik: Öyle mi? O if (!ok || Math.random() < 0.1)(veya benzeri) çok daha açık bir şekilde yazılabilir .
Oliver Charlesworth

5
github.com/mongodb/mongo-java-driver/commit/… ilk değilsiniz, bu satıra yorum yapın
msangel

3
@msangel Bu adamlar kodlama stilini değil mantığı eleştiriyor gibi görünüyor.
Marko Topolnik

Yanıtlar:


279

Bu hattın tarihini inceledikten sonra, asıl sonucum, iş yerinde bazı yetersiz programlamaların olduğudur.

  1. Bu çizgi minnetle kıvrık. Genel form

    a? true : b

    için boolean a, bbasit ile eşdeğerdir

    a || b
  2. Etraftaki olumsuzlama ve aşırı parantezler işleri daha da katıştırıyor. De Morgan'ın yasalarını akılda tutarak , bu kod parçasının

    if (!_ok && Math.random() <= 0.1)
      return res;
  3. O taahhüt başlangıçta bu mantığı tanıtıldı vardı

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

    - yetersiz kodlamanın başka bir örneği, ancak ters mantığa dikkat edin : burada olay, ya _okda diğer vakaların% 10'unda ise günlüğe kaydedilir , oysa 2.'deki kod zamanların% 10'unu döndürür ve zamanların% 90'ını günlüğe kaydeder. Böylece daha sonraki taahhüt sadece açıklığı değil, doğruluğu da mahvetti.

    Gönderdiğiniz kodda aslında yazarın orijinali bir if-thenşekilde kelimenin tam anlamıyla erken returndurum için gerekli olan olumsuzluğuna dönüştürmeyi amaçladığını görebiliriz . Ama sonra berbat etti ve eşitsizlik işaretini tersine çevirerek etkili bir "çift negatif" ekledi.

  4. Stil sorunlarını bir kenara koyarsak, özellikle log girişi kendi kendine özgü davranışını belgelemediği için stokastik loglama tek başına oldukça şüpheli bir uygulamadır. Amaç, aynı gerçeğin yeniden ifadelerini azaltmaktır: sunucunun şu anda kapalı olması. Uygun çözüm, bu tür gözlemlerin rastgele% 10'unu seçmesine izin vermek yerine, her birinin gözlemini değil, yalnızca sunucu durumundaki değişiklikleri günlüğe kaydetmektir . Evet, bu biraz daha fazla çaba gerektiriyor, bu yüzden biraz görelim.

Sadece üç kod satırını incelemekle biriken tüm bu yetersizlik kanıtlarının projenin bir bütün olarak adil bir şekilde konuşmamasını ve bu çalışmanın en kısa sürede temizleneceğini umuyorum.


26
Buna ek olarak, bu söyleyebildiğim kadarıyla, MongoDB için resmi 10gen Java sürücüsü gibi görünüyor, bu yüzden Java sürücüsü hakkında bir görüşe sahip olmanın yanı sıra, bana MongoDB kodu hakkında bir fikir verdiğini düşünüyorum
Chris Travers

5
Sadece birkaç satır kodun mükemmel analizi, onu bir röportaj sorusuna dönüştürebilirim! Dördüncü noktanız, bu projede temelde yanlış olan bir şeyin neden gerçek anahtarıdır (diğerleri talihsiz programcının hataları olarak reddedilebilir).
Abel

1
@ChrisTravers O olduğu Mongo'da için resmi Mongo java sürücüsü.
assylias

17

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

11 saat önce gareth-rees:

Muhtemelen fikir, bir sayaç veya zamanlayıcı tutmanın maliyeti olmadan, sunucu hatalarının sadece yaklaşık 1 / 10'unu günlüğe kaydetmektir (ve böylece günlüğü büyük oranda spam etmekten kaçının). (Ama elbette bir zamanlayıcıyı korumak uygun olur mu?)


13
Nitpick için değil ama: 1/10 kez res dönecektir, bu yüzden diğer 9/10 kez günlüğe kaydedecektir.
Supericy

23
@Supericy Bu kesinlikle nitpicking değil. Bu, bu kişinin korkunç kodlama uygulamalarına dair daha fazla kanıt.
Anorov

7

Negatif 1 olarak başlatılmış bir sınıf üyesi ekleyin:

  private int logit = -1;

Deneme bloğunda testi yapın:

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

Bu her zaman ilk hatayı, ardından sonraki onuncu hatayı günlüğe kaydeder. Mantıksal işleçler "kısa devre", bu nedenle logit yalnızca gerçek bir hatada artar.

Eğer hepsinin ilkini ve onda birini istiyorsanızBağlantıdan bağımsız hataların aa yerine logit sınıfını statik yapın.

Belirtildiği gibi, bu iplik güvenli olmalıdır:

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

Deneme bloğunda testi yapın:

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

Not: Hataların% 90'ını atmanın iyi bir fikir olduğunu düşünmüyorum.


1

Daha önce böyle bir şey gördüm.

Başka bir 'kara kutu' kod parçasından gelen belirli 'sorulara' cevap verebilecek bir kod parçası vardı. Onlara cevap veremediği takdirde, onları gerçekten yavaş olan başka bir 'kara kutu' koduna yönlendirirdi.

Bu yüzden bazen daha önce görülmemiş yeni 'sorular' ortaya çıkacak ve 100 gibi üst üste görünecekler.

Programcı, programın çalışma şeklinden memnun kaldı, ancak gelecekte yazılımın geliştirilmesinin bir yolunu istedi, mümkünse yeni sorular keşfedildi.

Yani, çözüm bilinmeyen soruları kaydetmekti, ama ortaya çıktığı gibi 1000 farklı soru vardı. Günlükler çok büyüdü ve açık bir cevabı olmadığı için bunları hızlandırmanın bir yararı yoktu. Ancak arada bir, cevaplanabilecek bir grup soru ortaya çıkacaktır.

Günlükler çok büyük olduğundan ve günlük tutma, bu çözüme ulaştığı önemli şeyleri günlüğe kaydetme yolunda ilerlediğinden:

Sadece% 5 rastgele bir giriş yapın, bu günlükleri temizlerken uzun vadede hangi soruların / cevapların eklenebileceğini gösterir.

Bu nedenle, bilinmeyen bir olay meydana gelirse, bu vakaların rastgele bir miktarına kaydedilir.

Bence bu, burada gördüğünüze benziyor.

Bu şekilde çalışma hoşuma gitmedi, bu yüzden bu kod parçasını kaldırdım ve sadece bu mesajları farklı bir dosyaya kaydettim , bu yüzden hepsi mevcuttu, ancak genel günlük dosyasını toparlamıyorlardı.


3
Burada bir veritabanı sürücüsünden bahsetmemiz dışında ... yanlış sorun alanı, IMO!
Steven Schlansker

@StevenSchlansker Bunun iyi bir uygulama olduğunu söylemedim. Bu kod parçasını kaldırdım ve bu mesajları farklı bir dosyaya kaydettim.
Jens Timmerman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.