2011-09-05 13 views
17

में वास्तविक दुनिया तर्क डालने में परेशानी होने के बावजूद Domain Driven Design लंबे समय से अध्ययन करने के बावजूद अभी भी कुछ मूलभूत बातें हैं जिन्हें मैं आसानी से समझता हूं।डीडीडी डोमेन परत

ऐसा लगता है कि हर बार जब मैं एक अमीर domain layer डिजाइन करने की कोशिश, मैं अभी भी Domain Services या एक मोटी Application Layer का एक बहुत अलग की जरूरत है, और मैं उन्हें में कोई वास्तविक तर्क के साथ लगभग कमजोर डोमेन संस्थाओं के एक समूह के साथ खत्म हो, "GetTotalAmount" और जैसा से। मुख्य मुद्दा यह है कि संस्थाएं बाहरी सामानों से अवगत नहीं हैं, और संस्थाओं में कुछ भी इंजेक्ट करना बुरा व्यवहार है। ऊपर

1. किसी उपयोगकर्ता के प्रवेश के लिए एक सेवा के लिए:

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

पुष्टिकरण ईमेल के साथ उदाहरण पर अन्य धागे में भारी चर्चा की गई है, लेकिन कोई वास्तविक निष्कर्ष नहीं है। कुछ लोग तर्क को application service में डालने का सुझाव देते हैं जो EmailService और FileServiceinfrastructure layer से इंजेक्शन प्राप्त करता है। लेकिन फिर मेरे पास डोमेन के बाहर व्यापार तर्क होगा, है ना? लेकिन इस मामले में मैं अंदर domain layer (IEmailService और IFileService) infrastructure services के इंटरफेस है की आवश्यकता होगी जो भी अच्छा नहीं लगता है या तो (domain layer संदर्भ नहीं दे सकता क्योंकि infrastructure layer) - अन्य कि infrastructure services इंजेक्शन हो जाता है एक domain service बनाने का सुझाव । और अन्य Udi Dahan's Domain Events को लागू करने का सुझाव देते हैं और उसके बाद ईमेल सेवा और फ़ाइल सेवा उन घटनाओं की सदस्यता लेते हैं। लेकिन यह बहुत ढीला कार्यान्वयन की तरह लगता है - और यदि सेवा विफल हो जाती है तो क्या होता है? कृपया मुझे बताएं कि आपको क्या लगता है कि यह सही समाधान है।

2. एक डिजिटल संगीत स्टोर से एक गीत खरीदा जाता है। शॉपिंग कार्ट खाली हो गया है। खरीद जारी है। भुगतान सेवा कहा जाता है। एक ईमेल पुष्टि भेजी जाती है।

ठीक है, यह पहले उदाहरण से संबंधित हो सकता है। यहां सवाल यह है कि इस लेनदेन को व्यवस्थित करने के लिए कौन जिम्मेदार है? बेशक मैं इंजेक्शन सेवाओं के साथ एमवीसी नियंत्रक में सब कुछ डाल सकता है। लेकिन अगर मैं असली डीडीडी चाहता हूं तो सभी व्यावसायिक तर्क डोमेन में होना चाहिए। लेकिन किस इकाई में "खरीद" विधि होनी चाहिए? Song.Purchase()? Order.Purchase()? OrderProcessor.Purchase() (डोमेन सेवा)? ShoppingCartService.Purchase() (आवेदन सेवा?)

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

मुझे आशा है कि ये उदाहरण उन मुद्दों को दिखाने के लिए पर्याप्त स्पष्ट हैं जिनके साथ मैं काम कर रहा हूं।

+0

डीडीडी डोमेन के 'फ़ाइल' और 'ईमेल' इकाइयों का हिस्सा बनाने का सुझाव देता है।इंफ्रास्ट्रक्चर वास्तव में फ़ाइल बनाने और वास्तव में एक ईमेल भेजने के लिए ज़िम्मेदार है जब डोमेन परत में संबंधित इकाइयां दिखाई देती हैं। – Lightman

उत्तर

8

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

आप यहां Dependency Inversion Principle लागू कर सकते हैं। इस तरह एक डोमेन इंटरफेस को परिभाषित करें:

