क्या डोमेन / दृढ़ता मॉडल अलगाव आमतौर पर यह अजीब है?


13

मैं डोमेन-चालित डिजाइन (डीडीडी) की अवधारणाओं में गोता लगा रहा हूं और कुछ सिद्धांतों को अजीब पाया गया, विशेष रूप से डोमेन और दृढ़ता मॉडल के अलगाव के बारे में। यहाँ मेरी बुनियादी समझ है:

  1. एप्लिकेशन लेयर पर एक सेवा (एक सुविधा सेट प्रदान करते हुए) डोमेन ऑब्जेक्ट को अपने कार्य को पूरा करने के लिए आवश्यक भंडार से अनुरोध करती है।
  2. इस भंडार का ठोस कार्यान्वयन उस भंडारण से डेटा प्राप्त करता है जिसे इसके लिए लागू किया गया था
  3. सेवा डोमेन ऑब्जेक्ट को बताती है, जो व्यावसायिक तर्क को एन्क्रिप्ट करती है, कुछ कार्यों को करने के लिए जो इसके राज्य को संशोधित करता है।
  4. सेवा संशोधित डोमेन ऑब्जेक्ट को जारी रखने के लिए रिपॉजिटरी को बताती है।
  5. भंडार में संबंधित प्रतिनिधित्व के लिए रिपॉजिटरी को डोमेन ऑब्जेक्ट को मैप करने की आवश्यकता है।

प्रवाह चित्रण

अब, उपरोक्त मान्यताओं को देखते हुए, निम्नलिखित अजीब लगता है:

विज्ञापन 2:

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

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

विज्ञापन 3:

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

विज्ञापन 5:

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

आपके पास मैपिंग करने के लिए आपके पास ओआरएम टूल्स का उपयोग करने का विकल्प है। इन्हें अक्सर ORM के प्रतिबंधों के अनुसार डोमेन मॉडल तैयार करने की आवश्यकता होती है, हालाँकि, या डोमेन से बुनियादी ढांचे की परत पर निर्भरता का परिचय देते हैं (उदाहरण के लिए, डोमेन ऑब्जेक्ट्स में ORM एनोटेशन का उपयोग करके)। यह भी मैंने पढ़ा है कि ORMs एक काफी कम्प्यूटेशनल ओवरहेड का परिचय देते हैं।

NoSQL डेटाबेस के मामले में, जिसके लिए शायद ही कोई ORM जैसी अवधारणाएं मौजूद हैं, आप डोमेन मॉडल में किस गुणों को परिवर्तित करते हैं save()?

संपादित करें : इसके अलावा, डोमेन ऑब्जेक्ट की स्थिति (यानी प्रत्येक फ़ील्ड का मूल्य) तक पहुंचने के लिए एक रिपॉजिटरी के लिए, डोमेन ऑब्जेक्ट को अपनी आंतरिक स्थिति को प्रकट करने की आवश्यकता होती है जो एनकैप्सुलेशन को तोड़ती है।

सामान्य रूप में:

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

मैं इस विषय पर कुछ स्पष्टीकरण की सराहना करूंगा। क्या मेरी धारणाएँ सही हैं? यदि नहीं, तो इन समस्याओं से निपटने का सही तरीका क्या है?


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

2
इससे भी अधिक निराशाजनक बात यह है कि आपके जैसे प्रश्न लगभग बहुत बार पूछे जाते हैं, लेकिन, मेरी जानकारी के लिए - एग्रीगेट और रिपॉजिटरी के कार्यान्वयन के शून्य उदाहरण हैं जो पुस्तक द्वारा हैं
दुसान

जवाबों:


5

आपकी बुनियादी समझ सही है और आपके द्वारा स्केच की गई वास्तुकला अच्छी है और अच्छी तरह से काम करती है।

लाइनों के बीच पढ़ना ऐसा लगता है जैसे आप प्रोग्रामिंग के अधिक डेटाबेस-केंद्रित सक्रिय रिकॉर्ड शैली से आ रहे हैं? एक कार्यान्‍वयन कार्यान्‍वयन के लिए मैं कहूंगा कि आपको इसकी आवश्‍यकता है

