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

मेटाप्रोग्रामिंग की वास्तविक लागत: जो आपको जानना आवश्यक है

मेटाप्रोग्रामिंग बहुत फैंसी शब्द लगता है, लेकिन क्या यह अच्छा है?

यह उपयोगी हो सकता है, लेकिन बहुत से लोग यह नहीं समझते कि मेटाप्रोग्रामिंग का उपयोग करने की कुछ लागतें हैं।

बस ताकि हम एक ही पेज पर हों...

मेटाप्रोग्रामिंग वास्तव में क्या है?

मैं मेटाप्रोग्रामिंग को किसी भी मेथड का उपयोग करने के रूप में परिभाषित करता हूं जो:

  • आपके कोड की संरचना को बदलता है (जैसे define_method)
  • स्ट्रिंग को चलाता है जैसे कि यह आपके वास्तविक रूबी कोड का हिस्सा था (जैसे instance_eval)
  • किसी घटना की प्रतिक्रिया के रूप में कुछ करता है (जैसे method_missing)

तो मेटाप्रोग्रामिंग की लागतें क्या हैं? मैं उन्हें 3 समूहों में वर्गीकृत करता हूं:

  • गति
  • पठनीयता
  • खोजने योग्यता

नोट: आप यह भी कह सकते हैं कि चौथा समूह है: सुरक्षा. इसका कारण eval मेथड्स हैं, जो पास की जा रही चीज़ पर किसी भी प्रकार की सुरक्षा जांच नहीं करते। आपको इसे स्वयं करना होगा।

आइए उनमें से प्रत्येक को विस्तार से जानें!

गति

पहली लागत गति है क्योंकि अधिकांश मेटाप्रोग्रामिंग मेथड्स नियमित मेथड्स की तुलना में धीमे होते हैं।

यहां कुछ बेंचमार्किंग कोड है:

 require 'benchmark/ips' class Thing def method_missing(name, *args) end def normal_method end define_method(:speak) {} end t = Thing.new Benchmark.ips do |x| x.report("normal method") { t.normal_method } x.report("missing method") { t.abc } x.report("defined method") { t.speak } x.compare! end 

परिणाम (रूबी 2.2.4):

 normal method: 7344529.4 i/s defined method: 5766584.9 i/s - 1.34x slower missing method: 4777911.7 i/s - 1.54x slower 

जैसा कि आप देख सकते हैं दोनों मेटाप्रोग्रामिंग मेथड्स (define_method और method_missing) नियमित मेथड की तुलना में काफी धीमे हैं।

यहां कुछ दिलचस्प है जो मैंने खोजा...

उपरोक्त परिणाम Ruby 2.2.4 से हैं, लेकिन यदि आप इन बेंचमार्क को Ruby 2.3 या Ruby 2.4 पर चलाते हैं तो ऐसा लगता है कि ये मेथड्स और धीमे हो रहे हैं!

रूबी 2.4 बेंचमार्क परिणाम:

 normal method: 8252851.6 i/s defined method: 6153202.9 i/s - 1.39x slower missing method: 4557376.3 i/s - 1.87x slower 

मैंने यह बेंचमार्क कई बार चलाया ताकि यह सुनिश्चित हो सके कि यह कोई अस्थायी नहीं था।

लेकिन यदि आप ध्यान दें और प्रति सेकंड पुनरावृत्तियों (i/s) को देखें तो ऐसा लगता है कि रूबी 2.3 के बाद से नियमित मेथड्स तेज़ हो गए हैं। यही कारण है कि method_missing बहुत धीमा दिखता है 🙂

पठनीयता

instance_eval / class_eval मेथड्स का उपयोग करते समय त्रुटि संदेश कम सहायक हो सकते हैं।

निम्नलिखित कोड पर एक नज़र डालें:

 class Thing class_eval("def self.foo; raise 'something went wrong'; end") end Thing.foo 

इसके परिणामस्वरूप निम्न त्रुटि होगी:

 (eval):1:in 'foo': 'something went wrong...' (RuntimeError) 

ध्यान दें कि फ़ाइल नाम गायब है (यह eval कहता है) और सही लाइन नंबर। अच्छी खबर यह है कि इसके लिए एक समाधान है, ये eval मेथड्स दो अतिरिक्त पैरामीटर लेते हैं:

  • एक फ़ाइल नाम
  • एक लाइन नंबर

बिल्ट-इन कॉन्स्टेंट्स __FILE__ और __LINE__ को class_eval के पैरामीटर के रूप में उपयोग करके आपको त्रुटि संदेश में सही जानकारी मिलेगी।

उदाहरण:

 class Thing class_eval( "def foo; raise 'something went right'; end", __FILE__, __LINE__ ) end 

यह डिफ़ॉल्ट क्यों नहीं है?

मुझे नहीं पता, लेकिन यह कुछ ऐसा है जिसे ध्यान में रखना चाहिए यदि आप इन मेथड्स का उपयोग करने जा रहे हैं 🙂

