DDD - नियम जो एंटिटीज़ सीधे रिपोजिटरी तक नहीं पहुँच सकते


183

में डोमेन प्रेरित डिजाइन, वहाँ हो रहा है बहुत सारे के समझौते है कि संस्थाओं चाहिए नहीं पहुँच डेटा संग्रह स्थान सीधे।

क्या यह एरिक इवांस डोमेन ड्रिवेन डिज़ाइन बुक से आया है, या यह कहीं और से आया है?

इसके पीछे के तर्क के लिए कुछ अच्छे स्पष्टीकरण कहां हैं?

संपादित करें: स्पष्ट करने के लिए: मैं डेटा लॉजिक को व्यापार तर्क से अलग परत में अलग करने की क्लासिक OO प्रथा के बारे में बात नहीं कर रहा हूं - मैं उस विशिष्ट व्यवस्था के बारे में बात कर रहा हूं जिसके तहत DDD में, Entities को डेटा से बात नहीं करनी चाहिए सभी तक पहुंच की परत (यानी वे रिपॉजिटरी ऑब्जेक्ट्स के संदर्भ को रखने के लिए नहीं हैं)

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

अद्यतन: मार्च २०१३, सवाल पर उभार का मतलब है कि इसमें बहुत रुचि है, और हालांकि बहुत सारे उत्तर हैं, फिर भी मुझे लगता है कि अगर लोगों के पास इस बारे में विचार हैं, तो इसके लिए अधिक जगह है।


मेरे प्रश्न पर एक नज़र डालें stackoverflow.com/q/8269784/235715 , यह एक स्थिति दिखाती है जब तर्क पर कब्जा करना मुश्किल होता है, बिना इकाई के भंडार तक पहुंच के बिना। हालांकि मुझे लगता है कि संस्थाओं को रिपॉजिटरी तक पहुंच नहीं होनी चाहिए, और मेरी स्थिति का एक समाधान है जब कोड को रिपॉजिटरी संदर्भ के बिना फिर से लिखा जा सकता है, लेकिन वर्तमान में मैं किसी के बारे में नहीं सोच सकता।
एलेक्स बर्टसेव

पता नहीं कहाँ से आया है। मेरे विचार: मुझे लगता है कि यह गलतफहमी लोगों से आती है कि कैसे समझ में नहीं आता कि DDD क्या है। यह दृष्टिकोण सॉफ्टवेयर को लागू करने के लिए नहीं है बल्कि इसे डिजाइन करने के लिए है (डोमेन .. डिजाइन)। पिछले दिनों में, हमारे पास आर्किटेक्ट और कार्यान्वयनकर्ता थे, लेकिन अब सिर्फ सॉफ्टवेयर डेवलपर हैं। DDD आर्किटेक्ट्स के लिए है। और जब एक वास्तुकार सॉफ्टवेयर डिजाइन कर रहा होता है, तो उसे तैयार मेमोरी को लागू करने के लिए कुछ मेमोरी या डेटाबेस का प्रतिनिधित्व करने के लिए कुछ टूल या पैटर्न की आवश्यकता होती है। लेकिन डिजाइन खुद (एक व्यावसायिक दृष्टिकोण से) को एक भंडार की आवश्यकता नहीं है या नहीं है।
berhalak

जवाबों:


47

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

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

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

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

टिप्पणी का जवाब 1 : सही, अच्छा सवाल। इसलिए डोमेन लेयर में सभी सत्यापन नहीं होते हैं । शार्प में एक विशेषता "DomainSignature" है जो आपको चाहिए। यह दृढ़ता से अवगत है, लेकिन एक विशेषता होने के नाते डोमेन परत को साफ रखता है। यह सुनिश्चित करता है कि आपके पास एक डुप्लिकेट संस्था नहीं है, आपके उदाहरण में समान नाम।

लेकिन चलो अधिक जटिल सत्यापन नियमों के बारे में बात करते हैं। मान लीजिए कि आप Amazon.com हैं। क्या आपने कभी एक्सपायर्ड क्रेडिट कार्ड के साथ कुछ ऑर्डर किया है? मेरे पास है, जहां मैंने कार्ड को अपडेट नहीं किया है और कुछ खरीदा है। यह आदेश को स्वीकार करता है और यूआई मुझे सूचित करता है कि सब कुछ आड़ू है। लगभग 15 मिनट बाद, मुझे यह कहते हुए एक ई-मेल मिलेगा कि मेरे आदेश में कोई समस्या है, मेरा क्रेडिट कार्ड अमान्य है। यहाँ क्या हो रहा है, आदर्श रूप से, डोमेन परत में कुछ regex सत्यापन है। क्या यह एक सही क्रेडिट कार्ड नंबर है? यदि हाँ, तो आदेश जारी रखें। हालांकि, आवेदन कार्यों की परत पर अतिरिक्त सत्यापन है, जहां एक बाहरी सेवा यह देखने के लिए बोली जाती है कि क्या क्रेडिट कार्ड पर भुगतान किया जा सकता है। यदि नहीं, तो वास्तव में कुछ भी शिप न करें, ऑर्डर स्थगित करें और ग्राहक की प्रतीक्षा करें।

