मैं एक बड़े ऑब्जेक्ट मॉडल के साथ तीसरे पक्ष के पुस्तकालयों को लपेटने के लिए मैनुअल प्रयास को कैसे कम कर सकता हूं?


16

2012 से इस प्रश्न के लेखक और 2013 से एक की तरह , मेरे पास एक 3 पार्टी लाइब्रेरी है जिसे मुझे अपने आवेदन का ठीक से परीक्षण करने के लिए लपेटने की आवश्यकता है। शीर्ष उत्तर बताता है:

आप हमेशा एक इंटरफ़ेस के पीछे तीसरे पक्ष के प्रकार और विधियों को लपेटना चाहते हैं। यह थकाऊ और दर्दनाक हो सकता है। कभी-कभी आप एक कोड जनरेटर लिख सकते हैं या ऐसा करने के लिए एक उपकरण का उपयोग कर सकते हैं।

मेरे मामले में, पुस्तकालय एक ऑब्जेक्ट मॉडल के लिए है और इसके परिणामस्वरूप बड़ी संख्या में कक्षाएं और विधियां हैं जिन्हें सफल होने के लिए इस रणनीति के लिए लपेटने की आवश्यकता होगी। केवल "थकाऊ और दर्दनाक" से परे, यह परीक्षण के लिए एक कठिन बाधा बन जाता है।

इस प्रश्न के बाद के 4 वर्षों में, मुझे पता है कि अलगाव के ढांचे ने एक लंबा सफर तय किया है। मेरा सवाल यह है: क्या अब थ्री पार्टी लाइब्रेरी की पूरी रैपिंग के प्रभाव को प्राप्त करने का एक सरल तरीका मौजूद है? मैं दर्द को इस प्रक्रिया से कैसे निकाल सकता हूं और मैनुअल प्रयास को कम कर सकता हूं।


मेरा प्रश्न उन सवालों का एक डुप्लिकेट नहीं है जो मैं शुरू में जुड़ा हुआ था, क्योंकि मेरा एक रैपिंग के मैनुअल प्रयास को कम करने के बारे में है। वे अन्य प्रश्न केवल पूछते हैं कि क्या लपेटने से समझ में आता है, न कि यह कि कैसे प्रयास को छोटा रखा जा सकता है।


आप किस प्रोग्रामिंग लैंग्वेज और किस तरह की लाइब्रेरी की बात कर रहे हैं?
Doc Brown

@DocBrown C # और एक पीडीएफ हेरफेर लाइब्रेरी।
टॉम राइट

2
मैंने आपके प्रश्न को फिर से खोलने के लिए कुछ समर्थन खोजने के लिए मेटा पर एक पोस्ट शुरू किया ।
डॉक ब्राउन

धन्यवाद @DocBrown - मुझे उम्मीद है कि वहाँ कुछ दिलचस्प दृष्टिकोण होंगे।
टॉम राइट

1
जब हमें अगले 48 घंटे तक बेहतर उत्तर नहीं मिलते हैं, तो मैं इस पर एक इनाम दूंगा।
डॉक्टर ब्राउन

जवाबों:


4

