आप में से उन लोगों के लिए जो गतिशील गुंजाइश के साथ भाषा में काम नहीं करने का सौभाग्य प्राप्त करते हैं, मैं आपको यह बताता हूं कि यह कैसे काम करता है। "रुबेला" नामक छद्म भाषा की कल्पना करें, जो इस तरह से व्यवहार करती है:
function foo() {
print(x); // not defined locally => uses whatever value `x` has in the calling context
y = "tetanus";
}
function bar() {
x = "measles";
foo();
print(y); // not defined locally, but set by the call to `foo()`
}
bar(); // prints "measles" followed by "tetanus"
यही है, चर स्वतंत्र रूप से कॉल स्टैक को ऊपर और नीचे प्रचारित करते हैं - परिभाषित सभी चर foo
इसके कॉलर के लिए (और परिवर्तनशील) दिखाई देते हैं bar
, और रिवर्स भी सच है। यह कोड परावर्तन के लिए गंभीर निहितार्थ है। कल्पना करें कि आपके पास निम्नलिखित कोड हैं:
function a() { // defined in file A
x = "qux";
b();
}
function b() { // defined in file B
c();
}
function c() { // defined in file C
print(x);
}
अब, कॉल टू a()
प्रिंट qux
। लेकिन फिर, किसी दिन, आप तय करते हैं कि आपको b
थोड़ा बदलने की जरूरत है । आप सभी कॉलिंग संदर्भों को नहीं जानते हैं (जिनमें से कुछ वास्तव में आपके कोडबेस के बाहर हो सकते हैं), लेकिन यह ठीक होना चाहिए - आपके परिवर्तन पूरी तरह से आंतरिक होने जा रहे हैं b
, है ना? तो आप इसे इस तरह से फिर से लिखें:
function b() {
x = "oops";
c();
}
और आप सोच सकते हैं कि आपने कुछ भी नहीं बदला है, क्योंकि आपने सिर्फ एक स्थानीय चर को परिभाषित किया है। लेकिन, वास्तव में, आप टूट गए हैं a
! अब, a
प्रिंट के oops
बजाय qux
।
इसे छद्म भाषाओं के दायरे से बाहर लाते हुए, यह ठीक उसी प्रकार है जैसे MUMPS व्यवहार करता है, भले ही अन्य वाक्यविन्यास के साथ।
MUMPS के आधुनिक ("आधुनिक") संस्करणों में तथाकथित NEW
कथन शामिल हैं, जो आपको चर को कॉलली से कॉलर तक लीक होने से रोकने की अनुमति देता है। तो ऊपर पहले उदाहरण में, अगर हम किया था NEW y = "tetanus"
में foo()
, तो print(y)
में bar()
कुछ भी नहीं मुद्रित होगा (MUMPS में सभी का नाम रिक्त स्ट्रिंग को इंगित जब तक स्पष्ट कुछ और करने के लिए सेट)। लेकिन ऐसा कुछ भी नहीं है जो चर को कॉलर से कॉलली तक लीक होने से रोक सकता है: यदि हमारे पास function p() { NEW x = 3; q(); print(x); }
, हम सभी जानते हैं, तो पैरामीटर के रूप में स्पष्ट रूप से प्राप्त नहीं होने के बावजूद q()
म्यूट कर सकते हैं । यह अभी भी एक बुरी स्थिति में है, लेकिन उतना बुरा नहीं है जितना कि यह कभी हुआ करता था।x
x
इन खतरों को ध्यान में रखते हुए, हम गतिशील स्कूप के साथ MUMPS या किसी अन्य भाषा में सुरक्षित रूप से रिफ्लेक्टर कोड कैसे बना सकते हैं?
रिफैक्टिंग को आसान बनाने के लिए कुछ स्पष्ट अच्छी प्रथाएं हैं, जैसे किसी फ़ंक्शन में वैरिएबल्स का उपयोग न करें जिन्हें आप NEW
खुद से शुरू करते हैं ( ) या एक स्पष्ट पैरामीटर के रूप में पारित किया जाता है, और किसी भी पैरामीटर को स्पष्ट रूप से दस्तावेज कर रहा है जो फ़ंक्शन के कॉलर्स से स्पष्ट रूप से पारित हो जाते हैं । लेकिन एक दशक पुराने, ~ 10 8 -LOC कोडबेस में, ये ऐसी विलासिता हैं जो अक्सर नहीं होती हैं।
और, ज़ाहिर है, शाब्दिक गुंजाइश के साथ भाषाओं में रिफैक्टिंग के लिए अनिवार्य रूप से सभी अच्छी प्रथाएं गतिशील गुंजाइश के साथ भाषाओं में भी लागू होती हैं - परीक्षण लिखें, और आगे। सवाल यह है कि क्या यह है: रिफैक्टरिंग करते समय हम डायनामिक रूप से स्कोप्ड कोड की बढ़ी हुई नाजुकता के साथ विशेष रूप से जुड़े जोखिमों को कम कैसे करते हैं?
(ध्यान दें कि आप डायनेमिक भाषा में लिखे गए कोड को कैसे नेविगेट और रिफ्लेक्टर करते हैं? इस सवाल का एक समान शीर्षक है, यह पूरी तरह असंबंधित है।)