2015-10-22 9 views
8

मैं निम्न विधि है cyclomatic जटिलता को कम करना:एक जावा विधि

private void setClientAdditionalInfo(Map map, Client client, User user) { 

    Map additionalInfo = (Map) map.get("additionalInfo"); 

    if (checkMapProperty(additionalInfo, "gender")) { 
     client.setGender(additionalInfo.get("gender").toString()); 
    } 
    if (checkMapProperty(additionalInfo, "race")) { 
     client.setRace(additionalInfo.get("race").toString()); 
    } 
    if (checkMapProperty(additionalInfo, "ethnicity")) { 
     client.setEthnicity(additionalInfo.get("ethnicity").toString()); 
    } 
    ..... 

12 अधिक अगर बयान समान तरीके से किया जाता है। एकमात्र अंतर एक अलग सेटर विधि नाम और एक अलग पैरामीटर है। अब, जैसा कि एक ही पैटर्न बार-बार दोहराया जाता है, क्या कोड जटिलता को कम करने का कोई तरीका है?

+0

आप मानचित्र {{"दौड़": क्लाइंट :: सेटरेस, ...} 'बना सकते हैं या स्ट्रिंग्स की सूची के लिए उचित सेटर ढूंढने के लिए प्रतिबिंब का उपयोग कर सकते हैं। सुनिश्चित नहीं है कि यह जटिलता को कम करेगा, लेकिन यह नकल को कम कर सकता है। मुझे लगता है कि मैं इसे इस तरह से रखूंगा।सोचने के लिए बेहतर "यह 15 बार क्यों दोहराया जाता है?" सोचने के बजाय "यह कोड क्या बिल्ली है?" –

+0

एक प्रश्न जो पूछने लायक हो सकता है: मानचित्र में आपकी जानकारी क्यों है? क्या आप अपनी जानकारी पहले 'क्लाइंट' में संग्रहीत नहीं कर सकते थे? अक्सर जवाब "नहीं" होता है और आपको बुलेट काटने की ज़रूरत होती है लेकिन कभी-कभी आप नक्शे से ऑब्जेक्ट्स को पूरी तरह से पॉप्युलेट करने से बच सकते हैं। – biziclop

+0

क्या आपका मतलब है "चक्रवात जटिलता" या "कोड की कम लाइनें?" एन चीजों पर लूप के लिए चक्रवात जटिलता में 2^एन जोड़ सकते हैं, भले ही यह बेहतर लगे। साइक्लोमैटिक जटिलता को न बदलने वाले कोड को बेहतर बनाने के लिए आपको बहुत सारे जवाब मिल रहे हैं। – djechlin

उत्तर

2

आसानी से नहीं, और प्रतिबिंब का उपयोग किए बिना नहीं।

प्रतिबिंब का उपयोग करके आप मूल्यों की सूची के माध्यम से लूप कर सकते हैं और क्लाइंट ऑब्जेक्ट में उपयुक्त विधि को कॉल कर सकते हैं। वह जटिलता से छुटकारा पायेगा और क्लीनर/अधिक मजबूत होगा। हालांकि यह धीमी गति से प्रदर्शन करेगा।

मूल रूप से यद्यपि आपके पास ऐसा मामला है जहां आप लगभग कर रहे हैं लेकिन काफी समान ऑपरेशन नहीं करते हैं, यह हमेशा मुश्किल होता है।

0

मैं enum का उपयोग name().toLowercase() कुंजी के रूप में मानचित्र के कुंजी से सेटर को जोड़ने के लिए करता हूं।

class MapWrapper { 
    private final Map map; 

    MapWrapper(Map map) { 
     this.map = map; 
    } 

    String get(String key) { 
     if (checkMapProperty(map,key)) { 
      return map.get(key).toString(); 
     } else { 
      return null; 
     } 
     // or more concisely: 
     // return checkMapProperty(map,key) ? map.get(key).toString() : null; 
    } 
} 

और फिर

private void setClientAdditionalInfo(Map map, Client client, User user) { 

    Map additionalInfo = (Map) map.get("additionalInfo"); 
    MapWrapper wrapper = new MapWrapper(additionalInfo); 

    client.setGender(wrapper.get("gender")); 
    ... 
} 

:

enum Setter { 

    Gender { 

       @Override 
       void set(Client client, Thing value) { 
        client.setGender(value); 
       } 

      }, 
    Race { 

       @Override 
       void set(Client client, Thing value) { 
        client.setRace(value); 
       } 

      }, 
    Ethnicity { 

       @Override 
       void set(Client client, Thing value) { 
        client.setEthnicity(value); 
       } 

      }; 

    void setIfPresent(Client client, Map<String, Thing> additionalInfo) { 
     // Use the enum name in lowercase as the key. 
     String key = this.name().toLowerCase(); 
     // Should this one be set? 
     if (additionalInfo.containsKey(key)) { 
      // Yes! Call the setter-specific set method. 
      set(client, additionalInfo.get(key)); 
     } 
    } 

    // All enums must implement one of these. 
    abstract void set(Client client, Thing value); 
} 

private void setClientAdditionalInfo(Map map, Client client, User user) { 
    Map additionalInfo = (Map) map.get("additionalInfo"); 
    for (Setter setter : Setter.values()) { 
     setter.setIfPresent(client, additionalInfo); 
    } 
} 
+0

समान चक्रवात जटिलता। – djechlin

0

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

1

आप जावा 8 कार्यात्मक इंटरफेस के साथ ऐसा कर सकते हैं। यह कम से कम दो बार सशर्त बयान से छुटकारा पा जाएगा।

private void doRepetitiveThing(Map info, String key, Consumer<String> setterFunction) { 
    if(checkMapProperty(info, key)) { 
     setterFunction.accept(info.get(key).toString()); 
    } 
} 

private void setClientAdditionalInfo(Map map, Client client, User user) { 

    Map additionalInfo = (Map) map.get("additionalInfo"); 

    doRepetitiveThing(additionalInfo, "gender", client::setGender); 
    doRepetitiveThing(additionalInfo, "race", client::setRace); 
    doRepetitiveThing(additionalInfo, "ethnicity", client::setEthnicity); 
    ..... 
+0

समान चक्रवात जटिलता। – djechlin

1

यह सुनिश्चित नहीं है कि यह वास्तव में चक्रवात जटिलता को कम करता है, लेकिन यह कोड को सुंदर बनाता है। यह जावा 8. साथ

private void setClientAdditionalInfo(Map<String, Object> map, Client client, User user) { 
    Map<String, ?> additionalInfo = (Map<String, Object>) map.get("additionalInfo"); 
    setIfPresent(additionalInfo, "gender", client::setGender); 
    setIfPresent(additionalInfo, "race", client::setRace); 
    setIfPresent(additionalInfo, "ethnicity", client::setEthnicity); 
} 

private void <T> setIfPresent(Map<String, ?> additionalInfo, 
           String property, 
           Consumer<T> consumer) { 
    if (checkMapProperty(additionalInfo, property)) { 
     consumer.apply((T)additionalInfo.get(property)); 
    } 
} 

यदि आप चाहते हैं तो आप एक Map<String, Consumer<?>> कर सकता है बार-बार कॉल से बचने के लिए आसान है।

private static Map<String, ClientSetter> setters = new HashMap<>(); 

interface ClientSetter { 
    void set(Client client, Object value); 
} 

static { 
    setters.put("gender", new ClientSetter() { 
     @Override 
     public void set(Client client, Object value) { 
      client.setGender(value.toString()); 
     } 
    }); 
    setters.put("race", new ClientSetter() { 
     @Override 
     public void set(Client client, Object value) { 
      client.setRace(value.toString()); 
     } 
    }); 
    setters.put("ethnicity", new ClientSetter() { 
     @Override 
     public void set(Client client, Object value) { 
      client.setEthnicity(value.toString()); 
     } 
    }); 
    // ... more setters 
} 

उपलब्ध संपत्तियों से अधिक दोहराएं और हर एक उपलब्ध के लिए set विधि बुला:

0

केवल ओपी के सवाल का जवाब देने के उद्देश्य के लिए एक व्यायाम के रूप में मैं एक Map एक सेटर इंटरफेस के साथ गुण जोड़ बनाएंगे

private void setClientAdditionalInfo(Map map, Client client, User user) { 

    Map additionalInfo = (Map) map.get("additionalInfo"); 

    List<String> additionalInfoKeys = new ArrayList<>(additionalInfo.keySet()); 
    additionalInfoKeys.retainAll(setters.keySet()); 
    for (String key: additionalInfoKeys) { 
     Object value = additionalInfo.get(key); 
     setters.get(key).set(client, value); 
    } 
} 

पुनश्च:: setters नक्शे में जाहिर है इस उत्पादन कोड के लिए सुझाव नहीं है। दो सेटों को छेड़छाड़ करने के लिए संग्रह के सभी तत्वों को एक सूची में कॉपी करना - कोड में परीक्षण/लिखित में स्थितियों को रोकने की खातिर - काफी महंगा है।

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