क्या मुझे बड़े कार्यों को रिफ्लेक्टर करना चाहिए जिसमें ज्यादातर एक रेगेक्स से बना हो? [बन्द है]


15

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

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


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

2
क्या आप सुनिश्चित हैं कि एक विशाल रेगेक्स आपकी समस्या का सबसे अच्छा समाधान है? क्या आपने एक पार्सर लाइब्रेरी की तरह सरल विकल्पों पर विचार किया है या एक मानक एक (XML, JSON आदि) के साथ कस्टम फ़ाइल प्रारूप की जगह ले रहे हैं?
lortabac

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

8
एक 100 लाइन regexp केवल 1 काम कैसे कर सकता है?
पीटर बी

@lortabac: इनपुट उपयोगकर्ता द्वारा उत्पन्न पाठ (गद्य) है
DudeOnRock

जवाबों:


36

जो आप सामना कर रहे हैं वह संज्ञानात्मक असंगति है जो उन लोगों को सुनने से आता है जो तर्कपूर्ण निर्णय लेने की "सर्वोत्तम प्रथाओं" की आड़ में दिशानिर्देशों का पालन करते हैं।

आपने अपना होमवर्क स्पष्ट रूप से किया है:

  • फ़ंक्शन का उद्देश्य समझा जाता है।
  • इसके कार्यान्वयन के कामकाज को समझा जाता है (यानी, पठनीय)।
  • कार्यान्वयन के पूर्ण-कवरेज परीक्षण हैं।
  • वे परीक्षण पास होते हैं, जिसका अर्थ है कि आप कार्यान्वयन को सही मानते हैं।

यदि उन बिंदुओं में से कोई भी सत्य नहीं था, तो मैं यह कहने के लिए पहले हूं कि आपके फ़ंक्शन को काम करने की आवश्यकता है। इसलिए कोड को छोड़ने के लिए एक वोट है।

दूसरा वोट आपके विकल्पों को देखकर आता है और आपको प्रत्येक से क्या (और हारना) मिलता है:

  • Refactor। इससे आपको किसी के विचार का अनुपालन करने में मदद मिलती है कि फ़ंक्शन कितने समय तक होना चाहिए और पठनीयता का त्याग करता है।
  • कुछ मत करो। यह मौजूदा पठनीयता को बनाए रखता है और किसी के विचार का अनुपालन करता है कि फ़ंक्शन कितने समय तक होना चाहिए।

यह निर्णय नीचे आता है जिसे आप अधिक मूल्य देते हैं: पठनीयता या लंबाई। मैं उस शिविर में आता हूं जो मानता है कि लंबाई अच्छी है, लेकिन पठनीयता महत्वपूर्ण है और किसी भी दिन सप्ताह के अंत में बाद ले जाएगा।

नीचे पंक्ति: यदि यह टूटा हुआ नहीं है, तो इसे ठीक न करें।


10
+1 के लिए "यदि यह टूटा नहीं है, तो इसे ठीक न करें।"
जियोर्जियो

वास्तव में। सैंडी मेट्ज़ नियम ( gist.github.com/henrik/4509394 ) अच्छे और सभी हैं, लेकिन youtube.com/watch?v=VO-NvnZfMA4#t=1379 पर वह बात करते हैं कि वे कैसे आए और लोग क्यों ले रहे हैं उन्हें बहुत गंभीरता से रास्ता।
अमदन

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

19

ईमानदारी से, आपका कार्य "एक काम कर सकता है", लेकिन जैसा कि आपने खुद कहा था

मैं regex को कई कार्यों में तोड़ना शुरू कर सकता हूं,

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

