आप डायनेमिक स्कोप वाली भाषा में सुरक्षित रूप से कैसे रिफ्लेक्टर करते हैं?


13

आप में से उन लोगों के लिए जो गतिशील गुंजाइश के साथ भाषा में काम नहीं करने का सौभाग्य प्राप्त करते हैं, मैं आपको यह बताता हूं कि यह कैसे काम करता है। "रुबेला" नामक छद्म भाषा की कल्पना करें, जो इस तरह से व्यवहार करती है:

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()म्यूट कर सकते हैं । यह अभी भी एक बुरी स्थिति में है, लेकिन उतना बुरा नहीं है जितना कि यह कभी हुआ करता था।xx

इन खतरों को ध्यान में रखते हुए, हम गतिशील स्कूप के साथ MUMPS या किसी अन्य भाषा में सुरक्षित रूप से रिफ्लेक्टर कोड कैसे बना सकते हैं?

रिफैक्टिंग को आसान बनाने के लिए कुछ स्पष्ट अच्छी प्रथाएं हैं, जैसे किसी फ़ंक्शन में वैरिएबल्स का उपयोग न करें जिन्हें आप NEWखुद से शुरू करते हैं ( ) या एक स्पष्ट पैरामीटर के रूप में पारित किया जाता है, और किसी भी पैरामीटर को स्पष्ट रूप से दस्तावेज कर रहा है जो फ़ंक्शन के कॉलर्स से स्पष्ट रूप से पारित हो जाते हैं । लेकिन एक दशक पुराने, ~ 10 8 -LOC कोडबेस में, ये ऐसी विलासिता हैं जो अक्सर नहीं होती हैं।

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

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



@gnat मैं यह नहीं देख रहा हूं कि यह प्रश्न / इसके उत्तर इस प्रश्न के लिए कैसे प्रासंगिक हैं।
सेंसहिन

1
@gnat क्या आप कह रहे हैं कि उत्तर "विभिन्न प्रक्रियाओं और अन्य भारी सामान का उपयोग करें" है? मेरा मतलब है, यह शायद गलत नहीं है, लेकिन यह विशेष रूप से उपयोगी नहीं होने के बिंदु पर भी सामान्य है।
सेंसिन

2
ईमानदारी से, मुझे नहीं लगता कि इसके अलावा इसका जवाब "एक भाषा पर स्विच करने के लिए है जहां चर वास्तव में स्कूपिंग नियम हैं" या "हंगेरियन नोटेशन के बस्टर्ड स्टेपचाइल्ड का उपयोग करें जहां हर चर इसकी फ़ाइल और / या नाम के नाम से उपसर्ग करता है" प्रकार या तरह से ”। आप जिस मुद्दे का वर्णन करते हैं वह सिर्फ इतना भयानक है कि मैं एक अच्छे समाधान की कल्पना नहीं कर सकता ।
Ixrec

4
कम से कम आप एक गलत बीमारी के नाम पर MUMPS के झूठे विज्ञापन का आरोप नहीं लगा सकते।
कार्सन63000

जवाबों:


4

वाह।

मैं MUMPS को एक भाषा के रूप में नहीं जानता, इसलिए मुझे नहीं पता कि मेरी टिप्पणी यहां लागू होती है या नहीं। आम तौर पर बोलना - आपको अंदर से बाहर रिफ्लेक्टर करना चाहिए। वैश्विक राज्य (वैश्विक चर) के उन उपभोक्ताओं (पाठकों) को मापदंडों का उपयोग करते हुए विधियों / कार्यों / प्रक्रियाओं में शामिल किया जाना चाहिए। विधि c को रिफ्लेक्टरिंग के बाद इस तरह दिखना चाहिए:

function c(c_scope_x) {
   print c(c_scope_x);
}

सी के सभी उपयोगों को फिर से लिखा जाना चाहिए (जो एक यांत्रिक कार्य है)

c(x)

यह स्थानीय राज्य का उपयोग करके "आंतरिक" कोड को वैश्विक राज्य से अलग करना है। जब आप उस के साथ कर रहे हैं, तो आपको बी को फिर से लिखना होगा:

function b() {
   x="oops"
   print c(x);
}

x = "उफ़" असाइनमेंट साइड इफेक्ट रखने के लिए है। अब हमें b को वैश्विक राज्य को प्रदूषित करने वाला मानना ​​चाहिए। यदि आपके पास केवल एक प्रदूषित तत्व है तो इस पर विचार करें:

function b() {
   x="oops"
   print c(x);
   return x;
}

अंत एक्स = बी () के साथ बी के प्रत्येक उपयोग को फिर से लिखना। फ़ंक्शन बी का उपयोग केवल पहले से ही साफ किए गए तरीकों का उपयोग करना चाहिए (आप चाहें तो ro नाम बदलना सह स्पष्ट कर सकते हैं) जब यह रीफैक्टरिंग कर रहा हो। उसके बाद आपको वैश्विक वातावरण को प्रदूषित न करने के लिए रिफ्लेक्टर बी चाहिए।

function b() {
   newvardefinition b_scoped_x="oops"
   print c_cleaned(b_scoped_x);
   return b_scoped_x;
}

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

