एक शुद्ध आत्मा के साथ गंदी प्रोग्रामिंग: ह्यूरिस्टिक सिस्टम का विकास (भाग 2)

इस लेख के पहले भाग में , हमने जटिल ह्यूरिस्टिक सॉफ्टवेयर सिस्टम के बारे में बात की, जिसे मैंने गंदा कहा। इस भाग में, हम ऐसी प्रणालियों के साथ काम करने के कुछ व्यावहारिक पहलुओं पर चर्चा करेंगे।

हमने ह्यूरिस्टिक सिस्टम की भयावह जटिलता के बारे में बात की। यह जीवन और मृत्यु के बारे में है: या तो आप जिस जटिलता के लिए भुगतान करते हैं वह प्रणाली की गुणवत्ता में सुधार है, या यह बहुत तेजी से बढ़ रहा है। दूसरे मामले में, यहां तक ​​कि छोटे सुधार भी हर बार अधिक से अधिक कठिन होते हैं, और अकिलिस कछुए को कभी नहीं मिलता है। पहले मामले में, सूप खाने का समय होने का एक मौका है।


रबर के दस्ताने


कीचड़ में चारों ओर प्रहार करना सुरक्षा के लिए अधिक सुविधाजनक है, इसलिए, सिस्टम के सामान्य विकास के लिए, सैनिटरी मानकों का अनुपालन आवश्यक है। यहां बहुत कुछ मेरे सहयोगी की सिफारिशों को ग्रहण करता है, इसलिए मैं आवश्यक उपायों का संक्षेप में वर्णन करूंगा।

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

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

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

सहयोगियों के साथ संचार। उन्हें कार्यक्रम में आपके परिवर्तन और वे किन पहलुओं को प्रभावित कर सकते हैं, उन्हें सूचित करें।

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

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

जिम्मेदारी का विभाजन


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

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

गहरी पैठ


मान लीजिए, कुछ मामलों में, सिस्टम ने पूरी तरह से काम नहीं किया। आप अंत से शुरुआत तक एक श्रृंखला में घटकों के संचालन को ट्रैक कर सकते हैं, अनुचित तरीके से उपयोग किए गए घटकों की पहचान कर सकते हैं और उन्हें सही कर सकते हैं। लेकिन शायद असली समस्या एक पूरी तरह से अलग जगह पर छिपी हुई थी। घटक ने स्पष्ट रूप से माना कि सिस्टम के कुछ अन्य हिस्से इसके बेहतरीन प्रदर्शन के लिए स्थितियां पैदा करेंगे, लेकिन ऐसी स्थितियां नहीं बनीं। कोई यह भी कैसे अनुमान लगा सकता है कि सिस्टम के ऐसे हिस्से मौजूद हैं और उन्हें इस तरह से काम करना चाहिए था?

दुर्भाग्य से, "आपको जानना था" से बेहतर कोई जवाब नहीं है। यह निम्नानुसार है कि सिस्टम को ठीक से कॉन्फ़िगर करने के लिए, आपको उन घटकों के संचालन पर सभी निहित समझौतों को जानना होगा जो प्रक्रिया को प्रभावित करते हैं। यदि आप कुछ नहीं जानते थे, तो एक तत्काल तबाही नहीं होगी - आप बस अधिक से अधिक इंटरैक्शन को जटिल कर सकते हैं, जो कि, जैसा कि हम जानते हैं, हेयुरिस्टिक सिस्टम की अकाल मृत्यु से भरा है।

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

कनेक्शन खोलना


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

जटिलता से निपटने के तरीके आमतौर पर अच्छी तरह से ज्ञात हैं, लेकिन हेयुरिस्टिक प्रोग्रामिंग की दुनिया में कई प्रभावी तकनीकें हैं जिन्हें सामान्य दुनिया में गंदा माना जाता है। इनमें से कुछ ट्रिक्स के बारे में नीचे चर्चा की जाएगी।

एक बार कॉपी-पेस्ट करें


पारंपरिक प्रोग्रामिंग में, कोड दोहराव को ठीक से दोषी ठहराया जाता है। हेयुरिस्टिक प्रोग्रामिंग में, यह तकनीक कभी-कभी सबसे कम बुराई होती है जब बातचीत की उलझन को सुलझाती है।

याद रखें कि गंदे प्रोग्रामिंग में घटकों की ज़िम्मेदारी का फ़र्ज़ी क्षेत्र है, और यह कि कोई भी निर्भरता इस क्षेत्र को ख़राब करती है। मान लीजिए कि एक घटक ए है जो घटकों बी और सी का उपयोग करता है । यह पता चल सकता है कि B और C अलग-अलग दिशाओं में "पुल" करेंगे (दोनों घटकों में से प्रत्येक को A से कुछ अलग चाहिए)। ए के लिए लोड का सामना करने के लिए, इसे जटिल करना आवश्यक होगा (उदाहरण के लिए, अतिरिक्त पैरामीटर दर्ज करें)। परिणामस्वरूप, कोड कोड को कॉपी करने और इसे A_for_B और A_for_C के घटकों में बदलने की तुलना में जटिलता कम स्वीकार्य समाधान हो सकती है । (वैसे, नकल विकास के लिए मुख्य रचनात्मक साधनों में से एक है। अक्सर, पहली बार में, एक जीन को गलती से नकल किया जाता है, और फिर इसकी एक प्रति नए कार्यों के लिए अडॉप्ट हो जाती है।)

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

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

विशेष अवसरों के लिए प्यार


प्रोग्रामिंग में एक आम गलती यह है कि समाधान कुछ विशेष मामलों को ध्यान में नहीं रखता है। इसके खिलाफ मुख्य बचाव निर्णय को सबसे सामान्य बनाने की कोशिश करना है, ताकि विशेष मामले अपने आप उत्पन्न हो जाएं। ह्यूरिस्टिक प्रोग्रामिंग में, यह अक्सर समस्याओं को हल करने का सबसे अच्छा तरीका नहीं है।

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

ज़ू बनाना


पायथन के दर्शन का एक सिद्धांत है: "एक होना चाहिए - और, अधिमानतः, केवल एक - ऐसा करने का स्पष्ट तरीका।" गंदी प्रोग्रामिंग में, एक सामान्य स्थिति तब होती है जब एक ही समस्या को कई तरीकों से हल किया जाता है, और एक ही समय में।

वास्तव में, यह सिद्धांत निजी समाधान बनाने के सिद्धांत का एक सामान्यीकरण है, सामान्य लोगों के साथ, ऊपर चर्चा की गई है। तर्क समान है: घटक पर लोड को कम करने से यह उस पर बेहतर ध्यान केंद्रित करने की अनुमति देता है जो इसमें सबसे शक्तिशाली है।

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

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

बेशक, चर्चा के तहत सिद्धांत के दुष्प्रभाव हैं। सबसे पहले, इसके उपयोग से गंभीर कोड सूजन होती है। दूसरे, प्रतिस्पर्धात्मक समाधान संबंधित घटकों के बीच nontrivial निर्भरता पैदा करते हैं, और इस तरह की निर्भरता के नुकसान पर पहले ही चर्चा की जा चुकी है।

निष्कर्ष


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

Source: https://habr.com/ru/post/In144913/


All Articles