[java] MongoDB Java 드라이버가 조건부에서 난수 생성기를 사용하는 이유는 무엇입니까?

나는 다음 코드를 보았다 커밋이 를 위해 MongoDB의 자바 연결 드라이버 , 어떤 종류의 농담 먼저 나타납니다. 다음 코드는 무엇을합니까?

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

(편집 : 이 질문을 게시 한 후 코드 가 업데이트되었습니다 )



답변

그 라인의 역사를 조사한 후, 나의 주요 결론은 직장에서 무능한 프로그래밍이 있었다는 것입니다.

  1. 그 선은 사실 복잡하다. 일반적인 형태

    a? true : b

    에 대한 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 );
    }

    — 무능한 코딩의 또 다른 예이지만 반대 논리를 주목하십시오 . 여기서는 _ok다른 경우 중 하나 또는 10 % 인 경우 이벤트가 기록되는 반면 2의 코드 10 %의 시간을 반환 하고 90 %의 시간을 기록합니다. 따라서 나중에 커밋은 명확성뿐만 아니라 정확성 자체를 망쳤습니다.

    나는 당신이 게시 한 코드에서 실제로 저자가 if-then어떻게 원본을 초기 return상태에 필요한 부정으로 어떻게 변형 시켰는지 알 수 있다고 생각 합니다. 그러나 그는 불평등을 뒤집어서 효과적인 “이중 부정”을 엉망으로 만들었습니다.

  4. 코딩 스타일 문제는 제쳐두고, 확률 적 로깅은 그 자체로는 상당히 모호한 관행입니다. 특히 로그 항목에는 고유 한 동작이 문서화되어 있지 않기 때문입니다. 서버의 현재 다운 상태와 같은 사실에 대한 설명을 줄이려는 의도는 분명합니다. 적절한 해결책은 10 %의 임의의 관찰을 제외하고 각각의 관찰이 아닌 서버 상태의 변경 사항 만 기록하는 입니다. 그렇습니다. 조금만 더 노력하면됩니다.

나는 단지 세 줄의 코드 를 검사하여 축적 된이 무능의 모든 증거가 프로젝트 전체를 공정하게 말하지 않고,이 작업이 최대한 빨리 정리 되기를 바랄 뿐입니다 .


답변

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

11 시간 전 gareth-rees에 의해 :

아마도 카운터 또는 타이머를 유지 관리하는 비용을 발생시키지 않으면 서 서버 장애의 약 1/10 만 기록하므로 대량 스팸을 피하는 것이 좋습니다. (그러나 타이머를 유지하는 것이 합리적입니까?)


답변

음수 1로 초기화 된 클래스 멤버를 추가하십시오.

  private int logit = -1;

try 블록에서 테스트를 수행하십시오.

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

이것은 항상 첫 번째 오류를 기록한 다음 10 번째 후속 오류를 기록합니다. 논리 연산자는 “단락”하므로 실제 오류시에만 로짓이 증가합니다.

연결에 관계없이 모든 오류 중 첫 번째와 열 번째 오류 를 원하면 멤버 대신 로짓 클래스를 정적으로 만드십시오.

언급했듯이 이것은 스레드 안전해야합니다.

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

try 블록에서 테스트를 수행하십시오.

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

참고 : 오류의 90 %를 버리는 것은 좋은 생각이 아닙니다.


답변

나는 이런 종류의 것을 전에 보았다.

다른 ‘블랙 박스’코드 조각에서 온 특정 ‘질문’에 응답 할 수있는 코드 조각이있었습니다. 응답 할 수없는 경우 실제로 느린 다른 ‘블랙 박스’코드로 전달합니다.

따라서 때때로 이전에 보지 못한 새로운 ‘질문’이 나타나고 100 개가 연속으로 배치되는 것처럼 배치로 나타납니다.

프로그래머는 프로그램의 작동 방식에 만족했지만 새로운 질문이있을 경우 향후 소프트웨어를 개선 할 수있는 방법을 원했습니다.

따라서 해결책은 알 수없는 질문을 기록하는 것이었지만 결과적으로 1000 개의 다른 질문이있었습니다. 로그가 너무 커져서 명확한 대답이 없었기 때문에 속도를 높이는 이점이 없었습니다. 그러나 가끔씩 대답 할 수있는 일련의 질문이 나타납니다.

로그가 너무 커지고 로깅이이 솔루션에 얻은 실제 중요한 사항을 로깅하는 방식으로 진행되고 있기 때문에 :

무작위로 5 % 만 기록하면 장기적으로 로그에 추가되는 질문 / 응답이 표시되는 동안 로그가 정리됩니다.

따라서 알 수없는 이벤트가 발생하면 임의의 경우에 기록됩니다.

나는 이것이 당신이보고있는 것과 유사하다고 생각합니다.

나는이 작업 방식이 마음에 들지 않았 으므로이 코드를 제거 하고이 메시지를 다른 파일 에 기록 했으므로 모두 존재했지만 일반 로그 파일을 방해하지는 않았습니다.


답변