function x() {
  fifth_to_refactor();
  {
    forth_to_refactor()
    ....
    {
      second_to_refactor();
    }
    ...
    third_to_refactor();
  }
  first_to_refactor()
}

hth।

प्रश्न: इन खतरों को ध्यान में रखते हुए, हम गतिशील स्कूप के साथ MUMPS या किसी अन्य भाषा में सुरक्षित रूप से रिफैक्टर कोड कैसे बना सकते हैं?

  • शायद कोई और संकेत दे सकता है।

प्रश्न: रिफ्लेक्टिंग करते समय हम डायनामिक-स्कोप कोड की बढ़ी हुई नाजुकता के साथ विशेष रूप से जुड़े जोखिमों को कैसे कम करते हैं?

  • एक प्रोग्राम लिखें, जो आपके लिए सुरक्षित रिफ्लेक्टर करता है।
  • एक कार्यक्रम लिखें, जो सुरक्षित उम्मीदवारों / पहले उम्मीदवारों की पहचान करता है।

आह, रिफ्लेक्टिंग प्रक्रिया को स्वचालित करने की कोशिश करने के लिए एक एमयूएमपीएस-विशिष्ट बाधा है: एमयूएमपीएस में प्रथम श्रेणी के कार्य नहीं हैं, न ही इसमें फ़ंक्शन पॉइंटर्स या कोई समान धारणा है। जिसका अर्थ है कि किसी भी बड़े MUMPS कोडबेस में अनिवार्य रूप से निष्कासित (MUMPS, कहे जाने वाले ) उपयोग के बहुत सारे उपयोग होंगे EXECUTE, कभी-कभी स्वच्छता के उपयोगकर्ता इनपुट पर भी - जिसका अर्थ है कि किसी फ़ंक्शन के सभी उपयोगों को वैधानिक रूप से ढूंढना और फिर से लिखना असंभव हो सकता है।
सिनहिन

ठीक है मेरे उत्तर को पर्याप्त मत समझिए। एक YouTube वीडियो मुझे लगता है कि @ google पैमाने को फिर से सक्रिय करना एक बहुत ही अनूठा तरीका था। वे एक एएसटी को पार्स करने के लिए क्लैंग का उपयोग करते थे और फिर अपने कोड को फिर से भरने के लिए किसी भी (यहां तक ​​कि छिपे हुए उपयोग) को खोजने के लिए अपने स्वयं के खोज इंजन का उपयोग करते थे। यह हर उपयोग को खोजने का एक तरीका हो सकता है। मेरा मतलब है कि कण्ठमाला कोड पर एक पार्स और खोज दृष्टिकोण है।
द पैपर

2

मुझे लगता है कि आपका सर्वश्रेष्ठ शॉट आपके नियंत्रण में पूर्ण कोड आधार लाना है, और सुनिश्चित करें कि आपके पास मॉड्यूल और उनकी निर्भरता के बारे में एक सिंहावलोकन है।

तो कम से कम आपके पास वैश्विक खोज करने का एक मौका है, और आपके पास सिस्टम के कुछ हिस्सों के लिए प्रतिगमन परीक्षण जोड़ने का मौका है जहां आप एक कोड परिवर्तन से प्रभाव की उम्मीद करते हैं।

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

यह आपको A से B की निर्भरता को A से B2 की निर्भरता में बदलने का मौका देता है, जहां B2 एक सैनिटाइज्ड है, B. B2 का फिर से लिखा गया संस्करण एक नया लिखा जाना चाहिए जो आपके द्वारा उल्लिखित नियमों को ध्यान में रखते हुए कोड बनाया जाए। अधिक सहज और रिफ्लेक्टर के लिए आसान।


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

इस लेख को पढ़ने के बाद , मुझे यकीन है कि मैं आपको अपने काम के लिए ईर्ष्या नहीं करता हूं।
डॉक ब्राउन

0

स्पष्ट रूप से बताने के लिए : यहां रिफैक्टरिंग कैसे करें? बहुत सावधानी से आगे बढ़ें।

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

मुझे विश्वास है कि मैं यहाँ पर एक परीक्षण-संचालित दृष्टिकोण लागू करूँगा। इसमें वर्तमान कार्यक्षमता बनी रहना सुनिश्चित करने के लिए परीक्षणों का एक सूट लिखना शामिल होगा, क्योंकि आप केवल रिफ्लेक्टिंग शुरू करते हैं, सबसे पहले परीक्षण को आसान बनाने के लिए। (हां, मैं यहां चिकन और अंडे की समस्या की उम्मीद करता हूं, जब तक कि आपका कोड पर्याप्त रूप से पहले से ही बिना इसे बदलने के परीक्षण के लिए मॉड्यूलर है।)

फिर आप अन्य रीफैक्टरिंग के साथ आगे बढ़ सकते हैं, यह जाँचते हुए कि आपने जाते ही कोई परीक्षण नहीं तोड़ा है।

अंत में, आप ऐसे परीक्षण लिखना शुरू कर सकते हैं जो नई कार्यक्षमता की अपेक्षा करते हैं और फिर उन परीक्षणों को काम करने के लिए कोड लिखते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.