void ICanSendConfirmationEmail(EmailAddress address, ...) 

या

void ICanNotifyUserOfSuccessfulRegistration(EmailAddress address, ...) 

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

एक डिजिटल संगीत स्टोर से एक गीत खरीदा जाता है। शॉपिंग कार्ट खाली है। खरीद जारी है। भुगतान सेवा कहा जाता है। एक ईमेल पुष्टि भेजी गई है। ठीक है, यह पहले उदाहरण से संबंधित हो सकता है। यहां सवाल यह है कि इस लेनदेन को व्यवस्थित करने के लिए कौन जिम्मेदार है?

जिम्मेदारियों को निर्दिष्ट करने के लिए ओओपी सर्वोत्तम प्रथाओं का उपयोग करें (GRASP और SOLID)। यूनिट परीक्षण और रिफैक्टरिंग आपको डिज़ाइन फीडबैक देगा। ऑर्केस्ट्रेशन स्वयं पतला एप्लिकेशन लेयर का हिस्सा हो सकता है।

आवेदन परत: DDD Layered Architecture से परिभाषित करता है नौकरियों सॉफ्टवेयर करने के लिए माना जाता है और समस्याओं को बाहर काम करने के अर्थपूर्ण डोमेन वस्तुओं निर्देश देता है। यह परत व्यवसाय के लिए सार्थक है या अन्य सिस्टम की अनुप्रयोग परतों के साथ बातचीत के लिए ज़िम्मेदार है।

यह परत पतली रखी जाती है। इसमें व्यावसायिक नियम या ज्ञान शामिल नहीं है, लेकिन केवल निम्न परतों में डोमेन ऑब्जेक्ट्स के सहयोगों के लिए कार्यों और प्रतिनिधियों को समन्वयित करता है। यह में व्यवसाय की स्थिति को प्रतिबिंबित करने वाला राज्य नहीं है, लेकिन इसमें राज्य हो सकता है जो उपयोगकर्ता या कार्यक्रम के लिए किसी कार्य की प्रगति को दर्शाता है।

+0

धन्यवाद! डोमेन इंटरफेस के साथ बढ़िया विचार। और अधिक डीडीडी नमूने की जांच करने के बाद, मुझे आश्वस्त है कि मुझे एप्लिकेशन परत में * कुछ * व्यावसायिक तर्क डालने से डरना नहीं चाहिए - जैसे डोमेन ऑब्जेक्ट्स को कॉल करने का ऑर्डर प्रबंधित करना। – lasseschou

+0

हाय दिमित्री, मेरे पास एक प्रश्न है डोमेन इंटरफेस। क्या आप सीधे डोमेन इकाइयों पर डोमेन इंटरफेस के कार्यान्वयन को इंजेक्शन देने की सलाह देंगे? (क्या यह अच्छी प्रथा है?) - या आप एक इंजेक्शन कार्यान्वयन के साथ एक डोमेन सेवा 'उपयोगकर्ता सेवा' बनायेंगे, और फिर उस सेवा को एप्लिकेशन लेयर ('UserService.SendConfirmationEmail()') से कॉल करें? यह अभी भी मुझे स्पष्ट नहीं है कि इस समाधान को कैसे कार्यान्वित किया जाए। – lasseschou

0

आप अनुरोधों की बड़ी हिस्सा उन्मुख डिजाइन और जिम्मेदारी असाइनमेंट वस्तु से जुड़े हुए हैं, तो आप GRASP Patterns और This के बारे में सोच सकते हैं, आप वस्तु उन्मुख डिजाइन पुस्तकों से फायदा हो सकता है, तो निम्न की सिफारिश

Applying UML and Patterns

11

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

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

कुछ मार्गदर्शन जो मैं डोमेन विकसित करने की कोशिश करते समय अपने लिए उपयोग करता हूं (यह कहना चाहिए कि एक समृद्ध डोमेन बनाने में समय लगता है, अक्सर कई पुनरावर्तक पुनरावृत्तियों ...):

  • गुण (प्राप्त/सेट)
  • उपयोग मूल्य के रूप में ज्यादा आप
  • रूप में छोटे आप कर सकते हैं दिखा सकता है के रूप में वस्तुओं को कम करें। आपको डोमेन समेकित विधियों को अंतर्ज्ञानी बनाते हैं।

