मैं गरीब-आदमी का पालन करता रहा हूं काफी समय से CQRS 1 को अपना रहा हूं क्योंकि मुझे इसकी लचीलेपन से प्यार है एक डेटा स्टोर में दानेदार डेटा रखना, विश्लेषण के लिए बहुत संभावनाएं प्रदान करना और इस प्रकार व्यापार मूल्य में वृद्धि करना और जब पठन के लिए किसी अन्य की आवश्यकता होती है, जिसमें प्रदर्शन के लिए असामान्य डेटा होता है। ।
लेकिन दुर्भाग्य से शुरू से ही मैं इस समस्या से जूझ रहा था, जहाँ मुझे इस प्रकार की वास्तुकला में व्यावसायिक तर्क रखने चाहिए।
जो मैं समझता हूं, एक कमांड इरादे को संप्रेषित करने का एक साधन है और एक डोमेन से इसका संबंध नहीं है। वे मूल रूप से डेटा हैं (गूंगा - यदि आप चाहें) वस्तुओं को स्थानांतरित करें। यह विभिन्न प्रौद्योगिकियों के बीच आसानी से हस्तांतरणीय आदेश बनाने के लिए है। समान रूप से सफलतापूर्वक पूर्ण की गई घटनाओं की प्रतिक्रियाओं के रूप में घटनाओं पर लागू होता है।
डीडीडी के एक विशिष्ट अनुप्रयोग में व्यापारिक तर्क संस्थाओं, मूल्य वस्तुओं, समग्र जड़ों के भीतर रहता है, वे डेटा के साथ-साथ व्यवहार में भी समृद्ध हैं। लेकिन एक कमांड एक डोमेन ऑब्जेक्ट नहीं है इस प्रकार यह डेटा के डोमेन प्रतिनिधित्व तक सीमित नहीं होना चाहिए, क्योंकि यह उन पर बहुत अधिक दबाव डालता है।
तो असली सवाल यह है: वास्तव में तर्क कहाँ है?
मुझे पता चला है कि मैं इस संघर्ष का सामना सबसे अधिक बार करता हूं जब एक काफी जटिल समुच्चय का निर्माण करने की कोशिश की जाती है जो इसके मूल्यों के संयोजन के बारे में कुछ नियम निर्धारित करता है। इसके अलावा, जब डोमेन डोमेन ऑब्जेक्ट्स को मैं फेल-फास्ट प्रतिमान का पालन करना पसंद करता हूं , तो यह जानते हुए कि जब कोई वस्तु एक विधि तक पहुंचती है तो यह एक वैध स्थिति में है।
मान लीजिए कि एक समुच्चय Car
दो घटकों का उपयोग करता है:
Transmission
,Engine
।
दोनों Transmission
और Engine
मूल्य वस्तुओं सुपर प्रकार के रूप में प्रतिनिधित्व कर रहे हैं और अनुसार उप प्रकार है, Automatic
और Manual
प्रसारण, या Petrol
औरElectric
क्रमशः इंजन के अनुसार होता है।
इस डोमेन में, अपने आप ही सफलतापूर्वक बनाया गया Transmission
, यह हो Automatic
या Manual
, या तो एक प्रकार का Engine
है, पूरी तरह से ठीक है। लेकिन Car
समुच्चय कुछ नए नियमों को लागू करता है, केवल तब लागू होता है जब वस्तुओं Transmission
और Engine
समान संदर्भ में उपयोग किया जाता है। अर्थात्:
- जब एक कार
Electric
इंजन का उपयोग करती है तो केवल अनुमत ट्रांसमिशन प्रकार होता हैAutomatic
। - जब कोई कार
Petrol
इंजन का उपयोग करती है तो उसका प्रकार भी हो सकता हैTransmission
।
मैं कमांड बनाने के स्तर पर इस घटक संयोजन उल्लंघन को पकड़ सकता हूं, लेकिन जैसा कि मैंने पहले कहा है, जो मैं समझता हूं कि ऐसा नहीं किया जाना चाहिए क्योंकि कमांड में फिर व्यावसायिक तर्क शामिल होंगे जो कि डोमेन परत तक सीमित होना चाहिए।
विकल्पों में से एक यह है कि इस व्यापार तर्क सत्यापन को वैधता कमांड करने के लिए स्थानांतरित किया जाए, लेकिन यह सही भी नहीं लगता है। ऐसा लगता है कि मैं कमांड को डिकॉन्स्ट्रक्ट कर रहा हूं, गेटर्स का उपयोग करके प्राप्त किए गए गुणों की जांच करना और सत्यापनकर्ता के भीतर उनकी तुलना करना और परिणामों का निरीक्षण करना। यह मेरे लिए Demeter कानून के उल्लंघन की तरह चिल्लाता है।
उल्लिखित सत्यापन विकल्प को छोड़ना क्योंकि यह व्यवहार्य नहीं लगता है, ऐसा लगता है जैसे किसी को कमांड का उपयोग करना चाहिए और इससे कुल का निर्माण करना चाहिए। लेकिन यह तर्क कहां मौजूद होना चाहिए? क्या यह एक ठोस कमांड को संभालने के लिए जिम्मेदार कमांड हैंडलर के भीतर होना चाहिए? या यह शायद कमांड वैलिडेटर के भीतर होना चाहिए (मुझे यह दृष्टिकोण पसंद नहीं है)?
मैं वर्तमान में एक कमांड का उपयोग कर रहा हूं और जिम्मेदार कमांड हैंडलर के भीतर इससे एक एग्रीगेट बना रहा हूं। लेकिन जब मैं ऐसा करता हूं, तो क्या मेरे पास एक कमांड वैलिडेटर होना चाहिए, इसमें कुछ भी शामिल नहीं होगा, क्योंकि CreateCar
कमांड मौजूद होना चाहिए और फिर इसमें ऐसे घटक शामिल होंगे जो मुझे पता है कि अलग-अलग मामलों में मान्य हैं, लेकिन कुल अलग-अलग कह सकते हैं।
आइए, अलग-अलग सत्यापन प्रक्रियाओं को मिलाकर एक अलग परिदृश्य की कल्पना करें - एक का उपयोग करके एक नया उपयोगकर्ता बनाएं CreateUser
कमांड बनाता है।
आदेश एक में शामिल है Id
एक उपयोगकर्ता बना लिया होगा, जो किया गया है और उनके की Email
।
सिस्टम उपयोगकर्ता के ईमेल पते के लिए निम्नलिखित नियम बताता है:
- अनोखा होना चाहिए,
- खाली नहीं होना चाहिए,
- अधिकतम 100 वर्ण (db कॉलम की अधिकतम लंबाई) होनी चाहिए।
इस मामले में, भले ही एक अनूठा ईमेल एक व्यावसायिक नियम है, लेकिन इसे समग्र रूप से जांचना बहुत कम समझ में आता है, क्योंकि मुझे सिस्टम में वर्तमान ईमेल के पूरे सेट को एक मेमोरी में लोड करना होगा और कमांड में ईमेल की जांच करनी होगी। कुल के खिलाफ ( Eekek! कुछ, कुछ, प्रदर्शन।)। उसके कारण, मैं इस चेक को कमांड वैलिडेटर के पास ले जाऊंगा, जो UserRepository
एक निर्भरता के रूप में लेगा और यह जांचने के लिए रिपॉजिटरी का उपयोग करेगा कि कमांड में मौजूद ईमेल वाला उपयोगकर्ता पहले से मौजूद है या नहीं।
जब यह इस पर आता है तो यह अचानक कमांड वैलिडेटर में अन्य दो ईमेल नियमों को डालने के लिए समझ में आता है। लेकिन मुझे लगता है कि नियमों को वास्तव में एक User
समुच्चय के भीतर मौजूद होना चाहिए और यह कि कमांड सत्यापनकर्ता को केवल विशिष्टता के बारे में जांच करनी चाहिए और यदि सत्यापन सफल होता है तो मुझे User
एकत्रीकरण बनाने CreateUserCommandHandler
और इसे बचाने के लिए एक रिपॉजिटरी को पास करने के लिए आगे बढ़ना चाहिए ।
मुझे ऐसा लगता है क्योंकि रिपॉजिटरी की सेव विधि एक एग्रीगेट को स्वीकार करने की संभावना है जो यह सुनिश्चित करता है कि एक बार एग्रीगेट पास हो जाने के बाद सभी इन्वर्टर पूरे हो जाएं। जब तर्क (जैसे गैर-शून्यता) केवल कमांड सत्यापन के भीतर मौजूद होता है, तो कोई अन्य प्रोग्रामर इस सत्यापन को पूरी तरह से छोड़ सकता है और UserRepository
किसी User
ऑब्जेक्ट के साथ सेव विधि को सीधे कॉल कर सकता है, जिससे घातक डेटाबेस त्रुटि हो सकती है, क्योंकि ईमेल में हो सकता है बहुत लंबा हो गया।
आप इन जटिल मान्यताओं और परिवर्तनों को व्यक्तिगत रूप से कैसे संभालते हैं? मैं ज्यादातर अपने समाधान से खुश हूं, लेकिन मुझे ऐसा लगता है कि मुझे इस बात की पुष्टि की जरूरत है कि मेरे विचार और दृष्टिकोण पूरी तरह से बेवकूफ नहीं हैं कि विकल्पों के साथ बहुत खुश हों। मैं पूरी तरह से अलग दृष्टिकोण के लिए पूरी तरह से खुला हूं। यदि आपके पास कुछ है जो आपने व्यक्तिगत रूप से कोशिश की है और आपके लिए बहुत अच्छी तरह से काम किया है तो मैं आपके समाधान को देखना पसंद करूंगा।
1 एक PHP डेवलपर के रूप में कार्य करना Restful सिस्टम बनाने के लिए जिम्मेदार CQRS की मेरी व्याख्या मानक async-command-processing दृष्टिकोण से थोड़ा विचलित करती है , जैसे कि कभी-कभी आदेशों की आवश्यकता के कारण आदेशों को सिंक्रोनाइज़ करने के कारण परिणाम वापस करना।
CommandDispatcher
।