2016-11-21 11 views
6

पर सीरियलज़ेबल पेश करना मुझे विश्वास है कि यह वास्तव में एक आम मामला होना चाहिए, फिर भी मुझे कोई सर्वोत्तम प्रथा नहीं मिल रही है। मान लें कि मेरे पास निम्न श्रेणी है:मौजूदा कोड

public class Equation { 

    private Operator operator; 
    private Object leftValue; 
    private Object rightValue; 

    // getters and setters 
} 

public enum Operator {...} 

यह कक्षा हमारे साथ कुछ वर्षों से पहले से ही अच्छी तरह से उपयोग की जा रही है और इसका उपयोग किया जाता है। अब मुझे इसे क्रमबद्ध करने की जरूरत है। मैं उसको कैसे करू?

बस implements Serializable

जोड़ने उस मामले में, Equation वर्ग केवल जब तक मान Serializable हैं काम करता है। चूंकि समीकरण केवल संख्याओं पर काम करते हैं (शायद तिथियां और तार?) जो काम कर सकते हैं। लेकिन मूल्य Object किसी भी तरह का हो सकता है, इसलिए एक बेहतर तरीका होना चाहिए।

मेक महत्व देता Serializable

public class Equation implements Serializable{ 

    private Operator operator; 
    private Serializable leftValue; 
    private Serializable rightValue; 

    // getters and setters 
} 

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

मेक Serializable को महत्व देता है, getters और setters को वैसे ही छोड़

public void setLeftValue(Object leftValue) { 
    if (!(leftValue instanceof Serializable)) 
     throw new IllegalArgumentException("Value must be Serializable!"); 
    this.leftValue = leftValue; 
} 

इस कोड को कोई मौजूदा एपीआई टूट जाता है, लेकिन कैसे कोड बर्ताव बदल जाता है। फिर भी अगर मुझे लगता है कि सभी मान Serializable हैं, तो मुझे लगता है कि यह जाने का तरीका हो सकता है। मैं पुराने सेटर्स के बगल में नए सेटर्स भी डाल सकता हूं और उन्हें भविष्य में डेवलपर्स के लिए यह स्पष्ट करने के लिए बहिष्कृत कर सकता हूं कि किस वस्तु का उपयोग करना है।

मेक transient को महत्व देता है:

कम से कम है कि क्या सोनार पता चलता है। फिर भी यह कम से कम उन सभी मामलों में एक अनुपयोगी वर्ग की ओर जाता है जहां हमें वास्तव में EquationSerializable होने की आवश्यकता होती है।

कार्यान्वयन कि है Serializable बनाएँ:

public class SerializableEquation extends Equation implements Serializable{ 

    private Serializable leftValue; 
    private Serializable rightValue; 

    // override getters and setters 
} 

इस तरह हम जो बदसूरत की तरह लगता है क्रमबद्धता प्रयोजनों के लिए एक पूरी अलग वर्ग, का उपयोग करना होगा, यह नहीं करता है?

प्रश्न:

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

+2

यह स्पष्ट रूप से कार्यान्वयन की समस्या है, 'ऑब्जेक्ट' के बजाय 'ऑपरेंड' वर्ग/इंटरफ़ेस होना चाहिए। उस स्थिति में, आपको केवल उस वर्ग/इंटरफ़ेस में कार्यान्वयन जोड़ना होगा। – AxelH

+5

आपका प्रश्न जावा के अंतर्निहित धारावाहिक तंत्र के नुकसान को दिखाता है। कक्षाओं को serializable बनाने के लिए वास्तव में आवश्यक है? या आप कुछ अन्य समाधान ढूंढ सकते हैं, उदाहरण के लिए कक्षाएं लिखें जो 'समीकरण' ऑब्जेक्ट्स को मानक प्रारूप में एक्सएमएल या जेएसओएन में पढ़/लिख सकते हैं। – Jesper

+1

सीरियलज़ेबल लागू करें। दस्तावेज कि एक समीकरण केवल serializable हो सकता है अगर इसके मूल्य भी हैं (हालांकि यह स्पष्ट होना चाहिए)। ArrayList किसी भी प्रकार का ऑब्जेक्ट स्टोर करता है, और अभी भी Serializable लागू करता है। आपको वही काम करने से डरना नहीं चाहिए। –

