मैं अब लगभग 8 वर्षों से डोमेन-संचालित डिज़ाइन को अपना रहा हूं और इन सभी वर्षों के बाद भी, अभी भी एक चीज है, जो मुझे परेशान कर रही है। यह एक डोमेन ऑब्जेक्ट के खिलाफ डेटा स्टोरेज में एक अद्वितीय रिकॉर्ड के लिए जाँच कर रहा है।
सितंबर 2013 में मार्टिन फाउलर ने टेलडॉट एएएस सिद्धांत का उल्लेख किया , जो कि यदि संभव हो तो, सभी डोमेन वस्तुओं पर लागू किया जाना चाहिए, जो तब एक संदेश वापस करना चाहिए, ऑपरेशन कैसे हुआ (ऑब्जेक्ट-ओरिएंटेड डिज़ाइन में यह ज्यादातर अपवादों के माध्यम से किया जाता है, जब ऑपरेशन असफल रहा)।
मेरी परियोजनाओं को आम तौर पर कई हिस्सों में विभाजित किया जाता है, जहां उनमें से दो डोमेन होते हैं (व्यावसायिक नियम और कुछ नहीं, डोमेन पूरी तरह से अज्ञान-अज्ञानी है) और सेवाएं। CRUD डेटा के लिए उपयोग की जाने वाली रिपॉजिटरी लेयर के बारे में जानने वाली सेवाएँ।
चूँकि किसी ऑब्जेक्ट से संबंधित विशेषता की विशिष्टता एक डोमेन / व्यावसायिक नियम है, यह डोमेन मॉड्यूल के लिए लंबा होना चाहिए, इसलिए यह नियम ठीक वही है जहां इसे माना जाता है।
किसी रिकॉर्ड की विशिष्टता की जांच करने में सक्षम होने के लिए, आपको वर्तमान डेटासेट, आमतौर पर एक डेटाबेस, यह पता लगाने की आवश्यकता है कि क्या कोई दूसरा रिकॉर्ड Name
पहले से मौजूद है।
डोमेन परत को ध्यान में रखते हुए अज्ञानता है और यह पता नहीं है कि डेटा को कैसे पुनर्प्राप्त करना है, लेकिन केवल उन पर संचालन कैसे करना है, यह वास्तव में स्वयं रिपॉजिटरी को नहीं छू सकता है।
फिर जिस डिजाइन को मैं अपना रहा हूं वह इस तरह दिखता है:
class ProductRepository
{
// throws Repository.RecordNotFoundException
public Product GetBySKU(string sku);
}
class ProductCrudService
{
private ProductRepository pr;
public ProductCrudService(ProductRepository repository)
{
pr = repository;
}
public void SaveProduct(Domain.Product product)
{
try {
pr.GetBySKU(product.SKU);
throw Service.ProductWithSKUAlreadyExistsException("msg");
} catch (Repository.RecordNotFoundException e) {
// suppress/log exception
}
pr.MarkFresh(product);
pr.ProcessChanges();
}
}
इससे डोमेन लेयर के बजाए डोमेन नियमों को परिभाषित करने वाली सेवाएँ हो जाती हैं और आपके कोड के कई सेक्शनों में नियम बिखर जाते हैं।
मैंने टेलडॉट एएएस सिद्धांत का उल्लेख किया है, क्योंकि जैसा कि आप स्पष्ट रूप से देख सकते हैं, सेवा एक कार्रवाई प्रदान करती है (यह या तो Product
अपवाद को बचाता है या एक अपवाद फेंकता है), लेकिन विधि के अंदर आप प्रक्रियात्मक दृष्टिकोण का उपयोग करके ऑब्जेक्ट पर काम कर रहे हैं।
स्पष्ट समाधान यह है कि फेंकने की विधि के Domain.ProductCollection
साथ एक वर्ग बनाया जाए , लेकिन इसमें प्रदर्शन की बहुत कमी है, क्योंकि आपको कोड में पता लगाने के लिए डेटा संग्रहण से सभी उत्पाद प्राप्त करने की आवश्यकता होगी, चाहे एक उत्पाद पहले से ही SKU हो उत्पाद के रूप में आप जोड़ने की कोशिश कर रहे हैं।Add(Domain.Product)
ProductWithSKUAlreadyExistsException
आप लोग इस विशिष्ट मुद्दे को कैसे हल करते हैं? यह वास्तव में प्रति से एक समस्या नहीं है, मैंने वर्षों तक सेवा परत को कुछ डोमेन नियमों का प्रतिनिधित्व किया है। सेवा परत आमतौर पर अधिक जटिल डोमेन संचालन भी करती है, मैं बस सोच रहा हूं कि क्या आप अपने करियर के दौरान बेहतर, अधिक केंद्रीकृत, समाधान पर ठोकर खा चुके हैं।