सेवा परत है कि कम से मान्यता वस्तुओं को बनाने के डरो मत कर सकते हैं का उपयोग कर सकते खजाने। बस इसे डोमेन लेयर से बाहर रखें।


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

मेरी प्रतिक्रिया टिप्पणी बॉक्स की तुलना में बड़ी थी, संपादन को देखेगा।
कर्कटोसिस

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

9
धन्यवाद एलेक। इसे व्यक्त करने का एक स्पष्ट तरीका है। लेकिन मुझे यह प्रतीत होता है कि इवांस का डोमेन-केंद्रित स्वर्ण नियम 'सभी व्यापारिक तर्क को डोमेन परत में जाना चाहिए' का विरोध 'संस्थाओं को रिपॉजिटरी तक नहीं पहुंचना चाहिए' के ​​साथ है। मैं उसके साथ रह सकता हूं अगर मुझे समझ में आता है कि ऐसा क्यों है, लेकिन मुझे कोई अच्छा स्पष्टीकरण ऑनलाइन नहीं मिल रहा है कि संस्थाओं को रिपॉजिटरी तक क्यों नहीं पहुंचना चाहिए। इवांस इसका स्पष्ट उल्लेख नहीं करते हैं। यह कहां से आया? यदि आप कुछ अच्छे साहित्य की ओर इशारा करते हुए उत्तर पोस्ट कर सकते हैं, तो आप अपने आप को एक 50 वां इनाम देने में सक्षम हो सकते हैं:)
कोडुलिक

4
"उसकी छोटी पर समझ में नहीं आता है" यह एक बड़ी गलती है टीमें करते हैं ... यह एक छोटी सी परियोजना है, जैसे मैं यह कर सकता हूं और वह ... ऐसा सोचना बंद करें। कई छोटी परियोजनाएं जिनके साथ हम काम करते हैं, व्यापार आवश्यकताओं के कारण बड़ी हो जाती हैं। यदि आप कुछ छोटा या बड़ा करते हैं, तो इसे सही तरीके से करें।
मीटिटस

35

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

  1. हमें अपने इरादे को एक अनुरोध में जानना चाहिए और हम डोमेन से क्या चाहते हैं, इसलिए हम एग्रीगेट व्यवहार का निर्माण या आह्वान करने से पहले रिपॉजिटरी कॉल कर सकते हैं। यह असंगत-स्मृति स्थिति की समस्या और आलसी लोडिंग की आवश्यकता से बचने में मदद करता है (यह आलेख देखें )। गंध यह है कि आप डेटा पहुंच के बारे में चिंता किए बिना अब अपनी इकाई की मेमोरी इंस्टेंस में नहीं बना सकते हैं।
  2. CQS (कमांड क्वेरी सेपरेशन) हमारी संस्थाओं में चीजों के लिए भंडार को कॉल करने की इच्छा को कम करने में मदद कर सकता है।
  3. हम डोमेन तर्क की ज़रूरतों को एन्कैप्सुलेट और संप्रेषित करने के लिए एक विनिर्देश का उपयोग कर सकते हैं और इसके बजाय रिपॉजिटरी को पास कर सकते हैं (एक सेवा हमारे लिए इन चीजों को ऑर्केस्ट्रेट कर सकती है)। विनिर्देश उस इकाई से आ सकता है जो उस अपरिवर्तनीय को बनाए रखने के लिए प्रभारी है। रिपॉजिटरी स्पेसिफिकेशन के कुछ हिस्सों की व्याख्या स्वयं क्वेरी कार्यान्वयन में करती है और क्वेरी परिणामों पर विनिर्देश से नियम लागू करती है। इसका उद्देश्य डोमेन लेयर को डोमेन लेयर में रखना है। यह सर्वव्यापी भाषा और सांप्रदायिकता को भी बेहतर ढंग से प्रस्तुत करता है। कल्पना करें कि "अतिदेय आदेश विनिर्देश" बनाम यह कहना कि "tbl_order से फ़िल्टर ऑर्डर जहां रखा गया है_ ssdate से 30 मिनट पहले कम है" (यह उत्तर देखें )।
  4. यह एकल-जिम्मेदारी सिद्धांत के उल्लंघन के बाद से संस्थाओं के व्यवहार के बारे में अधिक कठिन बनाता है। यदि आपको संग्रहण / दृढ़ता के मुद्दों पर काम करने की आवश्यकता है, तो आप जानते हैं कि कहाँ जाना है और कहाँ नहीं जाना है।
  5. यह वैश्विक स्तर (रिपॉजिटरी और डोमेन सेवाओं के माध्यम से) को एक इकाई द्विशताब्दी दिशात्मक पहुंच देने के खतरे से बचा जाता है। आप अपनी लेन-देन सीमा को भी नहीं तोड़ना चाहते।

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