यह मत भूलना कि आपका डोमेन सत्यापन करके समृद्ध हो सकता है। यह केवल आपका डोमेन है जो जानता है कि खरीदारी कैसे करें, और क्या आवश्यक है।

आपका डोमेन सत्यापन के लिए ज़िम्मेदार भी होना चाहिए जब आपकी संस्थाएं एक राज्य से दूसरे राज्य (कार्य प्रवाह सत्यापन) में संक्रमण करती हैं।

मैं तुम्हें कुछ उदाहरण दे देंगे: एक लेख कमजोर डोमेन के बारे में अपनी समस्या के बारे में मैं अपने ब्लॉग पर लिखा है यहाँ है http://magnusbackeus.wordpress.com/2011/05/31/preventing-anemic-domain-model-where-is-my-model-behaviour/

मैं भी वास्तव में इकाई सत्यापन के बारे में सिफारिश कर सकते हैं जिमी Bogard के ब्लॉग लेख और एक साथ सत्यापनकर्ता पद्धति का उपयोग कर विस्तार विधियों के साथ। यह आपको अपने डोमेन को गंदे किए बिना आधारभूत चीजों को सत्यापित करने की आजादी देता है: http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/

मैं बड़ी सफलता के साथ उडी के डोमेन ईवेंट का उपयोग करता हूं। यदि आप मानते हैं कि आपकी सेवा विफल हो सकती है तो आप उन्हें अतुल्यकालिक भी बना सकते हैं। आप इसे एक लेनदेन में भी लपेटते हैं (NServiceBus ढांचे का उपयोग करके)।

आपके पहले उदाहरण में (केवल हमारे दिमाग मूल्य वस्तुओं के बारे में सोचने के लिए दिमागी तूफान)।

  1. आपकी MusicService.AddSubscriber(User newUser) एप्लिकेशन सेवा किसी नए उपयोगकर्ता के साथ प्रस्तुतकर्ता/नियंत्रक/डब्ल्यूसीएफ से कॉल प्राप्त करती है। सेवा पहले ही IUserRepository और IMusicServiceRepository सीटीआर में इंजेक्शन मिली है।
  2. संगीत सेवा "Spotify" IMusicServiceRepository के माध्यम से भरी हुई
  3. इकाई musicService.SignUp(MusicServiceSubscriber newSubsriber) विधि एक मूल्य वस्तु MusicServiceSubscriber लेता है। यह मान ऑब्जेक्ट उपयोगकर्ता और अन्य अनिवार्य वस्तुओं को ctor (मूल्य वस्तुएं अपरिवर्तनीय) में लेनी चाहिए। यहां आप तर्क/व्यवहार को सब्सक्रिप्शन आईडी के इत्यादि जैसे
  4. क्या साइनअप विधि भी करता है, यह एक डोमेन इवेंट NewSubscriberAddedToMusicService को सक्रिय करता है। यह EventHandler HandleNewSubscriberAddedToMusicServiceEvent द्वारा पकड़ा गया है जो IFileService और IEmailService को इसके सीटीआर में इंजेक्शन दिया गया। यह हैंडलर का कार्यान्वयन अनुप्रयोग सेवा परत में स्थित है लेकिन ईवेंट को डोमेन और MusicService.SignUp द्वारा नियंत्रित किया जाता है। इसका मतलब है कि डोमेन नियंत्रण में है। Eventhandler फ़ाइल बनाता है और ईमेल भेजता है।

आप उपयोगकर्ता को ईवेंटहैंडर के माध्यम से जारी रख सकते हैं या MusicService.AddSubscriber(...) विधि बना सकते हैं। दोनों IUserRepository के माध्यम से ऐसा करेंगे लेकिन यह स्वाद का मामला है और शायद यह वास्तविक डोमेन को कैसे प्रतिबिंबित करेगा।

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

+0

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

+0

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

+0

ठीक है, धन्यवाद मैग्नस। हिमा से denja! – lasseschou

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