रिपोजिटरी या रिपोजिटरी को नहीं


10

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

अब मैं अनिश्चित हूं कि मुझे क्या करना है। रिपॉजिटरी के लिए या रिपॉजिटरी को नहीं। मैं वास्तव में इस तर्क को समझता हूं कि इस तरह के टोने-टोटके अमूर्त चीजों को जोड़ते हुए पूरी तरह से जटिल हो जाते हैं, जो डेटा एक्सेस को आसान बना सकते हैं, हालांकि, यह मेरे आवेदन के हर संभव पहलू जैसे कि एंटिटी फ्रेमवर्क को युगल करना सही नहीं लगता है । आमतौर पर, मैं कुछ सरल दिशानिर्देशों का पालन करता हूं:

  1. डोमेन लेयर सिस्टम का दिल है, जिसमें इकाइयाँ, सेवाएँ, रिपॉजिटरी शामिल हैं ...
  2. इन्फ्रास्ट्रक्चर लेयर एक इन्फ्रास्ट्रक्चरल चिंता, जैसे फ़ाइल, डेटाबेस, प्रोटोकॉल के डोमेन इंटरफेस का कार्यान्वयन प्रदान करता है।
  3. एप्लीकेशन लेयर एक कंपोजीशन रूट को होस्ट करता है जो चीजों को वायर करता है और सब कुछ ऑर्केस्ट्रेट करता है।

मेरे समाधान आमतौर पर इस तरह दिखते हैं:

Domain.Module1
Domain.Module2
    IModule2Repo
    IModule2Service
    Module2
Infrastructure.Persistence
    Repositories
        EntityFrameworkRepositoryBase
MyApp
    Boostrapper
        -> inject EntityFrameworkRepositoryBase into IRepository etc.

मैं अपने डोमेन की परत को साफ रखता हूं, IRepository<'T>जो कि एक ऐसी डोमेन चिंता है जो किसी और चीज पर निर्भर नहीं करता है जो मुझे बताती है कि डेटा का उपयोग कैसे किया जाए। जब मैं अब इसका ठोस क्रियान्वयन IModule2Serviceकरूंगा, इसके लिए डेटा एक्सेस की आवश्यकता होगी, तो मुझे इसे इंजेक्ट करना होगा DbContextऔर इसे सीधे इन्फ्रास्ट्रक्चर लेयर पर युग्मित करना होगा। ( विजुअल स्टूडियो परियोजना के लिए आ रहा है, यह परिपत्र निर्भरता के कारण वास्तव में मुश्किल हो सकता है! )

इसके अतिरिक्त, डिपॉजिटरी और कार्यों के बकवास का एक विकल्प क्या हो सकता है ? CQRS? एक शुद्ध अवसंरचनात्मक ढांचे का सार कैसे होता है?


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

जवाबों:


4

इंजीनियरिंग सभी समझौता है। और इसलिए सॉफ्टवेयर विकास है। अभी, मेरा मानना ​​है कि केवल अन्य विकल्प, जो सरल होगा, ORM के साथ सीधे काम करना है। लेकिन जैसा आपने कहा, वह आपको विशिष्ट दृढ़ता ढांचे में बंद कर सकता है।

तो आपको अपने आप से पूछना होगा "क्या दृढ़ता से आपके कोड के डिकॉउलिंग के लायक अतिरिक्त जटिलता है"। हर बार जब मैं लोगों को यह कहते हुए सुनता हूं कि वे अपने कोड को दृढ़ता से कम करना चाहते हैं, तो मैं पूछता हूं "आपने अपने करियर में कितनी बार अपने दृढ़ता ढांचे को बदल दिया है?"

मैं रिपॉजिटरी के साथ जो समस्याएं देख रहा हूं, वह यह है कि वे आम बदलावों को कठिन बनाते हैं। उदाहरण के लिए। एक समग्र क्वेरी के लिए नया तरीका जोड़ना। और वे असामान्य परिवर्तन (माना जाता है) को आसान बनाते हैं। उदाहरण के लिए। रिपॉजिटरी के कार्यान्वयन को बदलना।

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


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

एक कुल रूट या किसी भी इकाई को क्वेरी करने के लिए एक नया तरीका जोड़ने के बारे में , यही कारण है कि CQRS दिखाई दिया। व्यक्तिगत रूप से, मैं डोमेन उद्देश्यों के लिए रिपॉजिटरी रखता हूं और वास्तविक क्वेरी के लिए क्वेरी हैंडलर का उपयोग करता हूं। और उन संचालकों को db और toc पर बहुत कसकर जोड़ा जाता है जो वे करते हैं।
14:53 बजे माइकएसडब्ल्यू

3

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

  • डेटा की पुनःप्राप्ति
  • डेटा निर्माण
  • कड़ा हट जाना

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