अंगूठे के एक नियम के रूप में, हमें अगर संभव हो तो एग्रीगेट के अंदर से रिपॉजिटरी (12) के उपयोग से बचने की कोशिश करनी चाहिए।

वर्नोन, वॉन (2013-02-06)। डोमेन-चालित डिजाइन (जलाने का स्थान 6089) को लागू करना। पियर्सन शिक्षा। किंडल संस्करण।

और अध्याय 10 में एग्रीगेट्स पर, "मॉडल नेविगेशन" शीर्षक वाले खंड में वह कहता है (ठीक इसके बाद वह अन्य समग्र जड़ों को संदर्भित करने के लिए वैश्विक अद्वितीय आईडी के उपयोग की सिफारिश करता है):

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

वह कोड में इसका एक उदाहरण दिखाता है:

public class ProductBacklogItemService ... { 

   ... 
   @Transactional 
   public void assignTeamMemberToTask( 
        String aTenantId, 
        String aBacklogItemId, 
        String aTaskId, 
        String aTeamMemberId) { 

        BacklogItem backlogItem = backlogItemRepository.backlogItemOfId( 
                                        new TenantId( aTenantId), 
                                        new BacklogItemId( aBacklogItemId)); 

        Team ofTeam = teamRepository.teamOfId( 
                                  backlogItem.tenantId(), 
                                  backlogItem.teamId());

        backlogItem.assignTeamMemberToTask( 
                  new TeamMemberId( aTeamMemberId), 
                  ofTeam,
                  new TaskId( aTaskId));
   } 
   ...
}     

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

तब मेरी हमेशा मार्को पिवेटा @ ऑक्रेमियस के साथ कुछ चर्चा हुई जिन्होंने मुझे डोमेन से एक विनिर्देश निकालने और उसका उपयोग करने पर थोड़ा सा कोड दिखाया:

1) यह अनुशंसित नहीं है:

$user->mountFriends(); // <-- has a repository call inside that loads friends? 

2) एक डोमेन सेवा में, यह अच्छा है:

public function mountYourFriends(MountFriendsCommand $mount) { /* see http://store.steampowered.com/app/296470/ */ 
    $user = $this->users->get($mount->userId()); 
    $friends = $this->users->findBySpecification($user->getFriendsSpecification()); 
    array_map([$user, 'mount'], $friends); 
}

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

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

27

यह एक बहुत अच्छा सवाल है। मैं इस बारे में कुछ चर्चा के लिए तत्पर हूं। लेकिन मुझे लगता है कि इसका उल्लेख कई डीडीडी पुस्तकों और जिमी निल्सन और एरिक इवांस में है। मुझे लगता है कि यह उदाहरणों के माध्यम से भी दिखाई देता है कि रिपॉजिटरी पैटर्न का उपयोग कैसे करें।

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

जैसा कि आप देख सकते हैं कि इकाई A, B के जीवनचक्र में अधिक शामिल हो सकती है और यह मॉडल में और अधिक जटिलता जोड़ सकती है।

मुझे लगता है कि (बिना किसी उदाहरण के) इकाई-परीक्षण अधिक जटिल होगा।

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


1
अच्छी बात। मेरा अनुमान है कि पुराने स्कूल के डोमेन-मॉडल में शायद एंटिटी बी को खुद को वैध बनाने से पहले जिम्मेदार होना चाहिए। क्या आप सुनिश्चित हैं कि इवांस ने Repositories का उपयोग नहीं करने वाली संस्थाओं का उल्लेख किया है? मैं किताब के माध्यम से आधे रास्ते में हूँ और इसने अभी तक इसका उल्लेख नहीं किया है ...
कोड्यूलिक

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

1
पुस्तक P2p.wrox.com/ से DDD SmartCA उदाहरण डाउनलोड करना। आपको एक और दृष्टिकोण दिखाई देगा (हालांकि यह एक आरआईए विंडोज़ क्लाइंट है) जहां रिपॉजिटरी का उपयोग सेवाओं में किया जाता है (यहां कुछ भी अजीब नहीं है) लेकिन सेवाओं का उपयोग प्रवेश के अंदर किया जाता है। यह एक ऐसी चीज है जिसे मैं नहीं करूंगा लेकिन मैं एक वेब ऐप वाला लड़का हूं। स्मार्टसीए ऐप के लिए परिदृश्य को देखते हुए जहां आपको ऑफ़लाइन काम करने में सक्षम होना चाहिए, शायद डीडीडी डिजाइन अलग तरह से दिखाई देगा।
मैग्नस बैकियस

स्मार्टसीए उदाहरण दिलचस्प लगता है, यह किस अध्याय में है? (कोड डाउनलोड अध्याय द्वारा व्यवस्थित किए जाते हैं)
कोडुलिक

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

13