1: डोमेन ऑब्जेक्ट्स में संपूर्ण ऑब्जेक्ट ग्राफ शामिल नहीं है। उदाहरण के लिए मैं हो सकता है:

public class Customer
{
    public string AddressId {get;set;}
    public string Name {get;set;}
}

public class Address
{
    public string Id {get;set;}
    public string HouseNumber {get;set;
}

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

2: विशिष्टता की कमी आम तौर पर रिपॉजिटरी का दायरा होती है न कि डोमेन ऑब्जेक्ट की। डोमेन ऑब्जेक्ट में रिपॉजिटरी को इंजेक्ट न करें, यह सक्रिय रिकॉर्ड पर वापस जाता है, जब सेवा सहेजने का प्रयास करता है तो बस त्रुटि होती है।

व्यवसाय नियम यह नहीं है कि "समान SocialSecurityNumber के साथ उपयोगकर्ता के कोई दो उदाहरण एक ही समय में मौजूद न हों"

यह है कि वे एक ही भंडार पर मौजूद नहीं हो सकते।

3: व्यक्तिगत संपत्ति अद्यतन विधियों के बजाय रिपॉजिटरी लिखना कठिन नहीं है। वास्तव में, आप पाएंगे कि आपके पास बहुत अधिक समान कोड है। इसका सिर्फ यह कि आप इसे किस वर्ग में डालते हैं।

इन दिनों ORM आसान है और आपके कोड पर कोई अतिरिक्त बाधा नहीं है। कहा कि, व्यक्तिगत रूप से मैं बस SQL ​​क्रैंक हाथ करना पसंद करते हैं। यह मुश्किल नहीं है, आप ORM सुविधाओं के साथ किसी भी मुद्दे में कभी नहीं भाग सकते हैं और जहां आवश्यक हो, आप इसे अनुकूलित कर सकते हैं।

आपके द्वारा सहेजे जाने पर किन संपत्तियों को बदला गया, इस पर नज़र रखने की वास्तव में आवश्यकता नहीं है। अपने डोमेन ऑब्जेक्ट्स को छोटा रखें और पुराने संस्करण को बस अधिलेखित करें।

सामान्य सवाल

  1. लेन-देन का तर्क रिपॉजिटरी में जाता है। लेकिन अगर आपके पास इसमें से कुछ भी नहीं होना चाहिए। यदि आपके पास चाइल्ड टेबल है जिसमें आप एग्रीगेट की चाइल्ड ऑब्जेक्ट डाल रहे हैं, तो निश्चित रूप से आपको कुछ चाहिए, लेकिन वह पूरी तरह से SaveMyObject रिपॉजिटरी मेथड के भीतर इनकैप्सुलेट हो जाएगा।

  2. थोक अद्यतन। हां, आपको व्यक्तिगत रूप से प्रत्येक ऑब्जेक्ट को बदलना चाहिए फिर बल्क अपडेट करने के लिए बस अपनी रिपॉजिटरी में एक SaveMyObjects (सूची ऑब्जेक्ट) विधि जोड़ें।

