Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

रूबी में एसिंक्रोनस थ्रेड टेस्टिंग में महारत: सर्वोत्तम अभ्यास और पैटर्न

थ्रेड्स और एसिंक्रोनस वातावरण शुरू में थोड़े मुश्किल होते हैं। इंटरैक्शन को व्यवस्थित करने के लिए एक अच्छे मानसिक मॉडल के बिना, मुसीबत में पड़ना और अप्रत्याशित परिणामों के साथ समाप्त होना आसान है। उसके ऊपर, सही उपकरण या टेस्ट पैटर्न के बिना एसिंक्रोनस कोड का टेस्ट करना मुश्किल हो सकता है।

थ्रेड्स को लोगों के रूप में और शेयर्ड ऑब्जेक्ट्स को 'चीजों' के रूप में सोचना जो किसी एक व्यक्ति के स्वामित्व में हो सकती हैं, एक मल्टीथ्रेडेड सिस्टम के कामकाज को व्यवस्थित करने में मदद करता है। इस एपिसोड में हम एक उदाहरण के माध्यम से एसिंक्रोनस रूबी कोड के टेस्टिंग के बारे में सब कुछ सीखने जा रहे हैं।

यदि आप रेल्स या रैक या वास्तव में किसी ऐसे एप्लिकेशन का उपयोग कर रहे हैं जिसका वेब ब्राउज़र फ्रंट एंड है तो आप एक एसिंक्रोनस वातावरण में हैं। रैक #call को हमेशा एसिंक्रोनस रूप से कॉल किया जाता है। तो चाहे आप इसे जानते हों या नहीं, एक अच्छा मौका है कि आप पहले से ही मल्टीथ्रेडेड घटकों का उपयोग कर रहे हैं।

टेस्टिंग: ट्रिगर, कलेक्ट, और चेक

एक एसिंक्रोनस कॉलबैक API के टेस्टिंग को तीन चरणों के पैटर्न का पालन करके सिंक्रोनस बनाया जा सकता है; ट्रिगर, कलेक्ट, और चेक। प्रत्येक थ्रेड को एक अलग व्यक्ति के रूप में सोचें और ऑब्जेक्ट्स को, ठीक है, उन चीजों के रूप में जिन्हें एक समय में केवल एक व्यक्ति द्वारा स्वामित्व में रखा जा सकता है।

हम बैटमैन और उसके 7 अलग-अलग सूट्स के उदाहरण का उपयोग करेंगे। क्योंकि यह एक व्यावहारिक उदाहरण है और हम यह समझ सकते हैं कि यह जानना कितना महत्वपूर्ण है कि जब आप शहर को बचाने के लिए बाहर निकलने वाले होते हैं तो सभी सूट्स अल्फ्रेड के साथ धोने के लिए हैं या नहीं।

उदाहरण: बैटकेव में लॉन्ड्री डे

उदाहरण अल्फ्रेड द्वारा बैटमैन के सूट्स धोने का है। SuitWashScheduler एक शेड्यूलर है जो प्रत्येक वॉशिंग इवेंट के लिए एक कॉलबैक लागू करता है। शेड्यूलर शुरू होने के एक सेकंड बाद एक-सेकंड के अंतराल पर सात कॉलबैक बनाता है। ट्रिगर SuitWashScheduler का निर्माण है।

class SuitWashScheduler def initialize(cnt) Thread.new { cnt.times { sleep(1.0) yield } } end end

कलेक्टिंग

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

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

उदाहरण लिखना कुछ ग्लोबल्स सेटअप करने से शुरू होता है। एक वास्तविक एप्लिकेशन में ग्लोबल्स को क्लास या ऑब्जेक्ट एट्रिब्यूट्स द्वारा प्रतिस्थापित किया जाएगा।

$main_thread = Thread.current $mu = Mutex.new $count = 0 $target = 7

प्रबंधन और मालिक

$main_thread और $mu का उपयोग थ्रेड्स को प्रबंधित करने और टेस्ट के पूरा होने की प्रतीक्षा करने के लिए किया जाता है जबकि $target और $count टेस्ट परिणामों को ट्रैक करते हैं। याद रखें यह एक तुच्छ टेस्ट है इसलिए परिणामों को एकत्र करना और जांचना सरल होना चाहिए।

टेस्ट SuitWashScheduler का एक नया इंस्टेंस बनाकर शुरू किया जाता है, इनिशियलाइज़र को $target इटरेशन्स की संख्या देकर। इस मामले में, धोने की आवश्यकता वाले 7 सूट्स। प्रदान किया गया ब्लॉक SuitWashScheduler थ्रेड में चलाया जाएगा। प्रत्येक इटरेशन के लिए $count बढ़ाया जाता है और प्रिंट किया जाता है।

आगे देखते हुए हमें एहसास होता है कि मुख्य, टेस्ट थ्रेड $count की जांच करने वाला भी है जिसका अर्थ है कि इसे $count के स्वामित्व की भी आवश्यकता होगी इसलिए $count का स्वामित्व लेने का एक साधन आवश्यक है। $mu Mutex इंस्टेंस स्वामित्व टोकन है। SuitWashScheduler.new कॉल को पास किए गए ब्लॉक में एक $mu.synchronize ब्लॉक $count को सेट करने और परिणामों की जांच करने के लिए पर्याप्त समय तक स्वामित्व लेता है। परिणाम जांच पर एक पल में और अधिक।

SuitWashScheduler.new($target) { $mu.synchronize { $count += 1 puts $count $main_thread.wakeup if $target <= $count } }

चेक: क्या सभी सूट्स हो गए?