डेटा एक्सेस अलग क्यों?

पुस्तक से, मुझे लगता है कि अध्याय मॉडल ड्रिवेन डिज़ाइन के पहले दो पृष्ठ इस बात के लिए कुछ औचित्य देते हैं कि आप डोमेन मॉडल के कार्यान्वयन से तकनीकी कार्यान्वयन विवरणों को अलग क्यों करना चाहते हैं।

  • आप डोमेन मॉडल और कोड के बीच एक तंग संबंध रखना चाहते हैं
  • तकनीकी चिंताओं को अलग करना यह साबित करने में मदद करता है कि मॉडल कार्यान्वयन के लिए व्यावहारिक है
  • आप सिस्टम के डिजाइन के माध्यम से सर्वव्यापी भाषा चाहते हैं

यह एक अलग "विश्लेषण मॉडल" से बचने के उद्देश्य से लगता है जो सिस्टम के वास्तविक कार्यान्वयन से तलाक हो जाता है।

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

दूसरी दिशा में, डोमेन मॉडल में बहुत अधिक तकनीकी चिंताओं को पेश करने वाले डेवलपर्स इस विभाजन को भी पैदा कर सकते हैं।

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

का हवाला देते हुए:

"एकल मॉडल त्रुटि की संभावना को कम करता है, क्योंकि डिज़ाइन अब ध्यान से विचार किए गए मॉडल का प्रत्यक्ष विस्तार है। डिज़ाइन, और यहां तक ​​कि कोड भी, एक मॉडल की संचार क्षमता है।"

जिस तरह से मैं यह व्याख्या कर रहा हूं, यदि आप डेटाबेस एक्सेस जैसी चीजों से निपटने के लिए कोड की अधिक पंक्तियों के साथ समाप्त हो गए हैं, तो आप उस संचार को खो देते हैं।

यदि डेटाबेस तक पहुँचने की आवश्यकता विशिष्टता की जाँच करने जैसी चीज़ों के लिए है, तो एक नज़र डालें:

उदी दहन: डीडीडी को लागू करते समय सबसे बड़ी गलतियां टीमें करती हैं

http://gojko.net/2010/06/11/udi-dahan-the-biggest-mistakes-teams-make-when-applying-ddd/

"सभी नियम समान नहीं बनाए गए हैं"

तथा

डोमेन मॉडल पैटर्न को रोजगार

http://msdn.microsoft.com/en-us/magazine/ee236415.aspx#id0400119

"डोमेन मॉडल का उपयोग नहीं करने के लिए परिदृश्य" के तहत, जो एक ही विषय पर छूता है।

डेटा एक्सेस को अलग कैसे करें

एक इंटरफेस के माध्यम से डेटा लोड हो रहा है

"डेटा एक्सेस लेयर" को एक इंटरफेस के माध्यम से अमूर्त किया गया है, जिसे आप आवश्यक डेटा प्राप्त करने के लिए कहते हैं:

var orderLines = OrderRepository.GetOrderLines(orderId);

foreach (var line in orderLines)
{
     total += line.Price;
}

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

विपक्ष: कॉलिंग कोड को यह मान लेना चाहिए कि क्या लोड किया गया है और क्या नहीं।

SayOrderLines प्रदर्शन कारणों से एक अशक्त ProductInfo संपत्ति के साथ OrderLine ऑब्जेक्ट देता है। डेवलपर को इंटरफ़ेस के पीछे कोड का अंतरंग ज्ञान होना चाहिए।

मैंने वास्तविक सिस्टम पर इस विधि की कोशिश की है। आप प्रदर्शन समस्याओं को ठीक करने के प्रयास में हर समय लोड होने के दायरे को बदलते रहते हैं। आप डेटा एक्सेस कोड को देखने के लिए इंटरफ़ेस के पीछे झांकते हैं कि क्या है और लोड नहीं किया जा रहा है।

अब, चिंताओं को अलग करने से डेवलपर को एक समय में कोड के एक पहलू पर ध्यान केंद्रित करने की अनुमति मिल सकती है, जितना संभव हो सके। इंटरफ़ेस तकनीक हटाती है कि HOW यह डेटा लोड है, लेकिन HOW MUCH डेटा लोड नहीं है, जब इसे लोड किया जाता है, और जहां इसे लोड किया जाता है।

निष्कर्ष: काफी कम अलगाव!

धीरे लोड हो रहा है

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

foreach (var line in order.OrderLines)
{
    total += line.Price;
}

पेशेवरों: डेटा एक्सेस की 'WHEN, WHERE, और HOW' डेवलपर की ओर से डोमेन लॉजिक पर केंद्रित है। एग्रीगेट में कोई कोड नहीं है जो लोडिंग डेटा से संबंधित है। लोड किए गए डेटा की मात्रा कोड द्वारा आवश्यक सटीक राशि हो सकती है।

