2011-04-03 12 views
11

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

A 
| 
+-------------+ 
|    | 
B1   B2 
|    | 
+------+  +------+ 
|  |  |  | 
C11 C12 C21 C22 

जाहिर है, इकाई परीक्षण पत्ते काम करता है, C11, C12, C21, और C22 बहुत आसान है:: सेटअप आदानों, कार्यों आह्वान, जोर ऐसा नहीं है कि इस तरह दिखना कॉल-निर्भरता के साथ कार्य करता है आउटपुट।

लेकिन बी 1, बी 2 और ए के लिए अच्छी इकाई परीक्षण को सक्षम करने के लिए उचित रणनीति क्या है?

Dependency Injection सुझाव देगा कि B1 (और B2 भी) के रूप में घोषित किया जाना चाहिए?

// Declare B1 with dependency injection for invoking C11 and C12. 
int B1(int input, int (*c11)(int), int(*c12)(int)); 

लेकिन अगर मेरी कॉल की कई परतें हैं तो यह रणनीति स्केलेबल प्रतीत नहीं होती है। बस कल्पना करें कि A के लिए घोषणा क्या दिखाई देगी:

int A(int input, int (*b1)(int, int (*)(int), int(*)(int)), 
       int(*b2)(int, int (*)(int), int(*)(int)), 
       int (*c11)(int), 
       int (*c12)(int), 
       int (*c21)(int), 
       int (*c22)(int)); 

यक! कोई बेहतर तरीका ज़रूर होगा।

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

सी में बड़ी सॉफ्टवेयर परियोजनाएं जैसे कि पर्ल और रूबी, यूनिट-परीक्षण से संबंधित हैं?

उत्तर

3

यदि आपको केवल इकाई परीक्षण के लिए डीआई की आवश्यकता है तो आप इसे करने के लिए लिंकर का उपयोग कर सकते हैं।

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

आप गतिशील निर्भरता संकल्प कार्यावधि में आप एक कारखाने पैटर्न समारोह संकेत के लिए (समारोह-सूचक वाला फ़ंक्शन) का उपयोग और जरूरत पड़ने पर कारखाने से उन्हें खींच चाहिए की आवश्यकता होती है। कारखाना वैश्विक संदर्भ के आधार पर तय कर सकता है कि कौन सा कार्य वापस लौटना है।

+0

यह एक दिलचस्प विचार है। मुझे इसे आजमाना होगा। – kirakun

+0

आप प्रक्रिया में न केवल सीओ में ओओ प्रोग्राम भी कर सकते हैं। केवल डेटा सदस्यों और स्ट्रक्चर को पहले तर्क के रूप में ले जाने वाले कार्यों के साथ एक संरचना घोषित करें (इस सूचक को छद्म)। सी फाइल में कार्यान्वयन और आपने स्वयं को एक छद्म वर्ग बनाया है। पॉलिमॉर्फिज्म और ऐसी चीजें संभव हैं, बस जटिल;) – sanosdole

0

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

चूंकि आप प्रक्रियात्मक हैं ... मुझे लगता है कि आप इसे संभालने के लिए फ़ंक्शन ओवरलोडिंग का उपयोग कर सकते हैं। इसके अलावा जब आप परीक्षण कर रहे हों तो आपको ए 1 कॉल करते समय केवल बी 1 & बी 2 का नकल करना होगा ... ताकि आप उस उद्देश्य के लिए अपने DI को सरल बना सकें। दूसरे शब्दों में आप वास्तव में केवल इकाई परीक्षण के लिए डि का उपयोग कर तो आप केवल dependcies प्रथम स्तर dependecies के पूरे पेड़ इंजेक्षन की जरूरत नहीं है अगर ...

तो एक से आप हो सकता है ...

int A(int input){ 
// create function point to b1 & b2 and call "return A(input, {pointer to b1},{pointer to b2})" 
} 

