2011-04-21 13 views
19

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

उदाहरण के लिए, वेब ब्राउज़र पर Array.map कार्यान्वयन को जोड़ना अच्छा लगेगा जो ECMAScript 5 वें संस्करण को लागू नहीं करता है (और यदि आपको सभी jQuery की आवश्यकता नहीं है)। या आपके रूबी सरणी को "इंजेक्ट" का उपयोग करने वाली "योग" सुविधा विधि से लाभ हो सकता है। जब तक आपके सिस्टम में परिवर्तन अलग-अलग होते हैं (उदाहरण के लिए आप वितरण के लिए रिलीज किए गए सॉफ़्टवेयर पैकेज का हिस्सा नहीं हैं) क्या इस भाषा सुविधा का लाभ न लेने का कोई अच्छा कारण नहीं है?

http://en.wikipedia.org/wiki/Monkey_patch#Pitfalls

वहाँ भी बंदर पैचिंग के लिए, सब कुछ के लिए एक समय और जगह है:

+1

एफडब्ल्यूआईडब्ल्यू, रूबी 2.0 में "परिष्करण" नामक कुछ शामिल करने का प्रस्ताव है जो बंदर-पैचिंग से जुड़े नुकसान को कम करेगा। बस "रूबी परिष्करण" के लिए Google, आसपास के कुछ लेख हैं। –

+0

