हर जगह डेटा जांच शुरू करने के लिए अच्छा कोड शैली?


10

मेरे पास एक परियोजना है जो आकार में पर्याप्त रूप से बड़ी है कि मैं हर पहलू को अपने सिर में नहीं रख सकता। मैं इसमें कई वर्गों और कार्यों के साथ काम कर रहा हूं, और मैं डेटा पास कर रहा हूं।

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

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

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

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

(FYI करें: मैं अभी भी एक शुरुआत कर रहा हूँ, इसलिए कृपया बहाना करें यदि यह प्रश्न अनुभवहीन था; मेरी परियोजना अजगर में है।)



3
@gnat यह समान है, लेकिन मेरे प्रश्न का उत्तर देने के बजाय, यह उस विशिष्ट उदाहरण के लिए सलाह प्रदान करता है ("जितना रक्षात्मक हो सकता है") ओपी ने उल्लेख किया है, जो मेरी अधिक सामान्य क्वेरी से अलग है।
user7088941

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

3
यह एक ऐसी समस्या है जिसका लोग अक्सर कमजोर टाइप की गई भाषाओं का उपयोग करते हैं। यदि आप नहीं चाहते हैं या अधिक सख्ती से टाइप की गई भाषा पर स्विच कर सकते हैं, तो उत्तर बस "हाँ, यह कोड शैली इस समस्या को हल करने के लिए उपयुक्त है" । अगला प्रश्न?
डॉक्टर ब्राउन

1
कड़ाई से टाइप की गई भाषा में, उचित डेटा प्रकारों के साथ, संकलक ने आपके लिए ऐसा किया होगा।
एसडी

जवाबों:


4

एक बेहतर उपाय पायथन भाषा सुविधाओं और टूलिंग का अधिक लाभ लेना है।

उदाहरण के लिए, फ़ंक्शन 1 में, अपेक्षित इनपुट स्ट्रिंग्स की एक सरणी है, जहां पहला स्ट्रिंग कुछ शीर्षक और दूसरा ग्रंथ सूची संदर्भ को दर्शाता है। फ़ंक्शन 2 में अपेक्षित इनपुट अभी भी स्ट्रिंग्स की एक सरणी है, लेकिन अब स्ट्रिंग्स की भूमिकाएं उलट गई हैं।

इस समस्या को एक के साथ कम किया गया है namedtuple। यह हल्का है और आपके सरणी के सदस्यों के लिए आसान अर्थ अर्थ देता है।

भाषाओं को स्विच किए बिना कुछ स्वचालित प्रकार की जाँच का लाभ लेने के लिए, आप टाइप हिंटिंग का लाभ उठा सकते हैं । एक अच्छा IDE इसका उपयोग आपको यह बताने के लिए कर सकता है कि जब आप कुछ गूंगा करते हैं।

जब आवश्यकताएं बदल जाती हैं, तो आप कार्य के बासी होने पर भी चिंतित लगते हैं। इसे स्वचालित परीक्षण द्वारा पकड़ा जा सकता है ।

हालांकि मैं यह नहीं कह रहा हूं कि मैन्युअल रूप से जाँच करना कभी उचित नहीं है, उपलब्ध भाषा सुविधाओं का बेहतर उपयोग आपको इस समस्या को अधिक प्रभावी तरीके से हल करने में मदद कर सकता है।


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

9

ठीक है, वास्तविक समस्या इस उत्तर के नीचे एक टिप्पणी में वर्णित है:

उदाहरण के लिए, फ़ंक्शन 1 में, अपेक्षित इनपुट स्ट्रिंग्स की एक सरणी है, जहां पहला स्ट्रिंग कुछ शीर्षक और दूसरा ग्रंथ सूची संदर्भ को दर्शाता है। फ़ंक्शन 2 में अपेक्षित इनपुट अभी भी स्ट्रिंग्स की एक सरणी है, लेकिन अब स्ट्रिंग्स की भूमिकाएं उलट गई हैं

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

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


कभी-कभी वें समस्या और भी अधिक सूक्ष्म होती है: मैं सही प्रकार से गुजर रहा हूं, लेकिन मेरे इनपुट की "आंतरिक संरचना" फ़ंक्शन को गड़बड़ कर देती है: उदाहरण के लिए, फ़ंक्शन 1 में, अपेक्षित इनपुट स्ट्रिंग की एक सरणी है, जहां पहला स्ट्रिंग है किसी चीज के शीर्षक को दर्शाता है और दूसरे को ग्रंथ सूची के संदर्भ में। फ़ंक्शन 2 में अपेक्षित इनपुट अभी भी स्ट्रिंग्स का एक सरणी है, लेकिन अब स्ट्रिंग्स की भूमिकाओं को उलट दिया गया है: पहला स्ट्रिंग ग्रंथ सूची संदर्भ होना चाहिए और दूसरा ग्रंथ सूची संदर्भ होना चाहिए। मुझे लगता है कि इस जाँच के लिए उपयुक्त हैं?
user7088941