विपक्ष: जब आप एक प्रदर्शन समस्या से टकराते हैं, तो जब आप एक सामान्य "एक आकार सभी को हल करते हैं" ठीक करना मुश्किल होता है। आलसी लोडिंग से समग्र प्रदर्शन खराब हो सकता है, और आलसी लोडिंग को लागू करना मुश्किल हो सकता है।

भूमिका इंटरफ़ेस / उत्सुक लाना

प्रत्येक उपयोग के मामले को एग्रीगेट वर्ग द्वारा कार्यान्वित रोल इंटरफेस के माध्यम से स्पष्ट किया जाता है, जिससे डेटा लोडिंग रणनीतियों को प्रति उपयोग के मामले से निपटने की अनुमति मिलती है।

इस तरह दिख सकता है:

public class BillOrderFetchingStrategy : ILoadDataFor<IBillOrder, Order>
{
    Order Load(string aggregateId)
    {
        var order = new Order();

        order.Data = GetOrderLinesWithPrice(aggregateId);
    
        return order;
    }

}
   

तब आपका कुल मिलाकर ऐसा दिख सकता है:

public class Order : IBillOrder
{
    void BillOrder(BillOrderCommand command)
    {
        foreach (var line in this.Data.OrderLines)
        {
            total += line.Price;
        }

        etc...
    }
}

BillOrderFetchingStrategy का उपयोग एग्रीगेट बनाने के लिए किया जाता है, और फिर एग्रीगेट अपना काम करता है।

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

विपक्ष: डेवलपर को अभी भी डोमेन कोड बदलने के बाद लाने की रणनीति को समायोजित / समीक्षा करना है।

लाने की रणनीति दृष्टिकोण के साथ आप अभी भी अपने आप को व्यावसायिक नियमों में बदलाव के लिए कस्टम भ्रूण कोड बदल सकते हैं। यह चिंताओं का सही पृथक्करण नहीं है, लेकिन अधिक बनाए रखने योग्य है और पहले विकल्प से बेहतर है। प्राप्त करने की रणनीति HOW, WHEN और WH डेटा का डेटा कहाँ लोड करती है यह चिंताओं को बेहतर ढंग से अलग करता है, बिना लचीलेपन को खोए जैसे एक आकार सभी आलसी लोडिंग दृष्टिकोण को फिट करता है।


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

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

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

@codeulike: मैंने अपना उत्तर अपडेट कर दिया है। यदि आप महसूस करते हैं कि आप अभी भी व्यावसायिक नियमों के दौरान डेटा लोड कर सकते हैं, लेकिन इसके लिए आपको अपने डोमेन मॉडल (जैसे आलसी लोड) में डेटा एक्सेस कोड की लाइनों को जोड़ने की आवश्यकता नहीं है। मेरे द्वारा डिज़ाइन किए गए डोमेन मॉडल में, डेटा आमतौर पर अग्रिम में लोड किया जाता है जैसे आपने कहा। मैंने पाया है कि व्यावसायिक नियम चलाने के लिए आमतौर पर अत्यधिक मात्रा में डेटा की आवश्यकता नहीं होती है।
ttg

12

मुझे यह ब्लॉग मिला है कि संस्थाओं के अंदर रिपोजिटरी को एनकैप्सुलेट करने के खिलाफ काफी अच्छे तर्क हैं:

http://thinkbeforecoding.com/post/2009/03/04/How-not-to-inject-services-in-entities


हाँ, यह ब्लॉग उस सटीक मुद्दे के बारे में है जिसकी मुझे दिलचस्पी है, धन्यवाद।
कोडुइके नोव

12

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

इसलिए (कुछ ऐसा लिखने के जोखिम से, जिसे मैं अभी से एक वर्ष से असहमत हूं) यहां मेरी अब तक की खोजें हैं।

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

// Entity
public class Invoice
{
    ...
    public void SetStatus(StatusCode statusCode, DateTime dateTime) { ... }
    public void CreateCreditNote(decimal amount) { ... }
    ...
}

हम किसी भी सेवा के निर्माता के निर्माण में कोई इंजेक्शन लगाए बिना इसे प्राप्त करना चाहते हैं, क्योंकि:

  • एक नए व्यवहार का परिचय (जो एक नई सेवा का उपयोग करता है) एक रचनाकार बदलाव का कारण बन सकता है, जिसका अर्थ है कि परिवर्तन हर उस रेखा को प्रभावित करता है जो इकाई को तत्काल बदल देती है !
  • ये सेवाएं मॉडल का हिस्सा नहीं हैं , लेकिन कंस्ट्रक्टर-इंजेक्शन यह सुझाव देगा कि वे थे।
  • अक्सर एक सेवा (यहां तक ​​कि इसका इंटरफ़ेस) डोमेन के हिस्से के बजाय एक कार्यान्वयन विवरण है। डोमेन मॉडल में एक बाहरी-निर्भरता होती है
  • यह भ्रामक हो सकता है कि क्यों इकाई इन निर्भरताओं के बिना मौजूद नहीं हो सकती है। (एक क्रेडिट नोट सेवा, आप कहते हैं! मैं क्रेडिट नोट्स के साथ भी कुछ नहीं करने जा रहा हूं ...)
  • यह कठिन परिक्षण कर देगा , इस प्रकार परीक्षण करना कठिन है
  • समस्या आसानी से फैलती है, क्योंकि इसमें शामिल अन्य संस्थाओं को एक ही निर्भरता मिलेगी - जो उन पर बहुत अप्राकृतिक निर्भरता की तरह लग सकती है ।