मुख्य थ्रेड पर वापस हमें टेस्ट के खत्म होने की प्रतीक्षा करने की आवश्यकता है। बैटमैन को सभी 7 सूट्स के पूरा होने से पहले प्रतीक्षा करने की आवश्यकता है। जांच के लिए दो शर्तें हैं; टेस्ट अपेक्षा के अनुसार $count को अपडेट करता है या बैटमैन टेस्ट के खत्म होने की प्रतीक्षा करते हुए ऊब जाता है और टाइम आउट हो जाता है। $count की जांच करने से पहले यह देखने के लिए कि क्या यह $target तक पहुंच गया है, $count का स्वामित्व आवश्यक है। SuitWashScheduler के लिए ब्लॉक की तरह ही $mu.synchronize को कॉल किया जाता है।

लेकिन यह सही नहीं हो सकता, अगर हम मुख्य थ्रेड को लॉक कर दें तो SuitWashScheduler थ्रेड कभी $count को कैसे बदल सकता है? सौभाग्य से हमारे लिए एक साफ-सुथरी ट्रिक है जो इसका ख्याल रखती है। Mutex क्लास में एक #sleep विधि है जो स्वामित्व छोड़ देती है और तब तक प्रतीक्षा करती है जब तक यह टाइम आउट नहीं हो जाता या जागृत नहीं हो जाता। एक बार जागृत होने पर या तो टाइमआउट के माध्यम से या मुख्य थ्रेड $mu पर #wakeup कॉल के माध्यम से $mu जारी रखने से पहले फिर से स्वामित्व लेने का प्रयास करता है। एक बार स्वामित्व हासिल हो जाने पर परिणामों की जांच की जा सकती है और टेस्ट के पास या फेल स्थिति का निर्धारण किया जा सकता है।

$mu.synchronize { $mu.sleep($target + 1) if $target != $count puts 'FAILED' else puts 'Passed! All suits are washed and clean' end }

यदि आप इसमें गहराई से जाना चाहते हैं, तो आप कई शेड्यूलर्स बनाने की कोशिश करके उदाहरण को थोड़ा अधिक रोचक बना सकते हैं और देख सकते हैं कि Mutex $count परिवर्तनों को टकराने से कैसे रोकता है। जैसे बैटमैन कुछ सूट्स को अल्फ्रेड के पास धोने के लिए भेजता है, और कुछ अन्य को ड्राई क्लीनर्स के पास। $target चेक को सभी अपेक्षित यील्ड्स के कुल में बदलने के लिए तर्क को बदलना सुनिश्चित करें।

राउंडअप

सही मानसिक मॉडल के साथ थ्रेड्स और एसिंक्रोनस वातावरण के साथ काम करना आसान हो जाता है। इस पोस्ट में हमने थ्रेड्स के लिए लोगों के रूपक और भौतिक वस्तुओं (सूट्स) के रूपक का उपयोग शेयर्ड ऑब्जेक्ट्स के लिए किया, जिन्हें एक समय में केवल एक थ्रेड या व्यक्ति द्वारा स्वामित्व में रखा जा सकता है। हमें लगता है कि इस तरह से अमूर्त करना इसे समझने और याद रखने में आसान बनाता है।

हम आशा करते हैं कि उदाहरण आपको एसिंक्रोनस के तंत्र को याद रखने में मदद करेंगे, लेकिन हम आशा करते हैं कि बैटमैन के बाहर निकलने की छवि जबकि उसके सभी सूट्स धोए जा रहे हैं, बहुत लंबे समय तक आपके साथ नहीं रहेगी।

P.S. यदि आप ब्लॉग पर सभी बैटमैन रूपकों से थक गए हैं, तो हमें बताएं।

  1. टेस्ट-कमिट-रिवर्ट: लिगेसी रूबी कोड को सुरक्षित रूप से टेस्ट करने के लिए एक व्यावहारिक वर्कफ़्लो टेस्ट-कमिट-रिवर्ट: लिगेसी रूबी कोड को सुरक्षित रूप से टेस्ट करने के लिए एक व्यावहारिक वर्कफ़्लो

    यह हम सभी के साथ होता है। जैसे-जैसे सॉफ़्टवेयर प्रोजेक्ट बढ़ते हैं, कोडबेस के कुछ हिस्से एक व्यापक टेस्ट सूट के बिना प्रोडक्शन में चले जाते हैं। जब आप कुछ महीनों बाद कोड के उसी क्षेत्र को फिर से देखते हैं, तो इसे समझना मुश्किल हो सकता है; इससे भी बदतर, इसमें एक बग हो सकता है, और हमें नहीं पता कि इसे

  1. Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण

    Ruby का एक नया संस्करण नई सुविधाओं और प्रदर्शन सुधारों के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज (Endless Ranges) Ruby 2.5 और पुराने संस्करण पहले से ही अंतहीन रेंज का एक रूप (Float::INFINITY के साथ) का समर्थन करते हैं, लेकिन Ruby 2.6 इसे अगले स्त

  1. रूबी थ्रेड्स में महारत: मल्टीथ्रेडिंग के लिए एक शुरुआती-अनुकूल गाइड रूबी थ्रेड्स में महारत: मल्टीथ्रेडिंग के लिए एक शुरुआती-अनुकूल गाइड

    रूबी में थ्रेड क्या है? थ्रेड्स आपके रूबी प्रोग्राम्स को एक ही समय में कई चीजें करने देते हैं। जैसी चीजें: एकाधिक फाइलें पढ़ना एकाधिक वेब अनुरोधों को संभालना एकाधिक API कनेक्शन बनाना थ्रेड्स का उपयोग करने के परिणामस्वरूप, आपके पास एक मल्टी-थ्रेडेड रूबी प्रोग्राम होगा, जो चीजों को तेजी से पूरा करने