2010-05-26 12 views
33

मैं के एक हजार लाइन पद्धति के साथ एक जावा वर्ग है, तो इस तरह/किसी और तर्क:पुनर्रचना अगर/किसी और तर्क

if (userType == "admin") { 
    if (age > 12) { 
      if (location == "USA") { 
       // do stuff 
      } else if (location == "Mexico") { 
       // do something slightly different than the US case 
      } 
    } else if (age < 12 && age > 4) { 
      if (location == "USA") { 
       // do something slightly different than the age > 12 US case 
      } else if (location == "Mexico") { 
       // do something slightly different 
      } 
    } 
} else if (userType == "student") { 
    if (age > 12) { 
      if (location == "USA") { 
       // do stuff 
      } else if (location == "Mexico") { 
       // do something slightly different than the US case 
      } 
    } else if (age < 12 && age > 4) { 
      if (location == "USA") { 
       // do something slightly different than the age > 12 US case 
      } else if (location == "Mexico") { 
       // do something slightly different 
      } 
    } 

मैं कैसे अधिक प्रबंधनीय कुछ में इस refactor करना चाहिए?

+18

मैं समझता हूं कि यह एक त्वरित उदाहरण है, लेकिन स्ट्रिंग की तुलना में वास्तव में 'बराबर() 'के साथ किया जाना चाहिए। – BalusC

+14

... जब आप बिल्कुल 12 होते हैं तो क्या होता है ??? – polygenelubricants

+2

मैं सजावटी पैटर्न http://en.wikipedia.org/wiki/Decorator_pattern पर एक नज़र डालेगा। – Lumpy

उत्तर

1

आप userTypeenum बना सकते हैं, और इसे एक ऐसा तरीका दें जो आपके सभी "कुछ अलग करें" क्रियाएं करता है।

24

आप Strategies का उपयोग करना चाहिए, संभवतः एक enum के भीतर कार्यान्वित, जैसे:

enum UserType { 
    ADMIN() { 
    public void doStuff() { 
     // do stuff the Admin way 
    } 
    }, 
    STUDENT { 
    public void doStuff() { 
     // do stuff the Student way 
    } 
    }; 

    public abstract void doStuff(); 
} 

अपने कोड में प्रत्येक सबसे बाहरी if शाखा के भीतर कोड संरचना के रूप में काफी, एक ही लग रहा है पुनर्रचना की आप हो सकता है अगले चरण में template methods का उपयोग करके उस डुप्लिकेशन को कारक बनाना चाहते हैं। वैकल्पिक रूप से, आप स्थान (और संभवतः आयु) को एक रणनीति में बदल सकते हैं।

अद्यतन: Java4 में, आप लागू कर सकते हैं एक typesafe enum हाथ से, और सादे पुराने उपवर्गीकरण का उपयोग विभिन्न रणनीतियों को लागू करने। उपयोग OO

पहले एक उपयोगकर्ता परिभाषित करते हैं, व्यवस्थापक, छात्र और उपयोगकर्ताओं के अन्य सभी प्रकार को परिभाषित करने और उसके बाद बहुरूपता पर छोड़ दें:

1
अधिक जानकारी के बिना

कोई अच्छा जवाब

लेकिन निष्पक्ष अनुमान इस होगा है बाकी

1

बस चर नाम के आधार पर की, मेरा अनुमान है कि यह है कि आप उपवर्ग चाहिए User (या जो भी यह है कि एक userType चर है) AdminUser और StudentUser (और संभवतः अन्य) में और polymorphism का उपयोग करें।

5

पहले - प्रयोक्ता प्रकार और स्थान के लिए उपयोग enums - तो आप स्विच बयान (पठनीयता में सुधार) का उपयोग कर सकते

दूसरा - अधिक तरीकों का उपयोग।

उदाहरण:

switch (userType) { 
    case Admin: handleAdmin(); break; 
    case Student: handleStudent(); break; 
} 

और बाद में

private void handleAdmin() { 
    switch (location) { 
    case USA: handleAdminInUSA(); break; 
    case Mexico: handleAdminInMexico(); break; 
    } 
} 

इसके अलावा, डुप्लिकेट कोड की पहचान करने और अतिरिक्त तरीकों में रख दें।

संपादित

कोई आपको enums बिना जावा कोड करने के लिए (आप जावा 1.4.2 का उपयोग करने के लिए मजबूर कर रहे हैं की तरह), enums के बजाय का उपयोग करें 'अंतिम स्थिर है या कर की तरह कुछ मजबूर करता हैं:

if (isAdmin(userType)) { 
    handleAdmin(location, age); 
    } else if (isStudent(userType)) { 
    handleStudent(location, age)); 
    } 

//... 

private void handleAdmin(String location, int age) { 
    if (isUSA(location)) { 
    handleAdminInUSA(age); 
    } else if (isUSA(location)) { 
    handleAdminInMexico(age); 
    } 
} 

//... 

private void handleAdminInUSA(int age) { 
    if (isOldEnough(age)) { 
    handleAdminInUSAOldEnough(); 
    } else if (isChild(age)) { 
    handleChildishAdminInUSA(); // ;-) 
    } //... 
} 
+0