खोजने योग्यता

मेटाप्रोग्रामिंग मेथड्स आपके कोड को कम खोजने योग्य, कम सुलभ (खराब दस्तावेज़ीकरण के माध्यम से) और डिबग करना कठिन बनाते हैं।

यदि आप किसी मेथड परिभाषा की तलाश कर रहे हैं तो आप मेटाप्रोग्रामिंग के माध्यम से परिभाषित मेथड को खोजने के लिए CTRL+F (या आप जिस भी शॉर्टकट का उपयोग करते हैं) नहीं कर पाएंगे, खासकर यदि मेथड का नाम रन-टाइम पर बनाया गया है।

निम्नलिखित उदाहरण मेटाप्रोग्रामिंग का उपयोग करके 3 मेथड्स परिभाषित करता है:

 class RubyBlog def create_post_tags types = ['computer_science', 'tools', 'advanced_ruby'] types.each do |type| define_singleton_method(type + "_tag") { puts "This post is about #{type}" } end end end rb = RubyBlog.new rb.create_post_tags rb.computer_science_tag 

दस्तावेज़ीकरण उत्पन्न करने वाले टूल्स (जैसे Yard या RDoc) इन मेथड्स को ढूंढ और सूचीबद्ध नहीं कर सकते।

ये टूल्स क्लासेस और मेथड्स को खोजने के लिए "स्टेटिक एनालिसिस" नामक तकनीक का उपयोग करते हैं। यह तकनीक केवल उन मेथड्स को ढूंढ सकती है जो सीधे परिभाषित हैं (def सिंटैक्स का उपयोग करके)।

पिछले उदाहरण के साथ yard doc चलाने का प्रयास करें, आप देखेंगे कि पाया गया एकमात्र मेथड create_post_tags है।

यह ऐसा दिखता है:

मेटाप्रोग्रामिंग की वास्तविक लागत: जो आपको जानना आवश्यक है

yard को अतिरिक्त मेथड्स दस्तावेज़ करने के लिए बताने का एक तरीका है, @method टैग का उपयोग करके, लेकिन यह हमेशा व्यावहारिक नहीं होता।

उदाहरण:

 class Thing # @method build_report define_method(:build_report) end 

इसके अलावा यदि आप grep, ack, या अपने संपादक जैसे टूल का उपयोग करके मेथड परिभाषाओं की खोज करने जा रहे हैं, मेटाप्रोग्रामिंग मेथड्स को ढूंढना नियमित मेथड्स की तुलना में कठिन होगा।

"मुझे नहीं लगता कि Sidekiq किसी मेटाप्रोग्रामिंग का उपयोग करता है क्योंकि मुझे लगता है कि यह 95% समय कोड को अस्पष्ट करता है जितना यह मदद करता है।" - माइक पेरहैम, Sidekiq के निर्माता

निष्कर्ष

मेटाप्रोग्रामिंग के बारे में सब कुछ बुरा नहीं है। सही स्थितियों में यह आपके कोड को अधिक लचीला बनाने के लिए उपयोगी हो सकता है।

बस अतिरिक्त लागतों के बारे में जागरूक रहें ताकि आप बेहतर निर्णय ले सकें।

इस पोस्ट को शेयर करना न भूलें अगर आपको यह उपयोगी लगा 🙂

  1. जावास्क्रिप्ट में generator.throw() मेथड जावास्क्रिप्ट में generator.throw() मेथड

    generator.throw() मेथड का उपयोग यील्ड को एरर पास करने के लिए किया जाता है। जनरेटर throw कॉल होने के बाद एरर फेंककर और done और value प्रॉपर्टीज वाला ऑब्जेक्ट लौटाकर एक्जीक्यूशन फिर से शुरू करता है। जावास्क्रिप्ट में generator.throw() के लिए कोड निम्नलिखित है: उदाहरण <!DOCTYPE html> <html la

  1. सर्वश्रेष्ठ असीमित फ्री VPN सेवाएं (और उनकी छिपी हुई लागतें) सर्वश्रेष्ठ असीमित फ्री VPN सेवाएं (और उनकी छिपी हुई लागतें)

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

  1. Ruby में Alias कीवर्ड का उपयोग करके मेथड एलियास बनाना Ruby में Alias कीवर्ड का उपयोग करके मेथड एलियास बनाना

    Ruby में किसी मेथड को वैकल्पिक नाम देने के दो तरीके हैं: alias (कीवर्ड) alias_method चूंकि ये दोनों थोड़े अलग तरीके से एक ही काम करते हैं, इसलिए यह विषय भ्रमित करने वाला हो सकता है। यह छवि अंतरों का सारांश है: आइए इन अंतरों को विस्तार से समझते हैं ताकि आपको ठोस समझ मिल सके! alias कीवर्ड पहला है a