2008-12-04 2 views
5

मान लीजिए आप एक API कि मूल रूप से साल पहले जारी किया गया था को बनाए रखने रहे हैं (जावा से पहले enum समर्थन प्राप्त) है और यह ints के रूप में शुमार मूल्यों के साथ एक वर्ग को परिभाषित करता:एक एपीआई विकसित होने के रूप में जावा एनम्स के साथ "इंट एनम" पैटर्न के सह-अस्तित्व को संभालने का सबसे अच्छा तरीका क्या है?

public class VitaminType { 
public static final int RETINOL = 0; 
public static final int THIAMIN = 1; 
public static final int RIBOFLAVIN = 2; 
} 

वर्षों में एपीआई विकसित किया गया है और प्राप्त जावा 5-विशिष्ट विशेषताएं (जेनरेटेड इंटरफेस, आदि)। अब आप के बारे में एक नई गणना को जोड़ने के लिए कर रहे हैं:

public enum NutrientType { 
AMINO_ACID, SATURATED_FAT, UNSATURATED_FAT, CARBOHYDRATE; 
} 

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

  • ऊपर दो और (मेरे काल्पनिक उदाहरण में NutrientType) नई enum परिभाषित VitaminType वर्ग की तरह ints की एक श्रृंखला के रूप में:

    मैं तीन संभावित दृष्टिकोण से देखते हैं। आप स्थिरता प्राप्त करते हैं लेकिन आप प्रकार की सुरक्षा और अन्य आधुनिक सुविधाओं का लाभ नहीं उठा रहे हैं।

  • एक प्रकाशित एपीआई में असंगतता साथ रहने के लिए तय: VitaminType रखने के रूप में है चारों ओर, और एक enum रूप NutrientType जोड़ें। VitaminType लेने वाले तरीकों को अभी भी एक int लेने के रूप में घोषित किया गया है, NutrientType लेने वाले विधियों को इस तरह के रूप में घोषित किया जाता है।

  • VitaminType कक्षा को अस्वीकार करें और एक नया VitaminType2 enum प्रस्तुत करें। एक enum के रूप में नया NutrientType परिभाषित करें।
    बधाई हो, अगले 2-3 वर्षों तक जब तक आप बहिष्कृत प्रकार को मार नहीं सकते हैं, तो आप प्रत्येक विधि के बहिष्कृत संस्करणों से निपटने जा रहे हैं, जिसने VitaminType को एक इंट के रूप में लिया और प्रत्येक के नए foo(VitaminType2 v) संस्करण को जोड़ा। आपको प्रत्येक बहिष्कृत foo(int v) विधि के साथ-साथ इसके संबंधित foo(VitaminType2 v) विधि के लिए परीक्षण लिखने की भी आवश्यकता है, इसलिए आपने अपने क्यूए प्रयास को गुणा किया है।

सबसे अच्छा तरीका क्या है?

उत्तर

3

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

class A 
    { 
     public static final int MY_CONSTANT=1 
    } 

    class B 
    { 
      .... 
      i+=A.MY_CONSTANT; 
    } 

i+=1 

तो में संकलित किया जाता है, तो आप एक को फिर से लिखने क्या तुमने कभी एहसास नहीं हो सकता जब तक आप बी पुनः संकलित करें कि बी टूट गया है बाद में।

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

1

एक अफवाह है कि "मेक" के निर्माता ने महसूस किया कि मेकफ़ाइल का सिंटैक्स खराब था, लेकिन महसूस किया कि वह इसे नहीं बदल सका क्योंकि उसके पास पहले से 10 उपयोगकर्ता थे।

सभी लागतों पर पिछड़ा संगतता, भले ही यह आपके ग्राहकों को दर्द पहुंचाए, एक बुरी बात है। इसलिए वास्तव में आपको अपने मामले में क्या करना है, इस पर एक निश्चित उत्तर नहीं दे सकता है, लेकिन लंबे समय तक अपने उपयोगकर्ताओं को लागत सुनिश्चित करें और विचार करें।

यह भी सोचें कि आप अपने कोड के मूल को दोबारा कर सकते हैं, पुराने परत पर केवल पुराने पूर्णांक आधारित enums को रखेगा।

0

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

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

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

1

अगले प्रमुख संशोधन की प्रतीक्षा करें, सब कुछ को enum में बदलें और मौजूदा सिंटैक्स का उपयोग करने के लिए मौजूदा स्रोत कोड को परिवर्तित करने के लिए एक स्क्रिप्ट (sed, perl, Java, groovy, ...) प्रदान करें।

  • कोई दोहरी संगतता:

    जाहिर है इस दो कमियां हैं। यह कितना महत्वपूर्ण है उपयोग मामलों पर निर्भर करता है, लेकिन एक नई प्रमुख रिलीज

  • उपयोगकर्ताओं को कुछ काम करना है, के मामले में स्वीकार्य हो सकता है। अगर काम काफी आसान है, तो यह भी स्वीकार्य हो सकता है।

इस बीच, नए प्रकारों को enums के रूप में जोड़ें और पुराने प्रकार को स्याही के रूप में रखें।

6

एपीआई उपभोक्ता न्यूट्रिएंट टाइप के साथ विटामिन टाइप को भ्रमित करने जा रहे हैं? तो यह संभावना नहीं है, तो शायद यह बेहतर एपीआई डिजाइन स्थिरता बनाए रखने के लिए, खासकर यदि उपयोगकर्ता आधार स्थापित है और आप ग्राहकों द्वारा अपेक्षित काम/शिक्षा के डेल्टा कम करना चाहते हैं। तो भ्रम की संभावना है, तो NutrientType शायद एक enum बन जाना चाहिए।

एक थोक रातोंरात बदलाव नहीं हो इस ज़रूरत नहीं है; उदाहरण के लिए, आप enum के माध्यम से वर्ष पूर्णांक मूल्यों को बेनकाब कर सकते हैं:

public enum Vitamin { 

    RETINOL(0), THIAMIN(1), RIBOFLAVIN(2); 

    private final int intValue; 

    Vitamin(int n) { 
     intValue = n; 
    } 

    public int getVitaminType() { 
     return intValue; 
    } 

    public static Vitamin asVitamin(int intValue) { 
     for (Vitamin vitamin : Vitamin.values()) { 
      if (intValue == vitamin.getVitaminType()) { 
       return vitamin; 
      } 
     } 
     throw new IllegalArgumentException(); 
    } 

} 

/** Use foo.Vitamin instead */ 
@Deprecated 
public class VitaminType { 

    public static final int RETINOL = Vitamin.RETINOL.getVitaminType(); 
    public static final int THIAMIN = Vitamin.THIAMIN.getVitaminType(); 
    public static final int RIBOFLAVIN = Vitamin.RIBOFLAVIN.getVitaminType(); 

} 

यह आपको एपीआई अद्यतन करने के लिए अनुमति देता है और आप जब पुराने प्रकार का बहिष्कार और स्विच पर किसी भी कोड में समय निर्धारण करने के लिए पर कुछ नियंत्रण देता है कि आंतरिक रूप से पुराने प्रकार पर निर्भर करता है।

कुछ ध्यान उन है कि में लाइन पुराने उपभोक्ता कोड के साथ हो सकता है के साथ सिंक में शाब्दिक मान रखने के लिए आवश्यक है।

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

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