हम कैसे कर सकते हैं? मेरा अब तक का निष्कर्ष यह है कि विधि निर्भरता और दोहरे प्रेषण एक सभ्य समाधान प्रदान करते हैं।

public class Invoice
{
    ...

    // Simple method injection
    public void SetStatus(IInvoiceLogger logger, StatusCode statusCode, DateTime dateTime)
    { ... }

    // Double dispatch
    public void CreateCreditNote(ICreditNoteService creditNoteService, decimal amount)
    {
        creditNoteService.CreateCreditNote(this, amount);
    }

    ...
}

CreateCreditNote()अब एक सेवा की आवश्यकता है जो क्रेडिट नोट बनाने के लिए जिम्मेदार है। यह दोहरी प्रेषण का उपयोग करता है , इकाई से खोज को बनाए रखते हुए, कार्य को पूरी तरह से जिम्मेदार सेवा में उतार देता है।Invoice

SetStatus()अब एक लकड़हारे पर एक साधारण निर्भरता है , जो स्पष्ट रूप से काम का हिस्सा होगा ।

बाद के लिए, क्लाइंट कोड पर चीजों को आसान बनाने के लिए, हम इसके बजाय एक लॉग इन कर सकते हैं IInvoiceService। सब के बाद, चालान लॉगिंग एक चालान के लिए बहुत आंतरिक लगता है। ऐसा एकल IInvoiceServiceविभिन्न कार्यों के लिए सभी प्रकार की मिनी-सेवाओं की आवश्यकता से बचने में मदद करता है। नकारात्मक पक्ष यह अस्पष्ट वास्तव में सेवा करेंगे क्या हो जाता है कि है ऐसा । यहां तक ​​कि यह दोहरे प्रेषण की तरह लग सकता है , जबकि अधिकांश कार्य वास्तव में अभी भी SetStatus()अपने आप में किए जाते हैं।

हम अपने इरादे को प्रकट करने की उम्मीद में अभी भी पैरामीटर 'लकड़हारा' का नाम दे सकते हैं। हालांकि थोड़ा कमजोर लगता है।

इसके बजाय, मैं IInvoiceLogger(जैसे हम पहले से ही कोड नमूने में करते हैं) के लिए पूछने का विकल्प चुनते हैं और IInvoiceServiceउस इंटरफ़ेस को लागू करते हैं। क्लाइंट कोड बस अपने एकल का उपयोग IInvoiceServiceउन सभी Invoiceतरीकों के लिए कर सकता है जो किसी भी ऐसे विशेष, चालान-आंतरिक 'मिनी-सेवा' के लिए पूछते हैं, जबकि विधि हस्ताक्षर अभी भी बहुतायत से स्पष्ट करते हैं कि वे क्या पूछ रहे हैं।

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

public class Invoice
{
    public IEnumerable<CreditNote> GetCreditNotes(ICreditNoteRepository repository)
    { ... }
}

वास्तव में, यह कभी-कभी परेशान आलसी भार का विकल्प प्रदान करता है

अद्यतन: मैंने ऐतिहासिक उद्देश्यों के लिए पाठ को नीचे छोड़ दिया है, लेकिन मेरा सुझाव है कि आलसी लोड को 100% से साफ़ करें।

सही, संपत्ति-आधारित आलसी लोड के लिए, मैं वर्तमान में कंस्ट्रक्टर इंजेक्शन का उपयोग करता हूं , लेकिन दृढ़ता-अनभिज्ञ तरीके से।

public class Invoice
{
    // Lazy could use an interface (for contravariance if nothing else), but I digress
    public Lazy<IEnumerable<CreditNote>> CreditNotes { get; }

    // Give me something that will provide my credit notes
    public Invoice(Func<Invoice, IEnumerable<CreditNote>> lazyCreditNotes)
    {
        this.CreditNotes = new Lazy<IEnumerable<CreditNotes>>() => lazyCreditNotes(this));
    }
}

एक तरफ, Invoiceडेटाबेस से लोड होने वाले भंडार में एक फ़ंक्शन के लिए मुफ्त पहुंच हो सकती है जो संबंधित क्रेडिट नोटों को लोड करेगा, और उस फ़ंक्शन को इसमें इंजेक्ट करेगा Invoice

दूसरी ओर, कोड जो एक वास्तविक नया बनाता है, Invoiceकेवल एक फ़ंक्शन पारित करेगा जो एक खाली सूची देता है:

