2008-09-19 16 views
12

के लिए विचारों को दोबारा करने की आवश्यकता है मुझे एक राक्षस विरासत मिला है।तीर एंटी-पैटर्न

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

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

यह 775 लाइन लंबी होने पर घोंसला हुआ है। हाँ य़ह सही हैं। सात-सौ-और-फीफ-किशोर रेखाएं। मैं कोई कोड विश्लेषण विशेषज्ञ नहीं हूं, इसलिए मैंने कुछ फ्रीवेयर विश्लेषण टूल डाउनलोड किए और 49 की मैककेब साइक्लोमैटिक कॉम्प्लेक्सिटी रेटिंग के साथ आया। वे मुझे बताते हैं कि यह एक बहुत अधिक संख्या है। अटलांटा क्षेत्र में पराग की गणना के रूप में उच्च जहां 100 उच्च के लिए मानक है और समाचार कहता है "आज की पराग गणना 1,523 है"। यह तीर एंटी-पैटर्न के बेहतरीन उदाहरणों में से एक है जिसे मैंने कभी देखने के लिए प्रबल किया है। उच्चतम पर, इंडेंटेशन 15 टैब गहरा हो जाता है।

मेरा सवाल यह है कि, आप इस तरह की चीज़ को दोबारा बदलने या पुन: स्थापित करने के लिए क्या तरीके सुझाएंगे?

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

शायद एक डिज़ाइन पैटर्न है जो सहायक हो सकता है। क्या कमांड का चेन इस तक पहुंचने का एक तरीका होगा? ध्यान रखें कि इसे .NET 1.1 में रहना चाहिए।

किसी भी और सभी विचारों के लिए धन्यवाद।

उत्तर

2

state machine प्रारंभ करने के लिए तार्किक स्थान की तरह लगता है, और यदि आप इसे स्विंग कर सकते हैं तो डब्ल्यूएफ का उपयोग करना (जैसा आप नहीं कर सकते)।

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

अपने राज्यों को चित्रित करें, संक्रमण का क्या कारण बनता है। रिकॉर्ड को संसाधित करने के लिए वास्तविक कोड को बाहर निकाला जाना चाहिए, और जब राज्य निष्पादित होता है (यदि उस विशेष राज्य को इसकी आवश्यकता होती है) कहा जाता है।

तो राज्य 1 का निष्पादन आपके रिकॉर्ड को "रिकॉर्ड पढ़ें" कहता है, फिर उस रिकॉर्ड संक्रमण के आधार पर किसी अन्य राज्य पर।

अगला राज्य एकाधिक रिकॉर्ड पढ़ सकता है और रिकॉर्ड प्रोसेसिंग निर्देशों को कॉल कर सकता है, फिर राज्य 1 में वापस संक्रमण कर सकता है।

1

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

2

इन मामलों में एक चीज मैं 'रचनाकृत विधि' पैटर्न का उपयोग करना है। इस विषय पर Jeremy Miller's Blog Post देखें। बुनियादी विचार छोटे सार्थक तरीकों को निकालने के लिए आपके आईडीई में रिफैक्टरिंग टूल का उपयोग करना है। एक बार ऐसा करने के बाद, आप सार्थक कक्षाओं को आगे बढ़ाने और निकालने में सक्षम हो सकते हैं।

1

कभी-कभी मैं राज्य के पैटर्न को ढेर के साथ जोड़ता हूं।

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

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

+0

दिलचस्प विचार। मुझे यह समझने में परेशानी हो रही है कि यह कोड में कैसा दिखाई देगा। –

20

मेरे पास इस हफ्ते काम पर कुछ विरासत कोड था जो कि आप जो वर्णन कर रहे हैं उसके समान (हालांकि उतना ही गंभीर नहीं) था।

कोई भी चीज नहीं है जो आपको इससे बाहर निकाल देगी। state machine आपका कोड अंतिम फॉर्म हो सकता है, लेकिन आपको वहां जाने में मदद करने के लिए जा रहा है, और न ही आपके पास पहले से मौजूद गड़बड़ी को छेड़छाड़ करने से पहले इस तरह के समाधान पर निर्णय लेना चाहिए।

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

