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

रूबी में केस स्टेटमेंट्स से बचें: क्लीनर कोड के लिए पॉलीमॉर्फिज्म अपनाएं

क्या आप OOP (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) की पूरी शक्ति का उपयोग कर रहे हैं या आप चूक रहे हैं?

यदि आप किसी ऑब्जेक्ट के प्रकार के आधार पर निर्णय ले रहे हैं तो आप OOP की एक महत्वपूर्ण विशेषता से चूक रहे हैं: पॉलीमॉर्फिज्म।

प्रकार के निर्णय आमतौर पर केस स्टेटमेंट्स के अंदर किए जाते हैं (जो OO फ्रेंडली नहीं हैं) और इस लेख में आप उन्हें हटाकर बेहतर कोड लिखना सीखेंगे।

प्रकारों की जांच

मैं आपको एक उदाहरण दिखाकर शुरू करता हूं जहां हम पॉलीमॉर्फिज्म का लाभ नहीं उठाते।

हम "रॉक, पेपर, सीज़र्स" गेम को लागू करना चाहते हैं और हमने हर संभावित चाल के लिए एक क्लास और एक Game क्लास रखने का फैसला किया है।

विजेता की जांच के लिए हम Game पर एक play मेथड लागू करने जा रहे हैं:

 class Game def self.play(move1, move2) return :tie if move1 == move2 move1.wins_against?(move2) end end 

और यहां चालों में से एक है (अन्य समान पैटर्न का पालन करते हैं):

 class Rock def wins_against?(other_move) case other_move when Paper then false when Scissors then true end end end 

अब हम दो चालों के साथ play मेथड को कॉल कर सकते हैं और हम जान जाएंगे कि पहली चाल जीतती है या नहीं।

 p Game.play(Rock.new, Paper.new) # false 

ठीक है, यह काम कर रहा है, लेकिन क्या हम बेहतर कर सकते हैं? क्या हम उस बदसूरत केस स्टेटमेंट से छुटकारा पा सकते हैं?

टाइप चेकिंग के बजाय पॉलीमॉर्फिज्म

हाँ! हम OOP बुनियादी बातों का उपयोग करके टाइप-चेकिंग केस स्टेटमेंट से छुटकारा पा सकते हैं।

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

और हम एक मेथड नाम का उपयोग करने जा रहे हैं जो हमारी क्लास के लिए विशिष्ट है (Rock के लिए मेथड नाम हो सकता है: do_you_beat_rock?)

रूबी में, पॉलीमॉर्फिज्म किसी ऑब्जेक्ट की क्लास की जांच किए बिना किसी भी ऑब्जेक्ट को किसी भी मेथड कॉल (जिसे OOP शब्दावली में संदेश के रूप में भी जाना जाता है) भेजने की क्षमता है। इसे "डक टाइपिंग" के रूप में भी जाना जाता है, लेकिन मुझे वह शब्द पसंद नहीं है 🙂

जावा में (एक सेकंड के लिए मेरे साथ रहें...), आपके पास "इंटरफेस" नामक कुछ है जो आपको कंपाइलर स्तर पर एक क्लास द्वारा लागू किए जाने वाले मेथड्स के एक सेट को लागू करने की अनुमति देता है।

रूबी में हमारे पास वह नहीं है (शायद बेहतर के लिए), इसलिए आपको टेस्टिंग पर भरोसा करना होगा।

आइए देखें कि यह नया कार्यान्वयन कैसा दिखता है:

 class Rock def wins_against?(other_move) other_move.do_you_beat_rock? end def do_you_beat_paper? false end def do_you_beat_scissors? true end end 

ध्यान दें कि केस स्टेटमेंट चला गया है। इसे एक सिंगल मेथड कॉल और दो मेथड परिभाषाओं द्वारा प्रतिस्थापित किया गया है।

अपडेट: जैसा कि कुछ पाठकों ने टिप्पणी की, मैंने ध्यान नहीं दिया कि इस पैटर्न को लागू करते समय तर्क उल्टा हो जाता है। डैनियल पी. क्लार्क द्वारा प्रस्तावित एक समाधान play मेथड में ऑर्डर को केवल move2.wins_against?(move1) पर फ्लिप करना है।