new Invoice(inv => new List<CreditNote>() as IEnumerable<CreditNote>)

(एक रिवाज ILazy<out T>हमें बदसूरत कलाकारों से छुटकारा दिला सकता है IEnumerable, लेकिन यह चर्चा को जटिल करेगा।)

// Or just an empty IEnumerable
new Invoice(inv => IEnumerable.Empty<CreditNote>())

मुझे आपकी राय, प्राथमिकताएं और सुधार सुनने में खुशी होगी!


3

मेरे लिए यह DDD के लिए विशिष्ट होने के बजाय सामान्य अच्छा OOD संबंधित अभ्यास प्रतीत होता है।

कारण जो मैं सोच सकता हूं:

  • चिंताओं का पृथक्करण (एंटिटीज़ को उनके बने रहने के तरीके से अलग किया जाना चाहिए। जैसा कि कई रणनीतियाँ हो सकती हैं जिसमें एक ही इकाई का उपयोग परिदृश्य के आधार पर किया जाएगा)
  • तार्किक रूप से, संस्थाओं को उस स्तर से नीचे के स्तर में देखा जा सकता है जिसमें रिपॉजिटरी काम करती हैं। निचले स्तर के घटकों को उच्च स्तर के घटकों पर ज्ञान नहीं होना चाहिए। इसलिए प्रविष्टियों को रिपॉजिटरी पर ज्ञान नहीं होना चाहिए।

2

बस वर्नोन वॉन एक समाधान देता है:

कुल व्यवहार को लागू करने के लिए निर्भर वस्तुओं को देखने के लिए एक रिपॉजिटरी या डोमेन सेवा का उपयोग करें। क्लाइंट एप्लिकेशन सेवा इसे नियंत्रित कर सकती है।


लेकिन एक एंटिटी से नहीं।
18

