2009-01-07 13 views
7

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

class ShortLivedThing { 
    IDependency1 dep1; 
    IDependency1 dep2; 
    IDependency1 dep3; 
    ... 

    int TheRealData; 

    // Constructor used in production 
    public ShortLivedThing() { 
    dep1 = new Dep1(); dep2 = new Dep2(); dep3 = new Dep3(); 
    } 

    // DI for testing 
    public ShortLivedThing(IDependency1 d1, IDependency2 d2, IDependency3 d3) { 
    dep1 = d1(); dep2 = d2(); dep3 = d3(); 
    } 
} 

बारी में निर्भरता समय के सबसे अधिक अन्य निर्भरता और इतने पर है। इसके परिणामस्वरूप पेड़ के तात्कालिकता (ज्यादातर "स्थैतिक") वस्तुओं हर बार परीक्षण विधि के बाहर एक विधि कॉल किया जाता है। प्रत्येक वस्तु बहुत छोटी होती है (केवल कुछ पॉइंटर्स), लेकिन पेड़ प्रभाव इसे लगातार बढ़ते प्रदर्शन हिट में बदल देता है।

हम इसके बारे में क्या कर सकते हैं?

+0

क्या आप अपना उत्पादन कोड या अपने परीक्षण प्रोफाइल कर रहे हैं? –

+0

मैं उत्पादन कोड प्रोफाइलिंग कर रहा हूँ। परीक्षण तेजी से चलते हैं क्योंकि वे निर्भरताओं की निर्भरताओं का निर्माण नहीं करते हैं। –

उत्तर

8

ऐसा लगता है कि आपको सुविधाओं पर लाभ उठाने की ज़रूरत है, उचित निर्भरता इंजेक्शन ढांचा आपको दे सकता है। परीक्षण/उत्पादन के लिए विभिन्न निर्माण तर्क का प्रयोग न करें।

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

शायद आप सिंगलटन स्कॉप्स और बहुत अधिक प्रोटोटाइप स्कोप का उपयोग कर रहे हैं?

A Singleton 
| 
B Singleton 
| 
C Prototype (per-invocation) 
| 
D Singleton 
| 
E Session scope (web app) 
| 
F Singleton 

और प्रत्येक अनुरोध केवल 1 उदाहरण बन जाएगा: (प्रोटोटाइप = नया उदाहरण हर बार)

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

यह वास्तव में एक डीआई मॉडल के भीतर न्यूनतम वस्तु निर्माण संभव बनाता है, मुझे लगता है।

हालांकि यह जावा के लिए वसंत है, मुझे विश्वास है कि कई अन्य डी ढांचे को समान सुविधाओं का समर्थन करना चाहिए। शायद सबसे कम से कम नहीं।

+0

एफ ई वस्तु दी है? यदि हां, तो यह एकाधिक उपयोगकर्ताओं के साथ कैसे काम करता है? –

+0

मैं ऊपर से नीचे सोच रहा था, और डी को ई गतिशील प्रॉक्सी या cglib जादू दिया जाता है। – krosenvold

+0

और हाँ, यह कई उपयोगकर्ताओं के साथ वास्तव में अच्छी तरह से काम करता है। 300 अक्षर छोटे से छोटे हो जाते हैं। Http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes देखें – krosenvold

1

संदर्भों में गुजरने के बारे में कैसे?

0

सबसे अच्छा मैं आ सकता हूं कि सभी निर्भरताओं को एक "संदर्भ" ऑब्जेक्ट में रखा जाए, जिसे बाद में सभी मामलों में साझा किया जाता है। यह कुछ हद तक प्रदर्शन की समस्या को कम करना चाहिए।

1

यदि आपकी चिंता धीमी परीक्षण है, तो उन्हें समानांतर में चलाने का प्रयास करें और परीक्षण प्रक्रिया को अपने प्रोग्रामर को बाधित न होने दें।

स्वचालित इस प्रक्रिया:

  • जब कुछ एक में जाँच करता है, भंडार के बाहर एक निर्माण कर सकते हैं।
  • इस बिल्ड पर परीक्षण चलाएं।
  • ई - उन परिणामों को मेल करें जो चेक इन किए गए डेवलपर को मेल करें।

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

  • यदि परीक्षण पास होते हैं (और वैकल्पिक मानदंड पूरा हो जाते हैं), तो वास्तविक संग्रह के साथ नया कोड मर्ज करें।

इस प्रकार, धीमी परीक्षण कोई चिंता नहीं है। इसके अलावा जब एक डेवलपर को यह पता होना चाहिए कि उसके कोड ने कुछ तोड़ दिया है या प्रदर्शन की बढ़ोतरी की उम्मीद की है, तो वह बस जांचती है और उसके लिए उत्पन्न ई-मेल की प्रतीक्षा करती है।

2

मुझे लगता है कि आपको केवल "डी कन्स्ट्रक्टर" होना चाहिए। आप इस कन्स्ट्रक्टर को परीक्षण के साथ-साथ उत्पादन में भी कॉल करते हैं।

class ShortLivedThing { 
    IDependency1 dep1; 
    IDependency1 dep2; 
    IDependency1 dep3; 
    ... 

    int TheRealData; 

    public ShortLivedThing(IDependency1 d1, IDependency2 d2, IDependency3 d3) { 
    dep1 = d1; dep2 = d2; dep3 = d3; 
    } 
} 

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

सारांश में: 50% DI/50% हार्डकोडिंग के लिए न जाएं, 100% DI के लिए जाएं।

0

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

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