मेरी छद्म कोड माफ कर यह एक लंबे समय के बाद से मैं तुम्हें एक सी struct कि समारोह कॉल के लिए एक पैरामीटर हो जाएगा करने के लिए निर्भरता डाल सकते हैं सी

2

किया गया है। सी में यह फ़ाइल एपीआई के समान होगा जहां पहला पैरामीटर हमेशा फ़ाइल-हैंडल

+0

हम अन्य भाषाओं में एक समान बात करते हैं, एक सेवा प्रदाता है जिसमें इसमें सभी प्रकार की निर्भरताओं का कार्यान्वयन है। इसमें फ़ंक्शन हस्ताक्षर में कम परिवर्तन करने और रिफैक्टरिंग को आसान बनाने का अतिरिक्त बोनस है। – Enno

3

A केवल B1 और B2 पर कॉल करने की आवश्यकता है। इसे सी स्तर पर कुछ भी जानने की जरूरत नहीं है।

A परीक्षण के उद्देश्य के लिए आप B1 और B2A में फ़ंक्शंस के एक अलग डमी संस्करण इंजेक्ट कर सकते हैं।

यह पूरे संरचना की आवश्यकता से A को अलग करता है और इसका मतलब है कि आप अलगाव में प्रत्येक कार्य का परीक्षण कर सकते हैं।

0

आप बी 1, बी 2 और ए के बिना डीआई के उचित इकाई परीक्षण कर सकते हैं। पत्ती के कार्यों की तरह, बी 1 और बी 2 में वैध इनपुट और आउटपुट हैं, और आप उन लोगों का परीक्षण करते हैं, ए। बी बी 1 आंतरिक रूप से सी 11 और सी 12 का उपयोग कर सकते हैं ताकि आप अपने यूनिट परीक्षणों को पूरा करने में मदद कर सकें, इसका मतलब यह नहीं है कि उन्हें मामलों में इंजेक्शन देना है जहां आपको उस लचीलापन की आवश्यकता नहीं है।

+0

लेकिन यह कैसे स्केल करता है? विनिर्देशन पर, 'ए' 'बी 1' और' बी 2 'की कार्यक्षमताओं को कवर करेगा, जिनमें से दोनों' सी 11 ', 'सी 12',' सी 21', और 'सी 22' की कार्यक्षमताओं को भी शामिल करेंगे। तो, पत्ती कार्यों 'सी 11', आदि के लिए सभी परीक्षणों को उनके ऊपर के सभी नोड कार्यों के लिए दोहराया जाना होगा। अब, कोड के गहरा स्तर से सेट की कल्पना करें। आपको लेखन परीक्षण बहुत श्रमिक मिल सकता है। – kirakun

+0

@ किराकुन व्यावहारिक मामलों में ए बी 1 और बी 2 के समान नहीं कर रहा है, यह कुछ प्रकार की अतिरिक्त कार्यक्षमता जोड़ रहा है। यदि आपके पास बी 1 और बी 2 के लिए परीक्षण हैं तो आप कोड के उस हिस्से में आत्मविश्वास प्राप्त कर सकते हैं। आप के लिए केवल तभी परीक्षण करें कि आपको बी 1 और बी 2 के साथ संबंधों के बारे में विश्वास करने की आवश्यकता है। – tddtrying

+0

@tddtrying IMHO * इकाई * परीक्षण (उपरोक्त परिदृश्य में) का अर्थ है बी-स्तर में परीक्षण के बिना 'ए' * परीक्षण (यानी कॉलिंग) परीक्षण, सी-स्तर का उल्लेख नहीं करना। बी-स्तर बहस योग्य हो सकता है लेकिन कल्पना करें कि 'सी 11' डेटाबेस से जुड़ता है। आप वास्तविक 'सी 11' को कॉल करने के लिए 'ए' (या' बी 1') के लिए यूनिट परीक्षण नहीं चाहते हैं। इसके बजाय किसी प्रकार का नकली -' सी 11' कहा जाना चाहिए। – TobiMcNamobi

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