यह मानते हुए कि आप एक नकली ढांचे की तलाश नहीं कर रहे हैं, क्योंकि वे अल्ट्रा-सर्वव्यापी हैं और खोजने में आसान हैं , कुछ चीजें हैं जो ध्यान देने योग्य हैं:

  1. वहाँ "कभी नहीं" कुछ भी है जो आपको "हमेशा" करना चाहिए।
    किसी तीसरे पक्ष के पुस्तकालय को लपेटना हमेशा अच्छा नहीं होता है। यदि आपका आवेदन आंतरिक रूप से एक पुस्तकालय पर निर्भर है, या यदि यह सचमुच एक या दो मुख्य पुस्तकालयों के आसपास बनाया गया है, तो इसे लपेटने में अपना समय बर्बाद न करें। यदि पुस्तकालय बदलते हैं, तो आपके आवेदन को वैसे भी बदलना होगा
  2. एकीकरण परीक्षणों का उपयोग करना ठीक है।
    यह सीमाओं के आसपास विशेष रूप से सच है जो आपके आवेदन के लिए स्थिर, आंतरिक हैं, या आसानी से मजाक नहीं किया जा सकता है। उन शर्तों को पूरा कर रहे हैं, रैपिंग और मजाक होगा जटिल और थकाऊ हो। उस मामले में, मैं दोनों से बचना चाहता हूं: लपेटो मत और मॉक मत करो; सिर्फ एकीकरण परीक्षण लिखें। (यदि स्वचालित परीक्षण एक लक्ष्य है।)
  3. उपकरण और रूपरेखा तार्किक जटिलता को समाप्त नहीं कर सकते हैं।
    सिद्धांत रूप में, एक उपकरण केवल बॉयलरप्लेट पर कट सकता है। लेकिन, एक जटिल इंटरफ़ेस लेने और इसे सरल बनाने के लिए कोई स्वचालित-सक्षम एल्गोरिदम नहीं है - अकेले इंटरफ़ेस एक्स को लेने दें और इसे अपनी आवश्यकताओं के अनुरूप करने के लिए अनुकूल करें। (केवल आप उस एल्गोरिथ्म को जानते हैं !) इसलिए, जबकि निस्संदेह ऐसे उपकरण हैं जो पतले आवरण उत्पन्न कर सकते हैं , मेरा सुझाव है कि वे पहले से ही सर्वव्यापी नहीं हैं क्योंकि, अंत में, आपको अभी भी समझदारी से कोड करने की आवश्यकता है, और इसलिए मैन्युअल रूप से, इंटरफेस के खिलाफ भले ही वह एक रैपर के पीछे छिपा हो।

उस ने कहा, ऐसी रणनीतियाँ हैं जिनका उपयोग आप कई भाषाओं में सीधे एक कक्षा में संदर्भित करने से बचने के लिए कर सकते हैं। और कुछ मामलों में, आप एक इंटरफ़ेस या पतले आवरण को "फ़ैग्न" कर सकते हैं जो वास्तव में मौजूद नहीं है। C # में, उदाहरण के लिए, मैं दो मार्गों में से एक जाऊंगा:

  1. एक कारखाने और अंतर्निहित टाइपिंग का उपयोग करें

आप इस छोटे कॉम्बो के साथ एक जटिल वर्ग को पूरी तरह से लपेटने के प्रयास से बच सकते हैं:

// "factory"
class PdfDocumentFactory {
  public static ExternalPDFLibraryDocument Build() {
    return new ExternalPDFLibraryDocument();
  }
}

// code that uses the factory.
class CoreBusinessEntity {
  public void DoImportantThings() {
    var doc = PdfDocumentFactory.Build();

    // ... i have no idea what your lib does, so, I'm making stuff but.
    // but, you can do whatever you want here without explicitly
    // referring to the library's actual types.
    doc.addHeader("Wee");
    doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
    return doc.exportBinaryStreamOrSomething();
  }
}

यदि आप इन वस्तुओं को सदस्यों के रूप में संग्रहीत करने से बच सकते हैं, या तो अधिक "कार्यात्मक" दृष्टिकोण के माध्यम से या उन्हें एक शब्दकोश (या जो भी ) में संग्रहीत करके , इस दृष्टिकोण को आपके मुख्य व्यवसाय संस्थाओं के बिना संकलन-समय प्रकार की जाँच का लाभ है जो वास्तव में जानना आवश्यक है वे किस वर्ग के साथ काम कर रहे हैं

यह आवश्यक है कि संकलित समय पर, आपके कारखाने द्वारा लौटाए गए वर्ग में वास्तव में उस पर विधियां हों, जो आपके व्यावसायिक ऑब्जेक्ट का उपयोग कर रहा हो।

  1. डायनामिक टाइपिंग का उपयोग करें

यह अंतर्निहित टाइपिंग का उपयोग करने के रूप में एक ही नस में है , लेकिन इसमें एक और ट्रेडऑफ़ शामिल है: आप संकलन-प्रकार की जांच खो देते हैं और कक्षा के सदस्यों के रूप में बाहरी निर्भरता को जोड़ने और अपनी निर्भरता को इंजेक्ट करने की क्षमता प्राप्त करते हैं ।

class CoreBusinessEntity {
  dynamic Doc;

  public void InjectDoc(dynamic Doc) {
    Doc = doc;
  }

  public void DoImortantThings() {
    Doc.addHeader("Wee");
    Doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
    return Doc.exportBinaryStreamOrSomething();
  }
}

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

