2010-07-14 19 views
6

मेरे लिए विशिष्ट परिदृश्य:मैं ऑब्जेक्ट बनाने के लिए स्रोत कोड कैसे उत्पन्न करूं जो मैं डिबगिंग कर रहा हूं?

  1. विरासत कोड मैं पर काम एक बग है कि उत्पादन में केवल एक ग्राहक
  2. मैं एक डिबगर देते हैं और यह पता लगाने पर उनके प्रणाली समस्या को ठीक करने के लिए कैसे हो रही है है उनके इनपुट दिए गए। लेकिन, मुझे नहीं पता कि त्रुटि अभी तक क्यों हो रही है।
  3. अब मैं कोशिश करते हैं और पुन: पेश तो

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

क्या मेरे डीबगर में ब्रेक पॉइंट से फ़ील्ड लेने का एक स्वचालित तरीका है और उस ऑब्जेक्ट को उत्पन्न करने वाले स्रोत कोड उत्पन्न करने के लिए एक स्वचालित तरीका है, उसी तरह पॉप्युलेट किया गया है?

एकमात्र चीज जो मैंने आई है, इस इनपुट को क्रमबद्ध करना है (उदाहरण के लिए एक्सस्ट्रीम का उपयोग करना)। मैं इसे एक फ़ाइल में सहेज सकता हूं और उसे स्वचालित परीक्षण में वापस पढ़ सकता हूं। इसमें एक बड़ी समस्या है: यदि कक्षा कुछ तरीकों से बदलती है (उदाहरण: एक फ़ील्ड/गेटर/सेटर नाम का नाम बदल दिया गया है), तो मैं अब ऑब्जेक्ट को deserialize करने में सक्षम नहीं होगा। दूसरे शब्दों में, परीक्षण बेहद नाजुक हैं।

+1

क्या आप स्पष्ट कर सकते हैं कि XStream की तरह कुछ क्यों फिट नहीं है और आपको स्रोत कोड उत्पन्न करने की पूरी आवश्यकता क्यों है? इससे निश्चित रूप से बेहतर उत्तर प्राप्त करने में मदद मिलेगी। –

+1

फ़ील्ड टेस्ट ईवेंट के लिए परीक्षण मामलों की लंबी अवधि की नाजुकता के साथ क्या समस्या है जिसे आप अभी हल करना चाहते हैं? –

+0

@IraBaxter अल्प अवधि के लिए इसके साथ कुछ भी गलत नहीं है। लेकिन अगर मैं वर्तमान में उससे बेहतर तरीके से निपटने के लिए वहां कुछ अच्छी लाइब्रेरी/तकनीक/रणनीति है, तो मैं इसके बारे में सुनना चाहता हूं। –

उत्तर

2

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

अधिक उपयुक्त अपनी आवश्यकताओं के लिए, दृष्टिकोण है कि objetcs अपने स्वयं के (बाइनरी) कस्टम क्रमबद्धता का समर्थन है। लेकिन अब versionId लिखकर पहले संस्करण को पेश करें। ऑब्जेक्ट्स जिनमें केवल एक संस्करण है, संस्करण 1 लिखें। इस तरह आप बाद में कर सकते हैं, जब आपको अपने objetcs में कोई परिवर्तन करना है, फ़ील्ड को हटाएं, फ़ील्ड जोड़ें, संस्करण संख्या बढ़ाएं।

इस तरह के एक ICustomSerializable तो पहले बाहर इनपुट धारा से संस्करण संख्या, एक readObject() विधि में पढ़ा होगा, और संस्करण क्रमांक के आधार पर readVersionV1() या जैसे readVersionV2().

public Interface ICustomSerializable { 
    void writeObject(DataOutputStream dos); 
    Object readObject(DataInputStream dis); 
} 

public Class Foo { 
    public static final VERSION_V1 = 1; 
    public static final VERSION_V2 = 2; 

    public static final CURRENT_VERSION = VERSION_V2; 
    private int version; 

    private int fooNumber; 
    private double fooDouble; 

    public void writeObject(DataOutputStream dos) { 
    dos.writeInt(this.version); 
     if (version == VERSION_V1) { 
      writeVersionV1(dos); 
     } else (version == VERSION_V2) { 
      writeVersionV2(dos); 
     } else { 
     throw new IllegalFormatException("unkown version: " + this.version); 
     } 
    } 
    public void writeVersionV1(DataOutputStream dos) { 
     writeInt(this.fooNumber); 
     writeDouble(this.fooValue); 
    } 
} 

इसके अलावा गेटर फोन और सेटर, और CURRENT_VERSION को संस्करण प्रारंभ करने वाला एक कन्स्ट्रक्टर आवश्यक है।

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

+0

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

1

मुझे लगता है कि आप "राज्य" को स्टोर करना चाहते हैं, और उसके बाद यह सुनिश्चित करने के लिए कि बग तय रहता है, उसे अपने परीक्षण में पुनर्स्थापित करें।

संक्षिप्त उत्तर: इस तरह के सामान्य कोड जनरेशन उपकरण का कोई अजीब नहीं है, लेकिन जब तक कई बाधाएं रखी जाती हैं, ऐसे उपकरण को लिखना छोटा काम होता है।

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

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

बग की प्रकृति भी एक बाधा है। उदाहरण के लिए कल्पना करें कि बग हुआ क्योंकि एक फ़ील्ड/विधि में यह और वह नाम था। यदि एक रिफैक्टरिंग अब नाम बदलती है तो बग अब आपके राज्य के बावजूद दिखाई नहीं देगा।

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

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

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