कमांड में ही हैंडलिंग पद्धति के बजाय हैंडल () के साथ अलग क्लास कमांडहैंडलर क्यों


13

मेरे पास इस तरह से S # arp Architecture का उपयोग करके CQRS पैटर्न का एक भाग है :

public class MyCommand
{
    public CustomerId { get; set; }

    // some other fields
}

public class MyCommandHandler<MyCommand> : ICommandHandler<MyCommand, CommandResult>
{
    Handle(MyCommand command)
    {
        // some code for saving Customer entity

        return CommandResult.Success;
    }
}

मुझे आश्चर्य है कि क्यों न केवल Commandडेटा और हैंडलिंग पद्धति दोनों को युक्त वर्ग है ? क्या यह एक प्रकार का परीक्षण योग्य लाभ है, जहां आपको कमांड गुणों से अलग कमांड हैंडलिंग लॉजिक का परीक्षण करने की आवश्यकता है? या यह कुछ लगातार व्यावसायिक आवश्यकता है, जहां आपको एक आदेश को विभिन्न कार्यान्वयनों द्वारा नियंत्रित करने की आवश्यकता है ICommandHandler<MyCommand, CommandResult>?


मेरे पास एक ही सवाल था, जो देखने लायक है: blogs.cuttingedge.it/steven/posts/2011/…
rdhaundiyal

जवाबों:


14

मजेदार, यह प्रश्न मुझे ठीक उसी बातचीत की याद दिलाता है जो मैंने अपने एक इंजीनियर के साथ संचार पुस्तकालय के बारे में की थी जिस पर मैं काम कर रहा था।

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

लेकिन इस डिजाइन में, कमांड (या अनुरोध) को एक पत्र के रूप में सोचें। या उन लोगों के लिए जो एक डाक सेवा नहीं जानते हैं, ई-मेल के बारे में सोचें। यह केवल सामग्री है, उस सामग्री को किस तरह से काम किया जाना चाहिए, इससे अलग।

आप ऐसा क्यों करेंगे? अधिकांश सरल मामलों में, कमांड पैटर्न का कोई कारण नहीं है और आप इस वर्ग के काम को सीधे कर सकते हैं। हालाँकि, आपके डिज़ाइन में डिकॉप्लिंग करने से समझ में आता है कि क्या आपके एक्शन / कमांड / रिक्वेस्ट को कुछ दूरी तय करनी चाहिए। उदाहरण के लिए, पार, सॉकेट या पाइप, या डोमेन और बुनियादी ढांचे के बीच। या हो सकता है कि आपके आर्किटेक्चर में आपके कमांड्स लगातार बने रहें (जैसे कमांड हैंडलर एक बार में 1 कमांड कर सकता है, कुछ सिस्टम इवेंट्स के कारण, 200 कमांड्स आते हैं और पहले 40 प्रोसेस बंद हो जाते हैं)। उस स्थिति में, केवल एक सरल संदेश-युक्त वर्ग होने पर, केवल संदेश भाग को JSON / XML / बाइनरी / जो भी हो, उसे क्रमबद्ध करना बहुत आसान हो जाता है और जब तक इसका कमांड हैंडलर इसे संसाधित करने के लिए तैयार नहीं हो जाता है, तब तक इसे पाइप लाइन से गुजारें।

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

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


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

@ उत्साही: आप कैसे जानते हैं कि संदर्भ क्या है? जब तक S # arp Architecture कुछ खास नहीं है, मुझे लगता है कि सभी वर्ग घोषणाओं के एक जोड़े हैं और आपको पता नहीं है कि उनका उपयोग बाकी एप्लिकेशन में कैसे किया जाता है। यदि आप संख्याएँ पसंद नहीं करते हैं जिन्हें मैंने 50 की तरह चुना है, तो प्रति सेकंड 50 जैसा कुछ चुनें। यदि यह पर्याप्त नहीं है, तो प्रति सेकंड 1000 चुनें। मैं सिर्फ उदाहरण देने की कोशिश कर रहा था। या आपको नहीं लगता कि इस संदर्भ में उनके पास कई आदेश होंगे?
DXM