उस सभी के साथ, तीन बड़े कारण हैं जिन पर मैं अभी भी स्पष्ट रूप से तीसरे पक्ष के पुस्तकालय को लपेटने पर विचार करूंगा - जिनमें से कोई भी एक उपकरण या ढांचे का उपयोग करने में संकेत नहीं देगा:

  1. विशिष्ट पुस्तकालय आवेदन के लिए आंतरिक नहीं है ।
  2. इसे लपेटे बिना स्वैप करना बहुत महंगा होगा ।
  3. मुझे एपीआई ही पसंद नहीं है।

अगर मुझे उन तीनों क्षेत्रों में कुछ स्तर की चिंता नहीं है, तो आप इसे लपेटने के लिए कोई महत्वपूर्ण प्रयास नहीं करते हैं । और, अगर आपको तीनों क्षेत्रों में कुछ चिंता है, तो ऑटो-जेनरेट किया हुआ पतला रैपर वास्तव में मदद करने वाला नहीं है।

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

एक और तरीका रखो, शास्त्रीय सलाह पर ध्यान दिया: हर निर्णय को स्थगित करें जो आप कर सकते हैं। पहले अपने आवेदन की "कोर" बनाएँ। इंटरफेस के खिलाफ कोड जो अंततः आप चाहते हैं, जो अंततः "परिधीय सामान" द्वारा पूरा किया जाएगा जो अभी तक मौजूद नहीं है। आवश्यकतानुसार अंतराल को पाट दें।

यह प्रयास समय की बचत जैसा महसूस नहीं हो सकता है ; लेकिन अगर आपको लगता है कि आपको एक रैपर की जरूरत है, तो यह सुरक्षित रूप से करने का सबसे कारगर तरीका है

इस पर इस तरीके से विचार करें।

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

TLDR

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

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


2
जो स्पष्ट था - यह सवाल का जवाब नहीं एक और पोस्ट है नहीं "जब रैप करने के लिए", लेकिन "कैसे मैनुअल प्रयास को कम करने के लिए"।
डॉक ब्राउन

1
क्षमा करें, लेकिन मुझे लगता है कि आपने प्रश्न के मूल बिंदु को याद किया। मैं नहीं देखता कि आपके सुझाव कैसे लपेटने में किसी भी मैनुअल प्रयास को कम कर सकते हैं । मान लें कि हिस्सेदारी में एफबीआई के रूप में एक जटिल वस्तु मॉडल है, कुछ दर्जनों वर्गों और सैकड़ों तरीकों के साथ। इसका एपीआई ठीक है क्योंकि यह मानक उपयोग के लिए है, लेकिन कम दर्द / प्रयास के साथ इकाई परीक्षण के लिए इसे कैसे लपेटना है?
Doc Brown

1
TLDR; यदि आप बोनस अंक चाहते हैं, तो हमें कुछ बताएं जो हम पहले से ही नहीं जानते हैं ;-)
डॉक्टर ब्राउन

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

1
@DocBrown यह बेतुका है। "क्या समस्याओं के इस वर्ग में उपकरणों या दृष्टिकोणों का एक वर्ग है?" हाँ। बिलकुल यह करता है। रक्षात्मक कोडिंग और इकाई परीक्षणों के बारे में हठधर्मिता नहीं हो रही है ... जैसे मेरा जवाब कहता है। आप तो किया था एक स्वतः उत्पन्न पतली आवरण है, क्या मूल्य इसे प्रदान करेगा !? ... यह आपको परीक्षण के लिए निर्भरता को इंजेक्ट करने की अनुमति नहीं देगा, आपको अभी भी मैन्युअल रूप से करना होगा। और यह आपको लाइब्रेरी को स्वैप करने की अनुमति नहीं देगा, क्योंकि आप अभी भी लाइब्रेरी के एपीआई के खिलाफ कोडिंग कर रहे हैं ... यह अभी अप्रत्यक्ष है।
svidgen

9

उस कोड का यूनिट परीक्षण न करें। इसके बजाय एकीकरण परीक्षण लिखें। कुछ मामलों में, इकाई, परीक्षण मजाक, है कठिन और दर्दनाक। यूनिट परीक्षणों को खोदें और एकीकरण परीक्षण लिखें जो वास्तव में विक्रेता कॉल को बाहरी बनाते हैं।

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