    आप तर्क को समाहित करने के लिए डोमेन ऑब्जेक्ट या डोमेन सेवा चाहते हैं। डेटाबेस नहीं । इसका मतलब है कि आप केवल "ग्राहक सेट नाम = x जहां y" अपडेट नहीं कर सकते, क्योंकि आप सभी ग्राहक वस्तु को जानते हैं, या जब आप नाम बदलते हैं, तो CustomerUpdateService 20 अजीब अन्य चीजें करता है।


बहुत बढ़िया जवाब। आप बिल्कुल सही हैं, मैं कोडिंग की एक सक्रिय रिकॉर्ड शैली के लिए उपयोग किया जाता हूं, यही वजह है कि रिपॉजिटरी पैटर्न पहली नजर में अजीब लगता है। हालाँकि, OO सिद्धांतों के विपरीत ("के AddressIdबजाय " दुबला) डोमेन ऑब्जेक्ट नहीं है Address?
डबल एम

नहीं, आपके पास अभी भी एक पता वस्तु है, इसका ग्राहक नहीं है
इवान

विज्ञापन ऑब्जेक्ट मैपिंग के बिना परिवर्तन ट्रैकिंग सॉफ़्टवेयरइंजीनियरिंग.स्टैकएक्सचेंज.
डबल एम

2

संक्षिप्त उत्तर: आपकी समझ सही है और आपके पास जो प्रश्न हैं, वे वैध समस्याओं की ओर इशारा करते हैं जिनके लिए समाधान सीधे आगे नहीं हैं और न ही सार्वभौमिक रूप से स्वीकार किए जाते हैं।

बिंदु 2 .: (पूर्ण वस्तु रेखांकन लोड करना)

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

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

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

तो इसका समाधान केवल उपयोग के मामलों के लिए एक ORM का उपयोग नहीं करना है, जिसके लिए यह एक अच्छा फिट नहीं है। उपयोग-केस को "स्वाभाविक रूप से" लागू करें, क्योंकि यह कभी-कभी डेटा (डेटा-ऑब्जेक्ट्स) के अतिरिक्त "एब्स्ट्रैक्शन" की आवश्यकता नहीं होती है और न ही "टेबल" (रिपॉजिटरी) के ऊपर एब्सट्रैक्शन की।

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

बिंदु 3 .: (बाधाओं की जाँच)

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

बिंदु 5 .: (ORMs)

बेशक, यह एक आवश्यक शर्त है कि डोमेन कोड से ठोस भंडारण कार्यान्वयन को समाप्त करना। हालांकि, क्या यह वास्तव में इतनी अधिक लागत पर आता है?

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

सामान्य प्रश्न 1 .: (लेनदेन)

मुझे नहीं लगता कि एक भी समाधान नहीं है। यदि आपका डिज़ाइन ऑब्जेक्ट-ओरिएंटेड है, तो प्रत्येक उपयोग-केस के लिए एक "टॉप" विधि होगी। लेन-देन होना चाहिए।

कोई अन्य प्रतिबंध पूरी तरह से कृत्रिम है।

सामान्य प्रश्न 2 .: (थोक संचालन)

एक ORM के साथ, आप व्यक्तिगत वस्तुओं के माध्यम से जाने के लिए मजबूर अधिकांश ORM (मुझे पता है) के लिए हैं। यह पूरी तरह से अनावश्यक है और शायद आपका डिजाइन नहीं होगा यदि आपका हाथ ओआरएम द्वारा बंधा नहीं होगा।

SQL से "लॉजिक" को अलग करने की आवश्यकता ORMs से आती है। वे है क्योंकि वे इसे समर्थन नहीं कर सकता, ऐसा कहा जा सकता। यह स्वाभाविक रूप से "बुरा" नहीं है।

सारांश

मुझे लगता है कि मेरी बात यह है कि ORMs हमेशा एक परियोजना के लिए सबसे अच्छा उपकरण नहीं हैं, और भले ही यह एक परियोजना में सभी उपयोग के मामलों के लिए सबसे अच्छा होने की संभावना नहीं है।

इसी तरह, DDD का डेटाबॉजेक्ट-रिपॉजिटरी एब्स्ट्रेक्शन हमेशा सबसे अच्छा नहीं होता है। मैं यहां तक ​​कहना चाहूंगा, वे शायद ही इष्टतम डिजाइन हैं।

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


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

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

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

ठीक है, मुख्य उद्देश्य व्यवसाय तर्क से चिंताओं को दूर रखना है, ताकि साफ कोड हो जो समझने, विस्तार और परीक्षण करने में आसान हो। DB प्रौद्योगिकियों को स्वैप करने में सक्षम होना सिर्फ एक बोनस है। मैं देख सकता हूं कि दक्षता और अज्ञानता के बीच स्पष्ट रूप से घर्षण है, जो आपके द्वारा उपयोग किए जा सकने वाले शक्तिशाली प्रश्नों के कारण ग्राफ DBs के साथ मजबूत प्रतीत होता है।
डबल एम

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