क्या यह बहुत क्लीनर नहीं है? आप क्या सोचते हैं?

एक और चाल!

अब मान लें कि आप एक नई चाल जोड़ना चाहते हैं। आपको क्या बदलना होगा?

इसके बारे में एक मिनट सोचें...

केस स्टेटमेंट दृष्टिकोण के साथ आपको हर चाल में एक नई शाखा जोड़नी होगी। ध्यान दें कि आप नई कार्यक्षमता पेश करने के लिए एक पूरी तरह से काम करने वाले मेथड को बदलने के लिए "मजबूर" हैं।

लेकिन हमारे अधिक OOP उन्मुख संस्करण के साथ यह कोई समस्या नहीं है। हमें बस नए मेथड्स जोड़ने हैं। यह ओपन/क्लोज्ड सिद्धांत (SOLID में "O") का क्रियान्वयन है।

एक अन्य विकल्प मेटाप्रोग्रामिंग का उपयोग करना हो सकता है (method_missing या define_method के साथ)।

क्या मैं वास्तव में इसके लिए मेटाप्रोग्रामिंग का उपयोग करूंगा?

शायद नहीं, जब तक कि चालों की संख्या लगातार बदल रही न हो, या चालों की बड़ी संख्या न हो।

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

निष्कर्ष

इस लेख में आपने सीखा कि आपको क्लास प्रकारों की जांच के लिए केस स्टेटमेंट्स का उपयोग करने से बचना चाहिए। इसके बजाय, आपको पॉलीमॉर्फिज्म का लाभ उठाना चाहिए।

यह आपको बेहतर कोड बनाने में मदद करेगा जिसे मौजूदा कोड को बदलने के बजाय नया कोड जोड़कर बढ़ाया जा सकता है। अब आपकी बारी है कार्रवाई करने और कुछ रिफैक्टरिंग करने की 🙂

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

अगर आप चाहते हैं कि मैं ऐसे लेख लिखता रहूं तो इस लेख को शेयर करना न भूलें!

  1. रूबी ऑब्जेक्ट्स को डेकोरेटर पैटर्न से बढ़ाएं: एक व्यावहारिक गाइड रूबी ऑब्जेक्ट्स को डेकोरेटर पैटर्न से बढ़ाएं: एक व्यावहारिक गाइड

    डेकोरेटर डिज़ाइन पैटर्न क्या है? और आप इस पैटर्न का उपयोग अपने रूबी प्रोजेक्ट्स में कैसे कर सकते हैं? डेकोरेटर डिज़ाइन पैटर्न आपको क्लास को बदले बिना नई क्षमताएं जोड़कर एक ऑब्जेक्ट को बढ़ाने में मदद करता है। आइए एक उदाहरण देखें! लॉगिंग और प्रदर्शन इस उदाहरण में हम rest-client जैसे जेम का उपयोग करके

  1. रूबी केस स्टेटमेंट्स में महारत: बहुमुखी उपयोग और व्यावहारिक उदाहरण रूबी केस स्टेटमेंट्स में महारत: बहुमुखी उपयोग और व्यावहारिक उदाहरण

    जब भी आपको कुछ if / elsif स्टेटमेंट्स का उपयोग करने की आवश्यकता होती है तो आप इसके बजाय रूबी केस स्टेटमेंट का उपयोग करने पर विचार कर सकते हैं। इस पोस्ट में, आप कुछ अलग उपयोग के मामले सीखेंगे और यह वास्तव में हुड के नीचे कैसे काम करता है। नोट: अन्य प्रोग्रामिंग भाषाओं में इसे स्विच स्टेटमेंट के रूप

  1. रूबी एरे में महारत: व्यावहारिक उदाहरण और आवश्यक मेथड्स रूबी एरे में महारत: व्यावहारिक उदाहरण और आवश्यक मेथड्स

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