डेटा ऑब्जेक्ट्स के लिए निर्भरता इंजेक्शन का उपयोग करें?


11

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

Class DO{
    DO(){
        DataObject2List = new List<DO2>();
    }

    public string Field1;
    public string Field2;
    public List<DO2> DataObject2List;
}

Class DO2{
    public DateTime Date;
    public double Value;
}

"डेटा ऑब्जेक्ट" से आपका वास्तव में क्या मतलब है? यह एक मानक शब्द नहीं है। क्या आप किसी DTO के बारे में बात कर रहे हैं या आप बिना किसी तरीके (जैसे किसी डोमेन मॉडल के विशेष रूप से उबाऊ हिस्से) के साथ किसी भी वर्ग का उल्लेख कर रहे हैं? दोनों के बीच बहुत बड़ा अंतर है।
एरोन

ज़रूर, मेरा मतलब सिर्फ एक वर्ग है जिसमें कोई विधियां नहीं हैं, एक वर्ग जो सिर्फ डेटा संग्रहीत करता है। यदि डेटा ऑब्जेक्ट इसके लिए सही शब्द नहीं है, तो क्या कोई एक है, या क्या इसे बिना किसी तरीके के एक वर्ग कहा जाता है?

@sooprise यह एक अच्छा सवाल है। अच्छी सोच।
मैथ्यू रोडैटस

@sooprise शायद मेरा जवाब आधार है। आप CRUD के तरीके कहाँ से लाएँगे? एक अलग डेटा एक्सेस क्लास में जो डेटा ऑब्जेक्ट्स को ले जाएगा और उन्हें डेटाबेस तालिका में बनाए रखेगा? Ie DataAccess.Create (<DataObject>)?
मैथ्यू रोडटस

1
@ मैथ्यू, यह एक डेटा एक्सेस ऑब्जेक्ट होगा - यदि वास्तव में ओपी के बारे में बात हो रही है, तो यह बिल्कुल भी स्पष्ट नहीं है। आधुनिक कार्यान्वयन वैसे भी इस पैटर्न से दूर चले जाते हैं, जो रिपॉजिटरी और / या काम की इकाइयों पर निर्भर होते हैं।
एरोन

जवाबों:


7

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

निर्भरता:

एक "निर्भरता" आम तौर पर एक जटिल वस्तु होती है जो कुछ कार्यक्षमता करती है जिसे किसी अन्य वर्ग को निर्भर होने की आवश्यकता हो सकती है। कुछ क्लासिक उदाहरण एक लकड़हारा या एक डेटाबेस एक्सेसर या कुछ घटक होगा जो किसी विशेष व्यापार तर्क की प्रक्रिया करता है।

एक डेटा केवल एक डीटीओ या एक मूल्य वस्तु की तरह वस्तु आम तौर पर, एक "निर्भरता" कहा जाता है नहीं कर रहे हैं क्योंकि वे कुछ आवश्यक कार्य करते हैं नहीं है।

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

निर्भरता अन्तःक्षेपण:

यदि आपकी DO2कक्षा वास्तव में कुछ अतिरिक्त कार्यक्षमता प्रदान कर रही है जिसकी DOवर्ग को आवश्यकता है, तो यह वास्तव में एक निर्भरता होगी। उस स्थिति में, आश्रित वर्ग, DOको एक इंटरफ़ेस (जैसे ILogger या IDataAccessor) पर निर्भर होना चाहिए, और बदले में उस इंटरफ़ेस को प्रदान करने के लिए कॉलिंग कोड (दूसरे शब्दों में, DOउदाहरण में इसे 'इंजेक्ट करने के लिए) पर निर्भर होना चाहिए ।

इस तरह से निर्भरता को इंजेक्ट करना DOऑब्जेक्ट को अधिक लचीला बनाता है , क्योंकि प्रत्येक अलग-अलग संदर्भ DOऑब्जेक्ट को इंटरफ़ेस का अपना कार्यान्वयन प्रदान कर सकता है । (यूनिट परीक्षण सोचें।)


7

मैं सवाल में भ्रम के माध्यम से कटौती करने के लिए अपना सर्वश्रेष्ठ करने जा रहा हूं।

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

  • मूल्य ऑब्जेक्ट या "रिकॉर्ड" की कोई पहचान नहीं है। उन्हें मूल्य प्रकार होना चाहिए , कॉपी-ऑन-रेफरेंस शब्दार्थ के साथ, यह मानते हुए कि पर्यावरण इसका समर्थन करता है। चूंकि ये निश्चित संरचनाएं हैं, एक VO केवल एक आदिम प्रकार या प्राइमेटिक्स का एक निश्चित क्रम होना चाहिए। इसलिए, VO के पास कोई निर्भरता या संबद्धता नहीं होनी चाहिए ; कोई भी नॉन-डिफॉल्ट कंस्ट्रक्टर केवल वैल्यू को इनिशियलाइज़ करने के उद्देश्य से मौजूद होगा, क्योंकि इसे शाब्दिक के रूप में व्यक्त नहीं किया जा सकता है।

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

  • अंत में, डेटा एक्सेस ऑब्जेक्ट किसी प्रकार के डेटाबेस को एक आवरण या अग्रभाग प्रदान करते हैं। ये स्पष्ट रूप से निर्भरताएं हैं - वे डेटाबेस कनेक्शन और / या दृढ़ता घटकों पर निर्भर करते हैं। हालांकि, उनकी निर्भरता लगभग हमेशा बाहरी रूप से प्रबंधित होती है और कॉल करने वालों के लिए पूरी तरह से अदृश्य होती है। में सक्रिय रिकॉर्ड पैटर्न यह रूपरेखा है कि विन्यास के माध्यम से सब कुछ का प्रबंधन करता है, पुराने (आज के मानकों से प्राचीन) DAO मॉडल आप केवल कंटेनर के माध्यम से कभी भी इनका निर्माण कर सकते हैं। अगर मैंने इनमें से किसी एक को कंस्ट्रक्टर इंजेक्शन के साथ देखा, तो मैं बहुत चिंतित होऊंगा।

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

इनमें, आप आमतौर पर इंजेक्शन के लिए एक कंस्ट्रक्टर प्रदान नहीं करते हैं; इसके बजाय, आपको बस संपत्ति को आभासी बनाने और एक अमूर्त प्रकार (उदाहरण के IList<T>बजाय List<T>) का उपयोग करने की आवश्यकता है । बाकी सब पर्दे के पीछे होता है, और किसी को समझ नहीं आता।

तो सभी में मैं कहूंगा कि "डेटा ऑब्जेक्ट" पर लागू होने वाला एक दृश्य डि पैटर्न अनावश्यक है और शायद लाल झंडा भी है; लेकिन बड़े हिस्से में, ऐसा इसलिए है क्योंकि वस्तु का बहुत अस्तित्व एक लाल झंडा है, सिवाय मामले में जब इसे विशेष रूप से डेटाबेस से डेटा का प्रतिनिधित्व करने के लिए उपयोग किया जा रहा है। लगभग हर दूसरे मामले में यह एक कोड गंध, आम तौर पर एक की शुरुआत है खून की कमी डोमेन मॉडल या बहुत कम से कम एक में Poltergeist

दोहराना:

  1. "डेटा ऑब्जेक्ट्स" न बनाएं।
  2. यदि आपको "डेटा ऑब्जेक्ट" बनाना होगा, तो सुनिश्चित करें कि इसका स्पष्ट रूप से परिभाषित उद्देश्य है । यह उद्देश्य आपको बताएगा कि DI उचित है या नहीं। किसी ऐसी वस्तु के बारे में कोई सार्थक डिजाइन निर्णय लेना असंभव है जो पहली जगह पर मौजूद न हो।

फिन।


0

आपके उदाहरण में, DOकोई कार्यात्मक निर्भरता नहीं है (मूल रूप से क्योंकि यह कुछ भी नहीं करता है)। इसमें ठोस प्रकार पर निर्भरता होती है DO2, इसलिए आप एक इंटरफ़ेस को अमूर्त रूप से पेश करना चाहते हैं DO2, ताकि उपभोक्ता अपने स्वयं के ठोस कार्यान्वयन को बच्चे वर्ग के लिए लागू कर सके।

वास्तव में, आप यहाँ किस निर्भरता को इंजेक्ट करेंगे?


उनके एक अन्य प्रश्न के अनुसार जिसका मैंने उत्तर दिया, मुझे लगता है कि प्रश्न में शामिल CRUD ऑपरेशन के साथ डेटा ऑब्जेक्ट को संदर्भित किया गया है। डेटा ऑब्जेक्ट में डेटाबेस निर्भरता को कैसे / कहाँ इंजेक्ट किया जाता है? विधियों में? कंस्ट्रक्टर में? कोई और तरीका? धारणा यह है कि तरीकों के शरीर में निर्भरता को दूर नहीं छिपाया जाना चाहिए - जो डेटा ऑब्जेक्ट से डेटाबेस निर्भरता को अलग करने में अक्षम करता है ताकि डेटा ऑब्जेक्ट को परीक्षण किया जा सके।
मैथ्यू रोडाटस

@ मट्टू रोडाटस - मैं देख रहा हूं। हां, उस मामले में, आपके पास दो विकल्प हैं: दृढ़ता सेवा को इंजेक्ट करें या एक और वर्ग बनाएं, DOPersisterजो जानता है कि कैसे बनी रहें DOऔर इसे सख्ती से डेटा-ओनली ऑब्जेक्ट (मेरी राय में बेहतर) के रूप में छोड़ दें। बाद के मामले में, DOPersisterडेटाबेस निर्भरता के साथ इंजेक्ट किया जाएगा।
स्कॉट व्हिटलॉक

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

0

चूंकि यह डेटा एक्सेस लेयर में डेटा ऑब्जेक्ट है, इसलिए इसे सीधे डेटाबेस सेवा पर निर्भर होना चाहिए। आप कंस्ट्रक्टर के लिए एक डेटाबेस सेवा निर्दिष्ट कर सकते हैं:

DataObject dataObject = new DataObject(new DatabaseService());
dataObject.Update();

लेकिन, इंजेक्शन को कंस्ट्रक्टर में नहीं होना चाहिए। वैकल्पिक रूप से, आप प्रत्येक CRUD विधि के माध्यम से निर्भरता प्रदान कर सकते हैं। मैं इस विधि को पिछले पसंद करता हूं क्योंकि आपके डेटा ऑब्जेक्ट को यह जानने की आवश्यकता नहीं है कि यह तब तक बनी रहेगी जब तक कि आपको वास्तव में इसे बनाए रखने की आवश्यकता न हो।

DataObject dataObject = new DataObject();
dataObject.Update(new DatabaseService());

आप निश्चित रूप से निर्माण को सीआरयूडी विधियों में छिपाना नहीं चाहते हैं!

public void Update()
{
    // DON'T DO THIS!
    using (DatabaseService dbService = new DatabaseService())
    {
        ...
    }
}

एक वैकल्पिक विकल्प यह होगा कि डेटाबेससेवा का निर्माण एक उच्च श्रेणी के माध्यम से किया जाए।

public void Update()
{
    // GetDatabaseService() is protected virtual, so in unit testing
    // you can subclass the Data Object and return your own
    // MockDatabaseService.
    using (DatabaseService dbService = GetDatabaseService())
    {
        ...
    }
}

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

public void Update()
{
    // The ServiceLocator would not be a real singleton. It would have a setter
    // property so that unit tests can swap it out with a mock implementation
    // for unit tests.
    using (DatabaseService dbService = ServiceLocator.GetDatabaseService())
    {
        ...
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.