[क्या बंदर बुराई पकड़ रहा है?] (Http://www.singhajit.com/is-ruby-monkey-patching-evil) –

उत्तर

16

विकिपीडिया बंदर पैचिंग के नुकसान का एक संक्षिप्त सार है। अनुभवी डेवलपर्स के पास अपनी आस्तीन की कई तकनीकें होती हैं और उन्हें सीखने के लिए सीखते हैं। यह शायद ही कभी एक तकनीक है जो "बुराई" है, बस इसका असंगत उपयोग है।

+1

एह, यह उन चीजों में से एक है "यदि हर कोई ऐसा करना चाहता था", जैसे कि कूड़ेदान पर राजमार्ग –

+0

"अनुभवी डेवलपर्स के पास अपनी आस्तीन की कई तकनीकें हैं और उन्हें कब उपयोग करना है" <- मुझे यकीन नहीं है कि कभी भी "बंदर पैचिंग के लिए एक समय और जगह" है। अलग-अलग चीज़ को तर्क के रूप में पारित करने से बेहतर होता है, उदाहरण के लिए? – weberc2

+0

@ weberc2 बंदर-पैचिंग का अच्छा उदाहरण तीसरे पक्ष के lib के फ़ंक्शन का एक बेंचमार्क है। टाइमर जोड़ें जो फ़ंक्शन निष्पादन से पहले शुरू होता है और बाद में समाप्त होता है। क्यों नहीं? –

3

जब तक परिवर्तन आपके सिस्टम हैं (जैसे एक सॉफ्टवेयर पैकेज आप वितरण के लिए जारी का हिस्सा नहीं) इसका कोई खास कारण इस भाषा सुविधा का लाभ लेने के लिए नहीं है अलग हो जाती हैं?

एक अलग समस्या पर एकमात्र डेवलपर के रूप में देशी वस्तुओं को विस्तारित या बदलने में कोई समस्या नहीं है। बड़ी परियोजनाओं पर भी यह एक टीम पसंद है जिसे बनाया जाना चाहिए।

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

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

एक जावास्क्रिप्ट विशिष्ट pitfall को चित्रित करने के लिए।

Array.protoype.map = function map() { ... }; 

var a = [2]; 
for (var k in a) { 
    console.log(a[k]); 
} 
// 2, function map() { ... } 

यह समस्या ES5 जो आप एक वस्तु में गैर गणनीय गुण इंजेक्षन करने की अनुमति देता का उपयोग करके बचा जा सकता है।

यह मुख्य रूप से एक उच्च स्तरीय डिज़ाइन विकल्प है और हर किसी को इस पर जागरूक/सहमति होने की आवश्यकता है।

+0

'in' विरोध किया। चाहे सरणी पर 'इन' के लिए कॉल करना अच्छा अभ्यास है, एक अलग मुद्दा है। – user422039

+2

@ user422039 हाँ, यह एक examplar ख़तरा है के साथ के लिए ... प्रलोभन अब तक ... – Raynos

+3

नहीं, यहाँ संपत्ति गणन का उपयोग कर सरणी चलने के लिए बड़ी समस्या – user422039

2

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

बंदर पट्टी पर गिलाड ब्राचा द्वारा एक माना राय: http://gbracha.blogspot.com/2008/03/monkey-patching.html

22

बंदर-पैचिंग, प्रोग्रामिंग पिटारे में कई उपकरण की तरह है, अच्छे के लिए और बुराई के लिए दोनों का उपयोग किया जा सकता है। सवाल यह है कि, संतुलन पर, इस तरह के औजारों का सबसे अधिक उपयोग किया जाता है। रुबी के साथ अपने अनुभव में संतुलन "बुराई" पक्ष पर भारी वजन का होता है।

तो बंदर-पैचिंग का "बुराई" उपयोग क्या है? खैर, आम तौर पर बंदर-पैचिंग आपको प्रमुख, संभावित रूप से अपरिहार्य संघर्षों के लिए व्यापक रूप से खुली छोड़ देता है। मेरे पास कक्षा A है। मेरे पास कुछ प्रकार का बंदर-पैचिंग मॉड्यूल MB है जो A को, method2 और method3 शामिल करने के लिए पैच करता है। मेरे पास एक और बंदर-पैचिंग मॉड्यूल MC है जो को method2, method3 और शामिल करने के लिए पैच करता है। अब मैं एक बांध में हूँ। मैं instance_of_A.method2 पर कॉल करता हूं: किसकी विधि को बुलाया जाता है? इसका उत्तर कई कारकों पर निर्भर हो सकता है:

  1. मैं किस क्रम में पैचिंग मॉड्यूल लाता हूं?
  2. क्या पैच सही तरीके से या किसी प्रकार की सशर्त परिस्थिति में लागू होते हैं?
  3. AAAAAAARGH! स्पिडर अंदर से मेरी आंखें खा रहे हैं! भयानक टकरा समस्याओं:

ठीक है, तो # 3 शायद एक बालक अति-नाटकीय ....

वैसे भी, कि बंदर पैचिंग के साथ समस्या है। उन भाषाओं की अत्यधिक गतिशील प्रकृति को देखते हुए जो आम तौर पर इसका समर्थन करते हैं, आप पहले से ही बहुत दूर "दूरी पर डरावनी कार्रवाई" समस्याओं का सामना कर रहे हैं; बंदर-पैचिंग बस इन्हें जोड़ता है।

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

+0

के उपप्रकार के खिलाफ ढाल की जरूरत नहीं _should_ मैं जब यह अच्छे के लिए इस्तेमाल किया जा सकता के बारे में अधिक उत्सुक हूँ। सिक्के के बुराई पक्ष स्पष्ट है, लेकिन जब यह वास्तव में अपने कार्यक्रम को स्वीकार करने के लिए जो भी बात आप एक तर्क के रूप पैचिंग परिवर्तन किए जा रहे की तुलना में अधिक उपयोगी है? मेरा मतलब है, हम इन वास्तु पैटर्न है और ऐसा लगता है कि बंदर पैचिंग तरह बातें केवल मौजूद तोड़फोड़ के स्वयं के लिए उन्हें नष्ट करने का। – weberc2

0

आपके वर्णन की शर्तों - मौजूदा व्यवहार को जोड़ना (बदलना नहीं), और बाहरी कोड को अपना कोड जारी नहीं करना - अपेक्षाकृत सुरक्षित लगता है। समस्याएं आ सकती हैं, हालांकि, अगर रूबी या जावास्क्रिप्ट या रेल का अगला संस्करण उनके एपीआई को बदल देता है। उदाहरण के लिए, क्या होगा यदि jQuery का कुछ भविष्य संस्करण यह देखने के लिए जांचता है कि क्या Array.map पहले से परिभाषित है या नहीं, और मान लीजिए कि यह मानचित्र का ईएमसीए 5 स्क्रिप्ट संस्करण है जब वास्तविकता में यह आपके बंदर-पैच है?

इसी प्रकार, यदि आप रुबी में "योग" को परिभाषित करते हैं, और एक दिन आप तय करते हैं कि आप रेल में उस रूबी कोड का उपयोग करना चाहते हैं या अपने प्रोजेक्ट में सक्रिय समर्थन मणि जोड़ना चाहते हैं। सक्रिय समर्थन भी एक विधि (परिभाषित पर) को परिभाषित करता है, इसलिए एक संघर्ष है।

+0

"क्या होगा यदि jQuery का कुछ भविष्य संस्करण यह देखने के लिए जांचता है कि क्या Array.map पहले ही परिभाषित है या नहीं, और मानता है कि यह मानचित्र का ईएमसीए 5 स्क्रिप्ट संस्करण है" फिर यह एक अन्यायपूर्ण धारणा बना देता है और यह जो भी हो जाता है उसके योग्य है। – ChrisJJ

संबंधित मुद्दे