कभी-कभी एक एकीकरण परीक्षण आपके आवेदन के कुछ हिस्सों में एक इकाई परीक्षण की तुलना में बेहतर फिट होता है। हुप्स को कोड "टेस्टेबल" बनाने के लिए कभी-कभी हानिकारक हो सकता है।


2
पहली बात मुझे लगा कि जब मैंने आपका उत्तर पढ़ा था तो "पीडीएफ के लिए अवास्तविक था, क्योंकि द्विआधारी स्तर पर फाइलों की तुलना करने से आपको यह नहीं पता चलता है कि क्या परिवर्तन हुआ है या यदि परिवर्तन समस्याग्रस्त है"। तब मुझे यह पुराना SO पोस्ट मिला , यह दर्शाता है कि यह वास्तव में काम कर सकता है (इसलिए +1)।
डॉक ब्राउन

@DocBrown एसओ लिंक में उपकरण बाइनरी स्तर में पीडीएफ की तुलना नहीं करता है। यह पृष्ठों की संरचना और सामग्री की तुलना करता है। Pdf आंतरिक संरचना: safaribooksonline.com/library/view/pdf-explained/9781449321581/…
linuxunil

1
@linuxunil: हाँ, मुझे पता है, जैसा कि मैंने लिखा था, पहले मैंने सोचा था ... लेकिन फिर मुझे ऊपर उल्लिखित समाधान मिला।
डॉक्टर ब्राउन

ओह .. मैं देख रहा हूँ .. हो सकता है कि आपके उत्तर के अंतिम में 'यह वास्तव में काम कर सकता है' मुझे भ्रमित कर दे।
linuxunil

1

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

मैं देखता हूं कि हम .NET नेटवर्क्स के आसपास खेल रहे हैं, इसलिए हमारे हाथों में शक्तिशाली परावर्तन क्षमताएं हैं। आप इस पर विचार कर सकते हैं:

  1. .NET रैपर क्लास जेनरेटर जैसे उपकरण । मैंने उस उपकरण का उपयोग नहीं किया है और मुझे पता है कि यह एक विरासत प्रौद्योगिकी स्टैक पर संचालित होता है, लेकिन शायद आपके मामले के लिए यह फिट होगा। बेशक, कोड की गुणवत्ता, निर्भरता उलटा और Interfaces अलगाव के लिए समर्थन अलग से जांच की जानी चाहिए। शायद इस तरह के अन्य उपकरण हैं, लेकिन मैंने बहुत खोज नहीं की।
  2. अपना खुद का टूल लिखना जो सार्वजनिक विधियों / इंटरफेस के लिए संदर्भित विधानसभा में खोज करेगा और मैपिंग और कोड जनरेशन करता है। समुदाय का योगदान स्वागत से अधिक होगा!
  3. अगर .NET कोई मामला नहीं है ... शायद यहाँ देखें

मेरा मानना ​​है कि इस तरह के स्वचालन से आधार बिंदु बन सकता है, लेकिन अंतिम समाधान नहीं। मैनुअल कोड रिफैक्टिंग की आवश्यकता होगी ... या सबसे खराब स्थिति में एक नया स्वरूप, जैसा कि मैं पूरी तरह से सहमत हूं कि svidgen ने क्या लिखा है:

अपने इच्छित इंटरफ़ेस के विरुद्ध अपना एप्लिकेशन बनाएं; 3 जी एपीआई के खिलाफ नहीं।


ठीक है, कम से कम एक विचार कैसे समस्या को संभाला जा सकता है। लेकिन इस उपयोग के मामले में खुद के अनुभव के आधार पर, मुझे लगता है?
डॉक्टर ब्राउन

सवाल सॉफ्टवेयर इंजीनियरिंग डोमेन (आवरण, प्रतिबिंब, di) के बारे में मेरे अपने अनुभव पर आधारित है! साधनों के बारे में - मैंने उस का उपयोग नहीं किया जैसा कि asnwer में कहा गया है।
टमाटर ३

0

रैपर लाइब्रेरी बनाते समय इन दिशा-निर्देशों का पालन करें:

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

1
बस सोच रहा था कि आपको एक पोस्ट के लिए 3 अपवोट क्यों मिले जो सवाल के बिंदु को याद करते हैं।
डॉक्टर ब्राउन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.