रिफैक्टरिंग कोड के व्यवहार को नहीं बदलना चाहिए। उसे याद रखो। यही कारण है कि आप प्रमाणित करने के लिए इनपुट और ज्ञात आउटपुट डेटा सेट जानते हैं कि आप चीजों को तोड़ने वाले नहीं हैं। यह आपकी सुरक्षा नेट है।

अब रिएक्टर!

कुछ बातें मैंने किया था कि मैंने पाया उपयोगी:

उलटें if बयान

एक बड़ी समस्या मैं था जब मैं इसी else बयान नहीं पा सके सिर्फ कोड पढ़ रहा था, मैंने देखा है कि ब्लॉक के एक बहुत यह

if (someCondition) 
{ 
    100+ lines of code 
    { 
    ... 
    } 
} 
else 
{ 
    simple statement here 
} 

की तरह दिखाई देता if inverting से मेरा साधारण मामला देख सकते हैं और फिर वें पर ले जाने ई अधिक जटिल ब्लॉक यह जानकर कि दूसरे ने पहले से क्या किया है। एक बड़ा बदलाव नहीं, लेकिन मुझे समझने में मदद की।

निकालें विधि

मैं इस एक lot.Take कुछ जटिल बहु लाइन ब्लॉक इस्तेमाल होने वाले इस grok और उसके अपने विधि में यह अलग धकेलना। इसने मुझे आसानी से देखने के लिए अनुमति दी कि कोड डुप्लिकेशंस कहां था।

अब, उम्मीद है कि आपने अपना कोड तोड़ा नहीं है (परीक्षण अभी भी सही हो गया है?), और आपके पास प्रक्रियात्मक कोड अधिक पढ़ने योग्य और बेहतर समझा गया है। देखो यह पहले से ही सुधार हुआ है! लेकिन आपके द्वारा पहले लिखा गया परीक्षण वास्तव में पर्याप्त नहीं है ... यह केवल आपको बताता है कि आप मूल कोड की कार्यक्षमता (बग और सभी) को डुप्लिकेट कर रहे हैं, और यही वह पंक्ति है जिस पर आपने कवरेज किया था क्योंकि मुझे यकीन है कि आप कोड के ब्लॉक मिलेगा जिन्हें आप समझ नहीं सकते कि कैसे हिट करना है या कभी हिट नहीं कर सकता (मैंने अपने काम में दोनों को देखा है)।

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

Refactoring to Patterns इन परिस्थितियों में सहायक पैटर्न को समझाने में सहायता करने के लिए एक महान पुस्तक है।

आप एक हाथी खाने की कोशिश कर रहे हैं, और ऐसा करने का कोई दूसरा तरीका नहीं है लेकिन एक समय में एक काटने का कोई दूसरा तरीका नहीं है। सौभाग्य।

+1

हाथी समानता के लिए उपरोक्त। यह refactoring का सार है; यह थोड़ा सा है। – troelskn

+0

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

2

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

आपने कहा है कि आपके पास कोड 15 स्तरों का इंडेंट है। लगभग 1/2-रास्ता शुरू करें, और विधि निकालें। यदि आप एक अच्छे नाम के साथ आ सकते हैं, तो इसका इस्तेमाल करें, लेकिन यदि आप नहीं कर सकते हैं, तो वैसे भी निकालें। आधा फिर से विभाजित करें। आप यहां आदर्श संरचना के लिए नहीं जा रहे हैं; आप अपने मस्तिष्क में फिट होने वाले टुकड़ों में कोड तोड़ने की कोशिश कर रहे हैं। मेरा दिमाग बहुत बड़ा नहीं है, इसलिए मैं & तोड़ना बंद कर दूंगा जब तक कि इससे कोई चोट नहीं आती।

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

अक्सर जैसे ही आप जाते हैं, तो आप अपने काम की जांच कर सकते हैं, बाद में इतिहास को समझ सकते हैं, विलय करने की आवश्यकता के बिना कुछ "असली काम" करने के लिए तैयार रहें, और अपने साथियों को हार्ड विलय की परेशानी बचाएं।

अंततः आप वापस जाने के लिए और सुनिश्चित करें कि विधि के नाम अच्छे हैं, कि आप मेकअप भावना बना लिया है तरीकों में से सेट, नए वर्गों को साफ करने के लिए, आदि

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

एक जोड़ीदार साथी यहां सहायक होगा।

संबंधित मुद्दे