वेरनॉन वॉन आईडीडीडी स्रोत से: सार्वजनिक वर्ग कैलेंडर ईवेंटसॉरड्रेडरूटइंटेनिटी {... सार्वजनिक कैलेंडर ईवेंट्री शेड्यूल कैलेन्डरइंटर्री (CalendarIdentityService aCalendarIdentityService,
Teimuraz

अपने कागज की जाँच करें @Teimuraz
रहमानी खलीली

1

मैंने ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग को कोड करने के लिए सीखा, इससे पहले कि यह अलग-अलग लेयर बज़ दिखाई दे, और मेरी पहली ऑब्जेक्ट्स / क्लास डीआईडी ​​मैप को सीधे डेटाबेस में भेज दिया।

आखिरकार, मैंने एक मध्यवर्ती परत को जोड़ा क्योंकि मुझे दूसरे डेटाबेस सर्वर पर माइग्रेट करना था। मैंने एक ही परिदृश्य के बारे में कई बार देखा / सुना है।

मुझे लगता है कि आपके व्यावसायिक तर्क से डेटा एक्सेस (उर्फ "रिपॉजिटरी") को अलग करना, उन चीजों में से एक है, जिन्हें कई बार पुनर्निवेशित किया गया है, डोमेन ड्रिवेन डिज़ाइन की किताब को देखा, इसे "शोर" का एक बहुत बना दिया।

मैं वर्तमान में 3 परतों (GUI, लॉजिक, डेटा एक्सेस) का उपयोग करता हूं, जैसे कई डेवलपर करता है, क्योंकि इसकी एक अच्छी तकनीक है।

एक Repositoryपरत (उर्फ Data Accessपरत) में डेटा को अलग करना, एक अच्छा प्रोग्रामिंग तकनीक की तरह देखा जा सकता है, न कि केवल एक नियम का पालन करने के लिए।

कई कार्यप्रणालियों की तरह, आप इन्हें लागू करने के बाद, शुरू न करके, और अंत में, अपने प्रोग्राम को अपडेट करना शुरू कर सकते हैं।

उद्धरण: इलियड का पूरी तरह से होमर द्वारा आविष्कार नहीं किया गया था, कारमिना बुराना का पूरी तरह से कार्ल ऑर्फ द्वारा आविष्कार नहीं किया गया था, और दोनों मामलों में, जो व्यक्ति दूसरों को काम करता है, सभी togheter, को क्रेडिट मिला ;-)


1
धन्यवाद, लेकिन मैं व्यापार तर्क से डेटा एक्सेस को अलग करने के बारे में नहीं पूछ रहा हूं - एक बहुत स्पष्ट बात है कि इस पर बहुत व्यापक सहमति है। मैं इस बारे में पूछ रहा हूं कि डीडीडी आर्किटेक्चर्स जैसे S # arp में, Entities को डेटा एक्सेस लेयर के लिए 'टॉक' भी करने की अनुमति नहीं है। इसकी एक दिलचस्प व्यवस्था है जिसके बारे में मैं बहुत चर्चा कर पाया।
कोड्यूलिक

0

क्या यह एरिक इवांस डोमेन ड्रिवेन डिज़ाइन बुक से आया है, या यह कहीं और से आया है?

यह पुराना सामान है। एरिक की किताब ने इसे थोड़ा और गुलजार कर दिया।

इसके पीछे के तर्क के लिए कुछ अच्छे स्पष्टीकरण कहां हैं?

कारण सरल है - मानव मन कमजोर हो जाता है जब यह अस्पष्ट रूप से संबंधित कई संदर्भों का सामना करता है। वे अस्पष्टता की ओर ले जाते हैं (दक्षिण / उत्तर अमेरिका में अमेरिका का अर्थ दक्षिण / उत्तरी अमेरिका है), अस्पष्टता सूचना के निरंतर मानचित्रण की ओर जाता है जब भी "मन इसे छूता है" और यह खराब उत्पादकता और त्रुटियों के रूप में प्रकट होता है।

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

सादृश्य में: यदि आप सीख रहे हैं कि कैसे हस्तलिखित करना है, तो आपको यह समझने में बोझ नहीं होना चाहिए कि पेन कहाँ बनाया गया था, स्याही कागज पर क्यों है, जब कागज का आविष्कार किया गया था और अन्य प्रसिद्ध चीनी आविष्कार क्या हैं।

संपादित करें: स्पष्ट करने के लिए: मैं डेटा लॉजिक को व्यापार तर्क से अलग परत में अलग करने की क्लासिक OO प्रथा के बारे में बात नहीं कर रहा हूं - मैं उस विशिष्ट व्यवस्था के बारे में बात कर रहा हूं जिसके तहत DDD में, Entities को डेटा से बात नहीं करनी चाहिए सभी तक पहुंच की परत (यानी वे रिपॉजिटरी ऑब्जेक्ट्स के संदर्भ को रखने के लिए नहीं हैं)

कारण अभी भी वही है जिसका मैंने ऊपर उल्लेख किया है। यहाँ यह सिर्फ एक कदम आगे है। यदि वे पूरी तरह से कम से कम (करीब से) हो सकते हैं तो संस्थाओं को आंशिक रूप से अज्ञानता क्यों होनी चाहिए? कम डोमेन-असंबंधित चिंताएं जो हमारे मॉडल रखती हैं - अधिक साँस लेने का कमरा हमारे दिमाग को तब मिलता है जब इसे फिर से व्याख्या करना पड़ता है।


सही। तो, कैसे पूरी तरह से अज्ञानतापूर्ण एंटिटी बिजनेस लॉजिक को लागू करता है अगर इसकी दृढ़ता की परत पर बात करने की अनुमति नहीं है? जब यह अन्य संस्थाओं को मनमाने ढंग से मूल्यों को देखने की जरूरत है तो यह क्या करता है?
कोडुलिके जूल

यदि आपकी इकाई को मनमाने ढंग से अन्य संस्थाओं में मूल्यों को देखने की जरूरत है, तो आपके पास संभवतः कुछ डिज़ाइन मुद्दे हैं। शायद कक्षाओं को तोड़ने पर विचार करें ताकि वे अधिक सामंजस्यपूर्ण हों।
cdaq

0

कैरोलिना लिलिएनहल को उद्धृत करने के लिए, "पैटर्न को चक्रों को रोकना चाहिए" https://www.youtube.com/watch?v=eJjadzMRQAk , जहां वह कक्षाओं के बीच चक्रीय निर्भरता को संदर्भित करता है। समुच्चय के अंदर भंडार के मामले में, केवल कारण के रूप में ऑब्जेक्ट नेविगेशन के संयोजकता से बाहर चक्रीय निर्भरता बनाने का प्रलोभन है। प्रोगैहमर द्वारा उल्लिखित पैटर्न, जिसे वर्नोन वॉन द्वारा अनुशंसित किया गया था, जहां अन्य समुच्चय को रूट इंस्टेंस के बजाय आईडी द्वारा संदर्भित किया जाता है, (क्या इस पैटर्न का कोई नाम है?) एक विकल्प बताता है जो अन्य समाधानों में मार्गदर्शन कर सकता है।

वर्गों (स्वीकारोक्ति) के बीच चक्रीय निर्भरता का उदाहरण:

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

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

ऊपर दिए गए आलसी लोडिंग के नकारात्मक पहलुओं के बारे में ऊपर वर्णित इस लेख से मुझे भी मदद मिली ।


-1

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


नहीं, यह संस्थाओं को अनावश्यक युग्मन का परिचय देता है, एसआरपी और पृथक्करण की चिंताओं का उल्लंघन करता है, और दृढ़ता से इकाई को डिसेररलाइज़ करना मुश्किल बनाता है (क्योंकि डीसेरिएलाइज़ेशन प्रक्रिया को अब सेवाओं / रिपॉजिटरी को भी इकाई आवृत्तियों को इंजेक्ट करना होगा)।
18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.