लेकिन मुझे ऐसा लगता है कि मैं वास्तव में पठनीयता खो दूंगा, क्योंकि मैं प्रभावी रूप से भाषाओं को बदल रहा हूं

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

  • किसी अन्य उन्नत डेवलपर को अपना कोड दिखाएं (शायद /codereview// पर ) यह सुनिश्चित करने के लिए कि अन्य पठनीयता के बारे में सोचते हैं कि आप क्या करते हैं। इस विचार के लिए खुले रहें कि अन्य लोगों को आप के रूप में पठनीय के रूप में 100 लाइन रेज एक्सप नहीं मिल सकता है। कभी-कभी "इसकी आसानी से छोटे टुकड़ों में टूटने योग्य नहीं" की धारणा को केवल दूसरी जोड़ी की आंखों से दूर किया जा सकता है।

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

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


मैं कहूंगा कि कैप्चर ग्रुप्स (सामान्य रूप से कैप्चर ग्रुप्स, वास्तव में) अंतिम / राइट-वेरिएबल या शायद मैक्रोज़ के समान हैं। वे आपको मैच के विशिष्ट भागों को संदर्भित करने की अनुमति देते हैं, या तो मैच ऑब्जेक्ट से regex प्रोसेसर या बाद में नियमित अभिव्यक्ति में ही वापस आ जाते हैं।
JAB

4

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

लंबाई एक मनमाना "मानक" है जब यह कोड आकार की बात आती है। जहाँ C # में 100 लाइन फ़ंक्शन को लोंगिश माना जा सकता है, यह असेंबली के कुछ संस्करणों में छोटा होगा। मैंने कुछ एसक्यूएल प्रश्नों को देखा है जो कोड रेंज की 200 लाइनों में अच्छी तरह से थे जो एक रिपोर्ट के लिए डेटा का एक बहुत जटिल सेट लौटाते थे।

पूरी तरह से काम कर कोड , इतना आसान के रूप में आप कर सकते हैं के रूप में है यथोचित यह लक्ष्य है बनाते हैं।

इसे सिर्फ इसलिए मत बदलिए क्योंकि यह लंबा है।


3

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

my $start_re = qr/(?:\w+\.\w+)/;
my $middle_re = qr/(?:DOG)|(?:CAT)/;
my $end_re = qr/ => \d+/;

my $final_re = $start_re . $middle_re . $end_re;
# or: 
# my $final_re = qr/${start_re}${middle_re}${end_re}/

मैं क्रिया ध्वज का उपयोग करता हूं, जो कि आप जो सुझाव दे रहे हैं, उससे भी अधिक सुविधाजनक है।
डूडोनेरॉक

1

मैं कहूंगा कि अगर यह तोड़ने योग्य है तो इसे तोड़ दें। स्थिरता के दृष्टिकोण से और शायद resuability यह इसे तोड़ने के लिए समझ में आता है, लेकिन निश्चित रूप से आपको अपने कार्य की प्राकृतिकता पर विचार करना होगा और आपको इनपुट कैसे मिलेगा और यह क्या लौटने वाला है।

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

इसके अलावा, मैं प्रत्येक मुख्य भाग को कई छोटे और अधिक विशिष्ट कार्यों में तोड़ सकता हूं इसलिए अंत में मेरे पास पूरे काम करने के लिए 5 अलग-अलग कार्य थे और मैं कुछ कार्यों का पुन: उपयोग विभिन्न स्थानों पर कर सकता था।


1

एक चीज जिसे आप मान सकते हैं या नहीं मान सकते हैं, वह है उस भाषा में एक छोटे पार्सर को लिखना जो आप उस भाषा में रेगेक्स का उपयोग करने के बजाय उपयोग कर रहे हैं। यह पढ़ना, परीक्षण और रखरखाव आसान हो सकता है।


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

1
यदि एक रेगीक्स इसे पार्स कर सकता है, तो आप इसे पार्स कर सकते हैं। आपकी प्रतिक्रिया से मुझे यह प्रतीत होता है कि आप पार्स करने में पारंगत नहीं हो सकते। यदि ऐसा है, तो आप regex के साथ रहना चाह सकते हैं। या तो एक नया कौशल सीखें।
थॉमस ईडिंग

मुझे एक नया कौशल सीखना अच्छा लगेगा। कोई अच्छा संसाधन जो आप सुझा सकते हैं? मुझे इसके पीछे के सिद्धांत में भी दिलचस्पी है।
ड्यूडॉनरॉक

1

ज्यादातर मामलों में विशालकाय रेगीक्स एक बुरा विकल्प है। मेरे अनुभव में, वे अक्सर उपयोग किए जाते हैं क्योंकि डेवलपर पार्सिंग से परिचित नहीं है ( थॉमस एडिंग का जवाब देखें )।

वैसे भी, मान लें कि आप एक रेगेक्स-आधारित समाधान से चिपके रहना चाहते हैं।

जैसा कि मैं वास्तविक कोड नहीं जानता, मैं दो संभावित परिदृश्यों की जांच करूंगा:

  • रेगेक्स सरल है (बहुत सारे शाब्दिक मिलान और कुछ विकल्प)

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

  • रेगेक्स जटिल है (बहुत सारे विकल्प)

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

मुझे कल्पना की कमी हो सकती है, लेकिन मैं किसी भी वास्तविक दुनिया की स्थिति के बारे में नहीं सोच सकता हूं जहां 100-लाइन रेगेक्स एक अच्छा समाधान है।

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