ओओपी समुदाय में व्यापक सहमति प्रतीत होती है कि वर्ग निर्माणकर्ता को आंशिक रूप से या पूरी तरह से असंगठित वस्तु नहीं छोड़नी चाहिए।
"इनिशियलाइज़ेशन" से मेरा क्या मतलब है? मोटे तौर पर, परमाणु प्रक्रिया जो एक नव निर्मित वस्तु को एक ऐसी स्थिति में लाती है जहां उसके सभी वर्ग आक्रमणकारी रहते हैं। यह पहली चीज होनी चाहिए जो किसी ऑब्जेक्ट के साथ होती है, (इसे केवल एक बार ऑब्जेक्ट के अनुसार चलना चाहिए) और किसी भी चीज को अन-इनिशियलाइज्ड ऑब्जेक्ट को होल्ड करने की अनुमति नहीं दी जानी चाहिए। (इस प्रकार क्लास कंस्ट्रक्टर में ऑब्जेक्ट इनिशियलाइज़ेशन राईट करने की बार-बार सलाह दी जाती है। उसी कारण से,
Initialize
तरीकों को अक्सर फेल किया जाता है, क्योंकि ये एटमॉसिटी को तोड़ते हैं और इसे पकड़ना और उपयोग करना संभव बनाते हैं, एक ऐसी वस्तु जो अभी तक नहीं है। एक अच्छी तरह से परिभाषित राज्य में।)
समस्या: जब CQRS को इवेंट सोर्सिंग (CQRS + ES) के साथ जोड़ दिया जाता है, जहां किसी ऑब्जेक्ट के सभी राज्य परिवर्तन ईवेंट (इवेंट स्ट्रीम) की एक क्रमबद्ध श्रृंखला में पकड़े जाते हैं, तो मुझे आश्चर्य होता है कि जब कोई ऑब्जेक्ट वास्तव में पूरी तरह से प्रारंभिक अवस्था में पहुंचता है: वर्ग निर्माता के अंत में, या वस्तु के लिए पहली घटना के बाद लागू किया गया है?
नोट: मैं "कुल रूट" शब्द का उपयोग करने से बच रहा हूं। यदि आप पसंद करते हैं, तो जब भी आप "ऑब्जेक्ट" पढ़ते हैं, तब उसे प्रतिस्थापित करें।
उदाहरण के लिए चर्चा करें: मान लें कि प्रत्येक वस्तु को विशिष्ट रूप से कुछ अपारदर्शी Id
मान (GUID) द्वारा पहचाना जाता है । एक घटना धारा जो उस वस्तु के राज्य परिवर्तनों को एक ही Id
मान से इवेंट स्टोर में पहचाना जा सकता है : (चलो सही घटना क्रम के बारे में चिंता न करें।)
interface IEventStore
{
IEnumerable<IEvent> GetEventsOfObject(Id objectId);
}
आगे मान लें कि दो वस्तु प्रकार हैं Customer
और ShoppingCart
। आइए ध्यान केंद्रित करें ShoppingCart
: जब बनाया जाता है, तो खरीदारी की गाड़ियां खाली होती हैं और उन्हें ठीक एक ग्राहक के साथ जोड़ा जाना चाहिए। वह अंतिम बिट एक वर्ग अयोग्य है : एक ShoppingCart
वस्तु जो Customer
अमान्य स्थिति में एक से जुड़ी नहीं है।
पारंपरिक OOP में, कोई इसे निर्माता में मॉडल कर सकता है:
partial class ShoppingCart
{
public Id Id { get; private set; }
public Customer Customer { get; private set; }
public ShoppingCart(Id id, Customer customer)
{
this.Id = id;
this.Customer = customer;
}
}
हालांकि, मैं एक नुकसान में हूं कि इसे सीक्यूआरएस + ईएस में कैसे स्थगित किया जाए बिना आस्थगित आरंभीकरण के साथ। चूंकि इनिशियलाइज़ेशन का यह सरल सा तरीका प्रभावी रूप से एक राज्य परिवर्तन है, क्या इसे एक घटना के रूप में तैयार नहीं करना होगा ?:
partial class CreatedEmptyShoppingCart
{
public ShoppingCartId { get; private set; }
public CustomerId { get; private set; }
}
// Note: `ShoppingCartId` is not actually required, since that Id must be
// known in advance in order to fetch the event stream from the event store.
यह स्पष्ट रूप से किसी भी ShoppingCart
वस्तु के घटना प्रवाह में पहली घटना होगी, और उस वस्तु को केवल एक बार शुरू किया जाएगा जब घटना उस पर लागू होती है।
इसलिए यदि इनिशियलाइज़ेशन इवेंट स्ट्रीम "प्लेबैक" का हिस्सा बन जाता है (जो कि एक बहुत ही सामान्य प्रक्रिया है जो संभवतः एक ही काम करेगी, चाहे वह किसी Customer
वस्तु या ShoppingCart
वस्तु के लिए हो या उस मामले के लिए कोई अन्य ऑब्जेक्ट प्रकार) ...
- क्या कंस्ट्रक्टर को पैरामीटर-कम होना चाहिए और कुछ भी नहीं करना चाहिए, सभी काम को किसी
void Apply(CreatedEmptyShoppingCart)
विधि पर छोड़ देना चाहिए (जो कि फ्रॉन्ड-ऑन के समान ही हैInitialize()
)? - या निर्माणकर्ता को एक घटना स्ट्रीम प्राप्त करना चाहिए और इसे वापस खेलना चाहिए (जो पुन: आरंभीकरण परमाणु बनाता है, लेकिन इसका मतलब है कि प्रत्येक वर्ग के कंस्ट्रक्टर में एक ही जेनेरिक "प्ले बैक और अप्लाई" लॉजिक यानी अवांछित कोड दोहराव शामिल है)?
- या दोनों पारंपरिक ओओपी निर्माता (जैसा कि ऊपर दिखाया गया है) होना चाहिए जो ऑब्जेक्ट को ठीक से इनिशियलाइज़ करता है, और फिर सभी ईवेंट्स लेकिन पहले से
void Apply(…)
संबंधित हैं ?
मुझे पूरी तरह से काम करने वाले डेमो कार्यान्वयन प्रदान करने के लिए जवाब की उम्मीद नहीं है; मैं पहले से ही बहुत खुश अगर कोई जहाँ मेरे तर्क त्रुटिपूर्ण किया गया है या वस्तु प्रारंभ वास्तव में समझा सकता है हो जाएगा है एक "दर्द बिंदु" सबसे CQRS + ES कार्यान्वयन में।
Initialize
विधि) ने कब्जा कर लिया होगा। यह मुझे इस सवाल की ओर ले जाता है कि आपका ऐसा कारखाना कैसा दिख सकता है?