2008-09-24 13 views
6

This question about unit testing best practices निर्भरता इंजेक्शन के लिए कक्षाओं को डिजाइन करने का उल्लेख करता है। इसने मुझे यह सोचने के लिए प्रेरित किया कि इसका क्या अर्थ हो सकता है।निर्भरता इंजेक्शन के लिए कक्षाओं को डिजाइन करने के लिए दिशानिर्देश

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

जिस तरह से मैं इसे देखता हूं, वहां तीन मूल प्रकार की निर्भरताएं होती हैं जिन पर एक ऑब्जेक्ट हो सकता है।

  1. वस्तु निर्भरता - एक वास्तविक वस्तु है कि प्रश्न में वर्ग द्वारा उपयोग किया जाएगा। उदाहरण के लिए LogInFormController में LogInVerifier। इन्हें कन्स्ट्रक्टर के माध्यम से इंजेक्शन दिया जाना चाहिए। यदि कक्षा पर्याप्त रूप से उच्च स्तर है कि इसे कन्स्ट्रक्टर में इन 4 से अधिक वस्तुओं की आवश्यकता होती है तो इसे तोड़ने पर विचार करें या कम से कम फैक्ट्री पैटर्न का उपयोग करें। आपको इंटरफेस के खिलाफ एक इंटरफ़ेस और कोडिंग के साथ निर्भरता प्रदान करने पर भी विचार करना चाहिए।
  2. एक साधारण सेटिंग - उदाहरण के लिए एक थ्रेसहोल्ड या टाइमआउट अवधि। इन्हें आम तौर पर एक डिफ़ॉल्ट मान होना चाहिए और कारखाने के पैटर्न के निर्माता के माध्यम से सेट किया जाना चाहिए। आप कन्स्ट्रक्टर अधिभार भी प्रदान कर सकते हैं जो उन्हें सेट करते हैं। हालांकि ज्यादातर मामलों में आपको शायद क्लाइंट को इसे स्पष्ट रूप से सेट अप करने के लिए मजबूर नहीं करना चाहिए।
  3. एक संदेश ऑब्जेक्ट - एक ऑब्जेक्ट जो एक वर्ग से दूसरी कक्षा में सौंपी जाती है जो प्राप्तकर्ता वर्ग व्यावसायिक तर्क के लिए संभवतः उपयोग करता है। LogInCompleRouter क्लास के लिए एक उदाहरण एक उपयोगकर्ता ऑब्जेक्ट होगा। यहां मुझे लगता है कि संदेश के लिए यह अक्सर बेहतर होता है कि कन्स्ट्रक्टर में निर्दिष्ट नहीं किया जाना चाहिए क्योंकि आपको या तो आईओसी कंटेनर (इसे वैश्विक बनाना) के साथ उपयोगकर्ता आवृत्ति पंजीकृत करना होगा या लॉग इन कॉम्प्लेटर राउटर को तुरंत चालू नहीं करना चाहिए जब तक कि आपके पास उपयोगकर्ता का उदाहरण न हो (जिसके लिए आप DI का उपयोग नहीं कर सके या कम से कम कंटेनर पर स्पष्ट निर्भरता की आवश्यकता होगी)। इस मामले में संदेश ऑब्जेक्ट में केवल उस समय में गुजरना बेहतर होगा जब आपको विधि कॉल के लिए इसकी आवश्यकता हो (यानी LoginInCompleteRouter.Route (उपयोगकर्ता यू);)।

इसके अलावा, मैं उल्लेख करना चाहिए कि नहीं सब कुछ DI'ed किया जाना चाहिए, अगर आपको लगता है कि सिर्फ एक थ्रो-दूर वर्ग के लिए बाहर कारक सुविधाजनक था कार्यशीलता का एक सरल सा है, यह शायद का दृष्टांत के लिए ठीक है उसी स्थान पर। जाहिर है यह एक निर्णय कॉल है; अगर मैं इसे उपाय के रूप में

class PasswordEqualsVerifier { 
    public bool Check(string input, string actual) { return input===actual;} 
} 

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

तो आप लोग क्या सोचते हैं? कोई भी अतिरिक्त दिशानिर्देश या विपरीत विचारों का स्वागत है।

उत्तर

1

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

उदाहरण के लिए, यदि आप एक डेटा एक्सेस वस्तु है, तो आप के लिए इच्छुक इस तरह सभी DAOs के लिए एक आधार लिखने के लिए हो सकता है:

public class BaseDAO 
{ 
    public BaseDAO(String connectionURL, 
        String driverName, 
        String username, String password) 
    { 
     // use them to create a connection via JDBC, e.g. 
    } 

    protected Connection getConnection() { return connection; } 
} 

हालांकि, यह बेहतर होगा पक्ष में वर्ग से दूर करने के लिए एक अंतरफलक

public interface DatabaseConnection 
{ 
    Connection getConnection(); 
} 

public class BaseDAO 
{ 
    public BaseDAO(DatabaseConnection dbConnection) 
    { 
     this.dbConnection = dbConnection; 
    } 

    protected Connection getConnection() { return dbConnection.getConnection(); } 
} 

अब, आप DatabaseConnection की multilple imlementations प्रदान कर सकते हैं। यूनिट परीक्षण को अनदेखा करते हुए, अगर हम मानते हैं कि हम जेडीबीसी का उपयोग कर रहे हैं, तो Connection प्राप्त करने के दो तरीके हैं: कंटेनर से कनेक्शन पूल, या सीधे ड्राइवर का उपयोग करके। अब, आपका डीएओ कोड या तो रणनीति के साथ नहीं है।

परीक्षण के लिए, आप MockDatabaseConnection बना सकते हैं जो आपके कोड का परीक्षण करने के लिए डिब्बाबंद डेटा के साथ कुछ एम्बेडेड जेडीबीसी कार्यान्वयन से जुड़ता है।

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

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