MongoDB जावा ड्राइवर सशर्त में यादृच्छिक संख्या जनरेटर का उपयोग क्यों करता है?


211

मैंने MongoDB के जावा कनेक्शन ड्राइवर के लिए इस कमिट में निम्न कोड देखा , और यह पहली बार में किसी प्रकार का मजाक लगता है। निम्नलिखित कोड क्या करता है?

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

(EDIT: इस प्रश्न को पोस्ट करने के बाद से कोड अपडेट किया गया है )


13
इसका कौन सा हिस्सा आपको भ्रमित कर रहा है?
ओलिवर चार्ल्सवर्थ

4
मुझे लगता है कि यह भ्रामक है। इस कोड को कैच ब्लॉक में निष्पादित किया जाता है!
प्रांतीय

11
@MarkoTopolnik: क्या यह है? यह बहुत स्पष्ट रूप से if (!ok || Math.random() < 0.1)(या कुछ इसी तरह) लिखा जा सकता है ।
ओलिवर चार्ल्सवर्थ

5
github.com/mongodb/mongo-java-driver/commit/… आप पहले नहीं हैं, उस लाइन पर टिप्पणी देखें
msangel

3
@msangel वे लोग तर्क की आलोचना करते दिखते हैं, न कि कोडिंग शैली।
मार्को टोपोलनिक

जवाबों:


279

उस पंक्ति के इतिहास का निरीक्षण करने के बाद, मेरा मुख्य निष्कर्ष यह है कि काम में कुछ अक्षम प्रोग्रामिंग हुई है।

  1. उस लाइन को कृतज्ञतापूर्वक समझा जाता है। सामान्य रूप

    a? true : b

    के लिए boolean 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 );
    }

    - अक्षम कोडिंग का आसान उदाहरण है, लेकिन उल्टे तर्क पर ध्यान दें : यहां घटना लॉग की जाती है यदि या तो _ok10% अन्य मामलों में, जबकि 2. में कोड 10% बार लौटता है और 90% बार लॉग होता है। इसलिए बाद में किए गए अपराध ने न केवल स्पष्टता को बर्बाद कर दिया, बल्कि खुद को सही किया।

    मुझे लगता है कि आपके द्वारा पोस्ट किए गए कोड में हम वास्तव में देख सकते हैं कि मूल रूप से मूल रूप से मूल if-thenरूप से अपनी returnस्थिति को बदलने के लिए लेखक का इरादा प्रारंभिक स्थिति के लिए कैसे आवश्यक है । लेकिन फिर उन्होंने गड़बड़ी की और असमानता के संकेत को उल्टा करके एक प्रभावी "डबल नकारात्मक" डाला।

  4. कोडिंग शैली एक तरफ, स्टोकेस्टिक लॉगिंग अपने आप में काफी संदिग्ध अभ्यास है, खासकर जब से लॉग प्रविष्टि अपने अजीब व्यवहार का दस्तावेजीकरण नहीं करती है। इरादा, जाहिर है, एक ही तथ्य के प्रतिबंधों को कम करना है: कि सर्वर वर्तमान में नीचे है। उपयुक्त समाधान केवल सर्वर स्थिति के परिवर्तनों को लॉग करना है , और इसके प्रत्येक अवलोकन को नहीं करना है, अकेले 10% ऐसे टिप्पणियों का यादृच्छिक चयन करें। हां, इसमें थोड़ा और प्रयास करने की जरूरत है, तो चलिए कुछ देखते हैं।

मैं केवल यह आशा कर सकता हूं कि कोड की सिर्फ तीन पंक्तियों का निरीक्षण करने से संचित अक्षमता के यह सभी साक्ष्य, समग्र रूप से परियोजना के बारे में अच्छी तरह से नहीं बोलते हैं, और यह कि यह काम ASAP को साफ कर देगा।


26
इसके अतिरिक्त यह प्रतीत होता है, जहाँ तक मैं बता सकता हूँ, MongoDB के लिए आधिकारिक 10gen जावा चालक, जावा चालक पर एक राय होने के अलावा, मुझे लगता है कि यह मुझे MongoDB के कोड पर एक राय देता है
क्रिस ट्रैवर्स

5
कोड की सिर्फ कुछ पंक्तियों का उत्कृष्ट विश्लेषण, मैं इसे बस एक साक्षात्कार प्रश्न में बदल सकता हूं! आपका चौथा बिंदु असली कुंजी है कि इस परियोजना के साथ मौलिक रूप से कुछ गलत क्यों है (दूसरों को दुर्भाग्यपूर्ण प्रोग्रामर के कीड़े के रूप में खारिज किया जा सकता है)।
हाबिल

1
@ChrisTravers यह है मोंगो के लिए सरकारी मोंगो जावा ड्राइवर।
assylias

17

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