1
@ user7088941: आपके द्वारा वर्णित समस्या को दो क्षेत्रों के साथ एक वर्ग होने से आसानी से हल किया जा सकता है: "शीर्षक" और "ग्रंथ सूची_प्रदर्शन"। आप इसे मिलाएंगे नहीं। तार की एक सूची में आदेश पर भरोसा बहुत त्रुटि प्रवण लगता है। शायद यह अंतर्निहित समस्या है?
जैक्सबी

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

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

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

3

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

हमेशा यह पता लगाने से बचने के लिए कि क्या टूट गया है, जहां मैंने प्रत्येक फ़ंक्शन और वर्ग को "पृथक निकाय" के रूप में समझना शुरू कर दिया है कि यह बाहरी कोड पर सही इनपुट देने पर भरोसा नहीं कर सकता है और स्वयं इनपुट जांच करना है।

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

(या, कुछ मामलों में, डेटा को फिर से लिखें, अगर डेटा गलत रूप में दिया गया है)।

यह एक कम अच्छा विचार हो सकता है। यदि आप देखते हैं कि आपके प्रोग्राम का एक हिस्सा गलत स्वरूपित डेटा के साथ फ़ंक्शन को कॉल कर रहा है, तो FIX THAT PART , जो कि खराब डेटा को पचाने में सक्षम होने के लिए कॉल किए गए फ़ंक्शन को नहीं बदलता है।

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

आपके कोड की गुणवत्ता और स्थिरता में सुधार लंबे समय में एक समय बचाने वाला है (इस मायने में मुझे फिर से आपके कुछ कार्यों में आपके द्वारा बनाए गए आत्म-सुधार कार्यक्षमता के खिलाफ चेतावनी देनी चाहिए - वे बग के लिए एक कपटपूर्ण स्रोत हो सकते हैं। सिर्फ इसलिए कि आपकी कार्यक्रम दुर्घटना नहीं करता है और जलने का मतलब यह नहीं है कि यह सही काम करता है ...)

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


1

वह ठीक है। मैं फॉक्सप्रो में कोड करता था, जहां मेरे पास हर बड़े फंक्शन में TRY..CATCH ब्लॉक थे। अब, मैं जावास्क्रिप्ट / लाइवस्क्रिप्ट में कोड देता हूं और "आंतरिक" या "निजी" कार्यों में शायद ही कभी मापदंडों की जांच करता हूं।

"कितनी जाँच करनी है" चुने हुए प्रोजेक्ट / भाषा पर निर्भर करता है, जितना कि यह आपके कोड कौशल पर निर्भर करता है।


1
मुझे लगता है, यह TRY था ... CATCH ... IGNORE। आपने ओपी के लिए जो पूछ रहा है, उसके विपरीत के बारे में किया। IMHO उनकी बात असंगतता से बच रही है, जबकि आपकी यह सुनिश्चित करने के लिए कि कार्यक्रम एक को मारते समय उड़ा नहीं है।
Maaartinus

1
@maaartinus जो सही है। प्रोग्रामिंग भाषाएं आमतौर पर हमें निर्माण देती हैं जो उड़ाने के आवेदन को रोकने के लिए उपयोग करने के लिए सरल हैं - लेकिन प्रोग्रामिंग प्रोग्रामिंग भाषाएं हमें असंगति को रोकने के लिए उपयोग करने के लिए बहुत कठिन लगती हैं: मेरे ज्ञान के लिए, लगातार सब कुछ रिफ्लेक्टर करें और कक्षाओं का उपयोग करें: सबसे अच्छा कंटेनरीज़ आपके आवेदन में सूचना प्रवाह। यह वही है जो मैं पूछ रहा हूं - इसे ठीक करने का एक आसान तरीका है।
user7088941

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

यह सख्त / ढीले टाइप्ड पैरामीटर के बारे में नहीं है। यह जानने के बारे में है कि पैरामीटर सही है। यहां तक ​​कि अगर आप (पूर्णांक 4 बाइट) का उपयोग करते हैं, तो आपको यह जांचने की आवश्यकता हो सकती है कि यह उदाहरण के लिए कुछ सीमा 0..10 में है या नहीं। यदि आप जानते हैं कि पैरामीटर हमेशा 0..10 है, तो आपको इसकी जांच करने की आवश्यकता नहीं है। फॉक्सप्रो में उदाहरण के लिए सहयोगी सरणियां नहीं हैं, इसके चर, उनके दायरे और इतने पर काम करना बहुत मुश्किल है। यही कारण है कि आपको चेक चेक करना होगा ..
माइकल क्वाड

1
@ user7088941 यह OO नहीं है, लेकिन "विफल तेज़" नियम है। हर गैर-निजी पद्धति को अपने तर्कों की जाँच करनी चाहिए और कुछ भी गलत होने पर फेंक देना चाहिए। कोई कोशिश-कैच नहीं, इसे ठीक करने की कोई कोशिश नहीं, बस इसे आसमान छूना। ज़रूर, कुछ उच्च स्तर पर, अपवाद लॉग और हैंडल हो जाता है। जैसा कि आपके परीक्षणों में पहले से ही अधिकांश समस्याएं हैं और कोई समस्या छिपी नहीं है, कोड त्रुटि-सहिष्णु होने की तुलना में बहुत तेजी से बग-मुक्त समाधान में परिवर्तित हो जाता है।
मौर्टिनस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.