उत्तर

1

इस तरह की समस्या में, सही कार्यान्वयन में कार्रवाई के क्षेत्र को सीमित करने के लिए इंटरफेस का उपयोग किया जाना चाहिए था।

UrlConnection को String पर जोड़ने का क्या मतलब है?खैर, यह कुछ इस तरह किया जाना चाहिए था:

public class Equation { 
    Operator operator; 
    Operand leftOp, rightOp; 

    ... 
} 

interface Operand { 

    ... 
} 

और फिर, डेटा के विशिष्ट प्रकार के लिए, आप विशिष्ट औजार classs होता

public IntegerOperand implements Operand { 

    public Integer value; 
    ... 
} 

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

लेकिन

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

आप या तो, जब आप चाहते हैं कि एक विधि के साथ जांच करें (धारावाहिकरण से पहले) यह रोकने के लिए कि यह कार्रवाई इस डेटा के साथ या संभावनाओं को संयोजित करने के लिए दोनों मानों के सेटटर के साथ नहीं की जा सकती है।

public boolean isSerialisable(){ 
    return Serializable.class.isAssignable(leftValue.class) 
      && Serializable.class.isAssignable(rightValue.class); 
} 

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

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

संपादित करें:

यहां एक त्वरित (और बदसूरत उदाहरण) है क्रमबद्धता की वस्तु

public class Main implements Serializable{ 

    public Object value; 

    public Main(Object o){ this.value = o; } 

    public static void main(String[] args){ 
     Main m = new Main(new A()); 

     try { 
      FileOutputStream fileOut = new FileOutputStream("test.ser"); 
      ObjectOutputStream out = new ObjectOutputStream(fileOut); 
      out.writeObject(m); 
      out.close(); 
      fileOut.close(); 
     }catch(IOException i) { 
      i.printStackTrace(); 
     } 

     m = null; 
     try { 
      FileInputStream fileIn = new FileInputStream("test.ser"); 
      ObjectInputStream in = new ObjectInputStream(fileIn); 
      m = (Main) in.readObject(); 
      in.close(); 
      fileIn.close(); 
     }catch(Exception i) { 
      i.printStackTrace(); 
      return; 
     } 
     System.out.println(" M : " + m); 
    } 

    @Override 
    public String toString() { 
     return value == null ? "null" : value.toString(); 
    } 

    static class A implements Serializable{ 
     String s = "foo"; 

     @Override 
     public String toString() { 
      return s; 
     } 
    } 
} 

साथ अगर serializableA से कार्यान्वयन को हटाकर, इस एफएआई होगा एलईडी। लेकिन इस तरह, हम देखते हैं कि यह उम्मीद की तरह काम कर रहा है।

+0

इंटरफ़ेस में फ़ील्ड क्यों हैं? और आप POJO के लिए इंटरफ़ेस को कैसे औचित्य देते हैं? और यह मुझे कक्षा वर्ग बनाने से कैसे रोकता है ऑब्जेक्टऑपरेंड ऑपरेंड {सार्वजनिक ऑब्जेक्ट वैल्यू लागू करता है; } 'और मूल कोड के समान तरीके से कार्यान्वयन को तोड़ना होगा? –

+0

@SteffiS। क्षमा करें, इंटरफ़ेस एक गलती है ... यह एक वर्ग (संपादन) होना चाहिए। यदि ऑपरेंड Serializable है, ऑब्जेक्टऑपरैंड होना चाहिए। यदि आपके कार्यान्वयन में से कोई एक सही ढंग से कार्यान्वित नहीं किया गया है, तो आप ऑपरेंड इंटरफ़ेस का अनुबंध तोड़ते हैं जो Serializable होने के लिए कहता है;) – AxelH

+0

मैं वास्तव में समझ में नहीं आता कि यह मेरी समस्या से कैसे मदद करता है। यहां तक ​​कि अगर मेरे पास 'ऑपरेंड' इंटरफ़ेस था (जो मैं नहीं करता) ... इसे 'सीरियलज़ेबल' बनाने से कोड को उसी तरह से तोड़ दिया जाएगा जब मैं इसे अपने वर्तमान कोड में जोड़ता हूं। –

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