Dlaczego sterownik Java MongoDB używa generatora liczb losowych w trybie warunkowym?

Widziałem poniższy kod ww tym zatwierdzeniu dlaSterownika połączenia Java MongoDB i na początku wydaje się to żartem. Do czego służy poniższy kod?

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

(EDIT: the code has been updated since posting this question)

Author: Joe, 2013-05-30

4 answers

Po zapoznaniu się z historią tej linii, mój główny wniosek jest taki, że w pracy było trochę niekompetentnego programowania.

  1. Ta linia jest bezinteresownie zawiła. Forma ogólna

    a? true : b
    

    Dla {[4] } jest równoważne prostej

    a || b
    
  2. Otaczająca negacja i nadmierne nawiasy splatają sprawy dalej. Mając na uwadze prawa De Morgana jest trywialną obserwacją, że ten fragment kodu wynosi do

    if (!_ok && Math.random() <= 0.1)
      return res;
    
  3. Commit, który pierwotnie wprowadził tę logikę miał

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

    - kolejny przykład niekompetentnego kodowania, ale zwróć uwagę na odwróconą logikę : tutaj zdarzenie jest rejestrowane, jeśli _ok lub w 10% innych przypadków, podczas gdy kod w 2. zwraca 10% razy i rejestruje 90% razy. Tak więc późniejsze zatwierdzenie zrujnowało nie tylko klarowność, ale samą poprawność.

    Myślę, że w kodzie, który napisałeś, możemy zobaczyć, jak autor zamierzał przekształcić oryginał if-then w jakiś sposób dosłownie w jego negację wymaganą dla wczesnego return warunku. Ale potem schrzanił i wstawił skuteczny "podwójny negatyw", odwracając znak nierówności.

  4. Pomijając kwestie stylu kodowania, logowanie stochastyczne jest dość wątpliwą praktyką samą w sobie, zwłaszcza że wpis dziennika nie dokumentuje własnego osobliwego zachowania. Intencją jest oczywiście zmniejszenie tego samego faktu: że serwer obecnie nie działa. Odpowiednim rozwiązaniem jest rejestrowanie tylko zmian stanu serwera, a nie każdej jego obserwacji, nie mówiąc już o losowym doborze 10% takich obserwacji. Tak, to wymaga trochę więcej wysiłku, więc zobaczmy trochę.

Mogę tylko mieć nadzieję, że wszystkie te dowody niekompetencji, zgromadzone po sprawdzeniu tylko trzech linijek kodu , nie mówią rzetelnie o projekcie jako całości, i że ten kawałek pracy zostanie oczyszczony Jak najszybciej.

 270
Author: Marko Topolnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-11 13:15:23

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

11 godzin temu przez gareth-rees:

Przypuszczalnie chodzi o to, aby logować tylko około 1/10 awarii serwera (a więc uniknąć masowego spamowania dziennika), bez ponoszenia kosztów utrzymania licznika lub timera. (Ale na pewno utrzymanie timera byłoby niedrogie?)

 16
Author: msangel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-30 10:05:28

Dodaj członka klasy inicjalizowanego do ujemnego 1:

  private int logit = -1;

W bloku try wykonaj test:

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

To zawsze rejestruje pierwszy błąd, a następnie co dziesiąty kolejny błąd. Operatory logiczne "zwarcie", więc logit jest zwiększany tylko w przypadku rzeczywistego błędu.

Jeśli chcesz, aby pierwszy i dziesiąty z wszystkich błędów, niezależnie od połączenia, uczyń klasę logit statyczną zamiast członka A.

Jak już wspomniano, powinno to być wątek Bezpieczny:

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

W bloku try wykonaj test:

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

Uwaga: nie sądzę, aby wyrzucanie 90% błędów było dobrym pomysłem.

 7
Author: tpdi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-02 09:45:55

Widziałem już takie rzeczy.

Był kawałek kodu, który mógł odpowiedzieć na pewne "pytania", które pochodziły z innej "czarnej skrzynki". W przypadku, gdy nie mógł na nie odpowiedzieć, przekazywałby je do innego kawałka kodu "czarnej skrzynki", który był naprawdę powolny.

Tak więc czasami pojawiały się nieznane wcześniej nowe "pytania" i pojawiały się w partii, jak 100 z rzędu.

Programista był zadowolony z działania programu, ale chciał w jakiś sposób poprawić oprogramowanie w przyszłości, jeśli to możliwe, nowe pytania zostały odkryte.

Rozwiązaniem było więc zalogowanie nieznanych pytań, ale jak się okazało, było ich 1000. Dzienniki stały się zbyt duże i nie było korzyści z ich przyspieszenia, ponieważ nie mieli oczywistych odpowiedzi. Ale co jakiś czas pojawiało się mnóstwo pytań, na które można było odpowiedzieć.

Ponieważ logi stawały się za duże, a wyrębki dostały się do sposób zapisywania naprawdę ważnych rzeczy, które dostał do tego rozwiązania:

Tylko Zaloguj losowe 5% , to wyczyści dzienniki, podczas gdy w dłuższej perspektywie nadal pokazuje, jakie pytania/odpowiedzi można dodać.

Tak więc, gdyby miało miejsce nieznane Zdarzenie, w losowej ilości tych przypadków, byłoby ono rejestrowane.

Myślę, że to jest podobne do tego, co widzisz tutaj.

Nie podobał mi się ten sposób działania, więc usunąłem ten fragment kodu i po prostu zarejestrowałem te Wiadomości do a inny plik , więc wszystkie były obecne, ale nie naruszały ogólnego pliku dziennika.

 1
Author: Jens Timmerman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-07 12:06:35