यह उल्लेख करना भूल गया कि यह एक जावा 4 एप्लीकेशन है -> कोई enums – David

+0

मैं उम्र समूह के लिए भी enum बनाउंगा: इन्फैंट, बच्चे, ओवरवॉल्व। – DJClayworth

+0

@ डेविड - अच्छी तरह से पुराने तरीके से करें; जैसे उपयोगकर्ता को टाइप करने के लिए हैश मैप का उपयोग करके पूर्णांक स्थिरांक में टाइप करें, और फिर पूर्णांक स्थिरांक पर स्विच करें। –

1

इसका जोखिम यह नहीं है कि यह अस्पष्ट है, लेकिन यह बहुत ही त्रुटि प्रवण है। थोड़ी देर बाद, आप अपनी परिस्थितियों में ओवरलैप के जोखिम में भाग सकते हैं।

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

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

12

पहली बात यह है कि मैं इस कोड के साथ करूंगा Admin और Student, दोनों बेस बेस User से प्राप्त होते हैं। इन कक्षाओं में doStuff() विधि होनी चाहिए जहां आप इस तर्क के बाकी हिस्सों को छुपाएं।

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

1

मैं शायद पहले जांच करता हूं कि आप कोड doStuff और doSimilarStuff को पैरामीट्रिज़ कर सकते हैं या नहीं।

9

हजारों? शायद एक नियम इंजन है जो आपको चाहिए। ड्रोल एक व्यवहार्य विकल्प हो सकता है।

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

मानचित्र को कॉन्फ़िगरेशन के रूप में संग्रहीत किया जा सकता है और स्टार्ट अप पर पढ़ा जा सकता है। आप नए वर्ग जोड़कर और पुन: कॉन्फ़िगर करके नया तर्क जोड़ सकते हैं।

+0

+1। यदि आपके पास हजारों नियम हैं, तो वे निष्पादन और प्रबंधन को बहुत तेज करेंगे। –

0

उपयोग OOP अवधारणाओं: इस डिजाइन के बाकी के निर्भर है, लेकिन हो सकता है आप एक user इंटरफेस, Student होना चाहिए, Admin यह और UsaStudent, MexicoStudent, UsaAdmin, MexicoAdmin कार्यान्वयन है कि कुछ चीजें करते फैली इंटरफेस। User उदाहरण रखें और बस इसकी doStuff विधि पर कॉल करें।

+0

इस तरह "हां-फिर-अन्य" की हजारों पंक्तियों के बजाय आप अपने आप को जटिल विरासत संबंधों के साथ हजारों कक्षाओं के साथ मिल जाएंगे। –

+0

@ आर्टम बार्गेर मैं कुछ बहुत लंबी विधियों पर बहुत छोटी कक्षाओं को पसंद करता हूं। एक बार जब आप इनपुट पढ़ लेंगे तो आपको बहुत से छोटे वर्गों को परिभाषित करके –

+0

को एक ही स्थान से दूसरे स्थान पर निकालने के बाद, आपको यह तय करने की आवश्यकता होगी कि कौन सा उदाहरण बनाना है, ताकि आप इसे अपने फैक्ट्री क्लास या कुछ के अंदर कर सकें। –

1

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

नकारात्मकता यह है कि आपको राज्य की जानकारी को विभिन्न मामलों में बदलने के लिए कुछ तरीका चाहिए। लाभ आपके विरासत पदानुक्रम को संशोधित किए बिना व्यवहार जोड़ने का एक क्लीनर तरीका है।

1

आप जिम्मेदारी पैटर्न की श्रृंखला का उपयोग कर सकते हैं।

रिफैक्टर if-else उदाहरण के लिए इंटरफेस IUserController के साथ कक्षाओं में बयान।

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

इसके अलावा, आप रणनीति पैटर्न का उपयोग करके स्थान विशिष्ट कार्यक्षमता का मॉडल कर सकते हैं। आशा करता हूँ की ये काम करेगा।

1

यदि ब्लॉक में कोड कुछ मानक पैटर्न के भीतर फिट बैठता है, तो मैं कॉलम (प्रकार, स्थान, minAge, maxAge, action) के साथ एक तालिका बनाउंगा, जहां 'एक्शन' एक enum है जो दर्शाता है कि किस प्रकार की प्रसंस्करण करने के लिए। आदर्श रूप से, यह तालिका डेटा फ़ाइल से पढ़ी जाएगी या एसक्यूएल में रखी जाएगी।

फिर, आप उपयोगकर्ता के लिए कार्रवाई करने के लिए जावा कोड में एक टेबल लुकअप कर सकते हैं।

-1

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

एक बार जब आप इस ऑब्जेक्ट उन्मुख संरचना को जगह ले लेंगे, तो आप इस तर्क को फिर से कारक करने के लिए अच्छी तरह से समझी गई ऑब्जेक्ट उन्मुख डिजाइन पैटर्न का उपयोग करने में सक्षम होंगे।

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