डेटा अपडेट सवाल में संस्थाओं (एस) के साथ काम करने वाले व्यावसायिक तर्क की जिम्मेदारी है। इसमें सत्यापन नियम जैसी चीजें शामिल हो सकती हैं। मैं एक रिपॉजिटरी पद्धति में इनकैप्सुलेट करने की कोशिश नहीं करता।

मेरे अधिकांश सिस्टम में डिलीट सॉफ्ट-डिलीट है इसलिए यह डेटा अपडेट के अंतर्गत आएगा। (IsActive = false) हार्ड-डिलीट के मामले में यह रिपोजिटरी में वन-लाइनर होगा।

रिपोजिटरी क्यों? टेस्ट की क्षमता। ज़रूर, DbContext का मज़ाक उड़ाया जा सकता है, लेकिन जो क्लास में लौटता है उसका मज़ाक उड़ाना ज्यादा आसान हैIQueryable<TEntity>। वे यूओडब्ल्यू पैटर्न के साथ भी अच्छा खेलते हैं, व्यक्तिगत रूप से मैं मेहदीम के डीबीसीकोटेक्स्टस्कोप पैटर्न का उपयोग करता हूं, जो मैं चाहता हूं कि स्तर पर कार्य की इकाई (एमवीसी में नियंत्रकों) को गुंजाइश देने के लिए और मेरे नियंत्रकों और सहायक सेवा वर्गों को संदर्भों को पास किए बिना रिपॉजिटरी का उपयोग करने दें। UoW / dbContext के आसपास। IQueryable का उपयोग करने का अर्थ है कि आपको रिपॉजिटरी में बहुत सारे रैपर तरीकों की आवश्यकता नहीं है, और आपका कोड ऑप्टिमाइज़ कर सकता है कि डेटा की खपत कैसे होने वाली है। उदाहरण के लिए, रिपॉजिटरी को "एक्जिस्ट" या "काउंट" जैसी विधियों को उजागर करने की आवश्यकता नहीं है, या उन मामलों में अन्य POCO के साथ संस्थाओं को लपेटने का प्रयास करें जहां आप डेटा के उप-सेट चाहते हैं। उन्हें संबंधित डेटा के लिए उत्सुक-लोडिंग विकल्पों को संभालने की भी आवश्यकता नहीं है, जिनकी आपको आवश्यकता हो सकती है या नहीं। IQueryable पास करके, कॉलिंग कोड कर सकते हैं:

.Any()
.Count()
.Include() // Generally avoided, instead I use .Select()
.Where()
.Select(x => new ViewModel or Anon. Type)
.Skip().Take()
.FirstOrDefault() / .SingleOrDefault() / .ToList()

बहुत लचीला है, और एक परीक्षण पीओवी से मेरी नकली रिपॉजिटरी को बस आबादी वाली वस्तुओं की सूची वापस करने की आवश्यकता है।

जेनेरिक रिपॉजिटरी के रूप में, मैं इन सबसे भाग के लिए दूर चला गया हूं क्योंकि जब आप प्रति टेबल रिपॉजिटरी के साथ समाप्त होते हैं तो आपके नियंत्रक / सेवाएं एक बिजनेस एक्शन करने के लिए कई रिपॉजिटरी के संदर्भ के साथ समाप्त होते हैं। ज्यादातर मामलों में, इनमें से केवल एक या दो रिपॉजिटरी वास्तव में लेखन कार्य कर रहे हैं (बशर्ते आप नेविगेशन गुणों का सही तरीके से उपयोग कर रहे हों), जबकि बाकी लोग रीड्स का समर्थन कर रहे हैं। मेरे पास कुछ ऐसा होगा जैसा कि एक OrdersRepository है, जो ऑर्डर बनाने और किसी भी प्रासंगिक लुकअप आदि (हल्के ग्राहक ऑब्जेक्ट्स, उत्पाद आदि) को पढ़ने के लिए और एक ऑर्डर बनाते समय संदर्भ के लिए 5 या 6 विभिन्न रिपॉजिटरी को मारने की तुलना में पढ़ने में सक्षम है। यह DNRY शुद्धतावादियों का उल्लंघन कर सकता है, लेकिन इसके लिए मेरा तर्क यह है कि रिपॉजिटरी का उद्देश्य आदेशों के निर्माण की सेवा करना है जिसमें संबंधित संदर्भ शामिल हैं।Repository<Product>उत्पादों को प्राप्त करने के लिए जहां एक आदेश के आधार पर मुझे केवल एक मुट्ठी भर क्षेत्रों के साथ एक इकाई की आवश्यकता होती है। मेरे आर्डर रिपॉजिटरी में एक ऐसी .GetProducts()विधि हो सकती है IQueryable<ProductSummary>जो मुझे अच्छी लगती है, जो Repository<Product>कि आवेदन की ज़रूरतों के विभिन्न क्षेत्रों और / या कुछ जटिल पास-इन फ़िल्टरिंग अभिव्यक्ति की कोशिश करने और सेवा करने के लिए कई "गेट" तरीके हैं।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.