11 घंटे पहले gareth-rees द्वारा:

संभवतः यह विचार है कि सर्वर विफलताओं के बारे में केवल 1/10 लॉग करें (और इसलिए काउंटर या टाइमर को बनाए रखने की लागत के बिना, लॉग से बड़े पैमाने पर स्पैमिंग से बचें)। (लेकिन निश्चित रूप से एक टाइमर बनाए रखना सस्ता होगा?)


13
नाइटपिक के लिए नहीं, लेकिन: 1/10 वें समय यह फिर से लौट आएगा, इसलिए यह अन्य 9/10 बार लॉग करेगा।
सुपरसील

23
@ खुशामद निश्चित रूप से नहीं है। इस व्यक्ति की भयानक कोडिंग प्रथाओं के बारे में अभी और सबूत हैं।
औरोव

7

नकारात्मक 1 के लिए प्रारंभिक श्रेणी सदस्य जोड़ें:

  private int logit = -1;

कोशिश ब्लॉक में, परीक्षण करें:

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

यह हमेशा पहली त्रुटि, उसके बाद हर दसवीं त्रुटि को लॉग करता है। लॉजिकल ऑपरेटर्स "शॉर्ट-सर्किट", इसलिए लॉगिट केवल एक वास्तविक त्रुटि पर बढ़ जाता है।

यदि आप कनेक्शन की परवाह किए बिना सभी त्रुटियों में से पहला और दसवां हिस्सा चाहते हैं, तो आ सदस्य के बजाय लॉगिट क्लास को स्थिर बनाएं।

जैसा कि नोट किया गया था कि यह धागा सुरक्षित होना चाहिए:

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

कोशिश ब्लॉक में, परीक्षण करें:

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

नोट: मुझे नहीं लगता कि 90% त्रुटियों को फेंकना एक अच्छा विचार है।


1

मैंने इस तरह की चीज पहले भी देखी है।

कोड का एक टुकड़ा था जो कुछ 'सवालों' का जवाब दे सकता था जो कोड के दूसरे 'ब्लैक बॉक्स' से आया था। इस मामले में यह उन्हें जवाब नहीं दे सका, यह उन्हें 'ब्लैक बॉक्स' कोड के एक और टुकड़े के लिए अग्रेषित करेगा जो वास्तव में धीमा था।

इसलिए कभी-कभी पहले अनदेखे नए 'प्रश्न' दिखाई देंगे, और वे एक बैच में दिखाए जाएंगे, जैसे उनमें से 100 पंक्ति में।

प्रोग्रामर कैसे काम कर रहा था, इससे खुश था, लेकिन वह भविष्य में सॉफ्टवेयर में सुधार के कुछ तरीके चाहते थे, यदि संभव हो तो नए प्रश्न खोजे जाते।

इसलिए, समाधान अज्ञात प्रश्नों को लॉग इन करना था, लेकिन जैसा कि यह निकला, 1000 अलग-अलग थे। लॉग बहुत बड़े हो गए, और इनमें तेजी लाने का कोई लाभ नहीं था, क्योंकि उनके पास कोई स्पष्ट जवाब नहीं था। लेकिन हर बार एक समय में, प्रश्नों का एक समूह दिखाई देगा जो उत्तर दिया जा सकता है।

चूंकि लॉग बहुत बड़े हो रहे थे, और लॉगिंग इस समाधान को प्राप्त करने वाली वास्तविक महत्वपूर्ण चीजों को लॉग करने के तरीके में हो रही थी:

केवल एक यादृच्छिक 5% लॉग इन करें, यह लॉग्स को साफ करेगा, जबकि लंबे समय में अभी भी दिखा रहा है कि कौन से प्रश्न / उत्तर जोड़े जा सकते हैं।

इसलिए, यदि कोई अज्ञात घटना घटती है, तो इन मामलों की एक यादृच्छिक मात्रा में, इसे लॉग किया जाएगा।

मुझे लगता है कि यह वही है जो आप यहां देख रहे हैं।

मुझे काम करने का यह तरीका पसंद नहीं था, इसलिए मैंने इस कोड को हटा दिया, और बस इन संदेशों को एक अलग फ़ाइल में लॉग इन किया , इसलिए वे सभी मौजूद थे, लेकिन सामान्य लॉगफ़ाइल को क्लॉबरिंग नहीं कर रहे थे।


3
सिवाय इसके कि हम एक डेटाबेस ड्राइवर के बारे में यहाँ बात कर रहे हैं ... गलत समस्या स्थान, IMO!
स्टीवन श्लांसकर

@StevenSchlansker मैंने कभी नहीं कहा कि यह एक अच्छा अभ्यास था। मैंने इस कोड को हटा दिया, और बस इन संदेशों को एक अलग फ़ाइल में लॉग इन किया।
जेन्स टिम्मरमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.