उदाहरण के लिए, सटीक संरचना यहाँ weblogs.asp.net/shijuvarghese/archive/2011/10/18/… देखी गई है । और कहीं भी यह नहीं कहता कि आपने क्या कहा। और गति के बारे में, समस्या आप प्रोफाइलिंग के बिना 'प्रदर्शन' तर्क का उपयोग करते हैं। यदि आपके पास इस तरह के थ्रूपुट के लिए आवश्यकताएं हैं, तो आप सामान्य वास्तुकला का उपयोग नहीं करने जा रहे हैं, बल्कि कुछ और विशिष्ट निर्माण कर सकते हैं।
जश्न

1
मुझे देखने दें कि क्या यह आपका अंतिम बिंदु था: ओपी ने उदाहरण के लिए पूछा, और मुझे कहना चाहिए, उदाहरण के लिए, पहले आप सरल तरीके से डिजाइन करते हैं और आपका आवेदन काम करता है, फिर आप बड़े पैमाने पर काम करते हैं और आप उन स्थानों का विस्तार करते हैं जहां आप कमांड पैटर्न का उपयोग करते हैं, फिर आप लाइव जाते हैं और आपको अपने सर्वर से बात करने वाली 10,000 मशीनें मिल जाती हैं और आपका सर्वर अभी भी आपके मूल आर्किटेक्चर का उपयोग करता है, फिर आप प्रोफ़ाइल की पहचान करते हैं और समस्या की पहचान करते हैं, और फिर आप कमांड डेटा को कमांड हैंडलिंग से अलग कर सकते हैं, लेकिन केवल आपके प्रोफ़ाइल के बाद। अगर मैं जवाब में वह सब शामिल करूं तो क्या यह वास्तव में आपको खुशी देगा? उन्होंने एक उदाहरण के लिए कहा, मैंने उसे एक दिया।
DXM

... इसलिए मैंने आपके द्वारा पोस्ट की गई ब्लॉग पोस्ट के माध्यम से सिर्फ नज़र रखी है और जो मैंने लिखा है, उसके साथ संरेखित करना प्रतीत होता है: यदि आपकी कमान को आपकी दूरी की यात्रा करनी है तो उन्हें अलग करें। ब्लॉग में वह एक कमांड बस का जिक्र करता दिख रहा है, जो मूल रूप से सिर्फ एक और पाइप, सॉकेट, संदेश कतार, esb ... आदि है
मई को DXM

2

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

दूसरी ओर, आप आदेशों की विरासत और संरचना दोनों का ढीला लाभ लेंगे। जो मुझे लगता है कि यह सच्ची शक्ति है।

इसके अलावा, मामूली निपिक। सिर्फ इसलिए कि इसमें नाम का कमांड है, यह CQRS का हिस्सा नहीं है। यह कुछ ज्यादा ही मौलिक है। इस तरह की संरचना दोनों कमांड के रूप में और एक ही समय में एक क्वेरी के रूप में भी सेवा कर सकती है।


मैंने लिंक weblogs.asp.net/shijuvarghese/archive/2011/10/18/… देखा है, जो आपने इंगित किया है, लेकिन मुझे S # arp Arch कोड में बस के कोई भी लक्षण दिखाई नहीं दे रहे हैं। इसलिए, मुझे लगता है, मेरे मामले में इस तरह का अलगाव केवल वर्ग और विभाजन तर्क फैलाता है।
19

1
@rgripper फिर आपने ठीक से नहीं खोजा। github.com/sharparchitecture/Sharp-Architecture/blob/... और github.com/sharparchitecture/Sharp-Architecture/blob/...
जश्न

हम्म, बाहर इशारा करने के लिए धन्यवाद। फिर मेरा मामला और भी बुरा है, क्योंकि मेरे पास कोड में ICommandProcessor IOC'ed है और CommandProcessor (जो खुद कमांड हैंडलर के लिए IOC बना रहा है) को हल किया गया है - एक मैला रचना। और इस परियोजना में एक कमांड के लिए एक से अधिक हिटलर के लिए कोई व्यावसायिक मामले नहीं हैं।
rgripper
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.