यहां बताया गया है कि मैं आपकी समस्या का निर्माण कैसे करूंगा। मेरा मानना है कि यह करने का भी अनुशंसित डीडीडी तरीका है।
public class ProductService : IProductService // Application Service class, used by outside components like UI, WCF, HTTP Services, other Bounded Contexts, etc.
{
private readonly IProductRepository _prodRepository;
private readonly IStoreRepository _storeRepository;
public ProductService(IProductRepository prodRepository, IStoreRepository storeRepository) // Injected dependencies DI
{
if(prodRepository == null) throw new NullArgumentException("Prod Repo is required."); // guard
if(storeRepository == null) throw new NullArgumentException("Store Repo is required."); // guard
_prodRepository = prodRepository;
_storeRepository = storeRepository;
}
public void AddProductToStore(string name, Address address, StoreId storeId) //An exposed API method related to Product that is a part of your Application Service. Address and StoreId are value objects.
{
Store store = _storeRepository.GetBy(storeId);
IProductIdGenerator productIdGenerator = new ProductIdGenerator(_prodRepository);
Product product = Product.MakeNew(name, address, productIdGenerator);
}
... // Rest of API
}
public class Product : Entity
{
public static MakeNew(string name, Address address, IProductIdGenerator productIdGenerator) // Factory to make construction behaviour more explicit
{
return new Product(name, address, productIdGenerator);
}
protected Product(string name, Address address, IProductIdGenerator productIdGenerator)
: base(productIdGenerator.GetNextProductId())
{
Name = name;
Address = address;
}
... // Rest of Product methods, properties and fields
}
public class ProductIdGenerator : IProductIdGenerator
{
private IProductRepository _repository;
public ProductIdGenerator(IProductRepository repository)
{
_repository = repository;
}
public long GetNextProductId()
{
return _repository.GetNextProductId();
}
}
public interface IProductIdGenerator
{
long GetNextProductId();
}
असल में, ProductService, अपने अनुप्रयोग सेवा का हिस्सा है कि है, सब कुछ के प्रवेश और निकास बिंदु आपके डोमेन का उपयोग करें या इसकी सीमा पार करने के लिए जरूरत है। यह प्रत्येक उपयोग के मामलों को उचित घटकों के लिए जिम्मेदार बनाने के लिए ज़िम्मेदार है जो इससे निपट सकते हैं, और इन सभी घटकों के बीच समन्वय कर सकते हैं यदि उपयोग के मामले को पूरा करने के लिए कई आवश्यक हैं।
उत्पाद आपके समेकित रूट और आपके डोमेन में एक इकाई है। यह आपके उद्यम के डोमेन को कैप्चर करने वाले सर्वव्यापी भाषा के अनुबंध को निर्देशित करने के लिए ज़िम्मेदार है। इसलिए, अपने आप में, इसका मतलब है कि आपके डोमेन में एक उत्पाद की अवधारणा है, जिसमें डेटा और व्यवहार शामिल है, जो भी डेटा और व्यवहार आप सार्वजनिक रूप से बेनकाब करते हैं, वह सर्वव्यापी भाषा की अवधारणा होनी चाहिए। इस क्षेत्र में डोमेन मॉडल के बाहर बाह्य निर्भरता नहीं होनी चाहिए, इसलिए कोई सेवाएं नहीं। लेकिन, यह विधियां डोमेन सेवाओं को व्यवहार तर्क करने में सहायता के लिए पैरामीटर के रूप में ले सकती हैं।
ProductIdGenerator ऐसी डोमेन सेवा का एक उदाहरण है। डोमेन सेवाएं व्यवहार तर्क को समाहित करती हैं जो एक इकाई की अपनी सीमा के बाहर पार हो जाती है। तो यदि आपके पास तर्क है जिसके लिए अन्य कुल जड़ों, या रिपोजिटरी, फाइल सिस्टम, क्रिप्टोग्राफी इत्यादि जैसी बाहरी सेवाओं की आवश्यकता होती है। असल में, कोई भी तर्क जो आप अपनी इकाई के अंदर से कसरत नहीं कर सकते हैं, किसी और चीज की आवश्यकता के बिना, आपको एक डोमेन सेवा की आवश्यकता हो सकती है। यदि तर्क जटिलता की तरह है और अवधारणा की तरह लगता है तो वास्तव में आपकी संस्था पर एक विधि के रूप में नहीं हो सकता है, यह एक संकेत है कि आपको इसके लिए पूरी तरह से एक नया एप्लीकेशन सेवा उपयोग केस चाहिए, या आपने अपने डिज़ाइन में एक इकाई को याद किया है। एक गैर डबल प्रेषण तरीके से, सीधे सेवा सेवा से डोमेन सेवा का उपयोग करना भी संभव है। यह सामान्य स्थिर विधि बनाम सी # एक्सटेंशन विधियों के समान ही है।
=========== अपने संपादित सवालों के जवाब देने ===============
मैं भी शक है, तो सेवा बुलाया जाना चाहिए उत्पाद वर्ग से।
डोमेन सेवा को उत्पाद वर्ग से कहा जा सकता है यदि उन्हें विधि पैरामीटर के माध्यम से अस्थायी संदर्भ के रूप में पारित किया जाता है। उत्पाद सेवाओं को कभी भी उत्पाद वर्ग से नहीं बुलाया जाना चाहिए।
मैंने ऑब्जेक्ट के निर्माण के रूप में अभी तक एक कारखाना पैटर्न (अभी तक) का उपयोग नहीं किया है। मुझे लगता है कि यह अभी तक एक कारखाने विधि वारंट नहीं है?
यह निर्भर करता है कि आप क्या आप अधिक समय लगेगा उम्मीद करते हैं, अब एक कारखाने बनाने, भले ही आप एक से अधिक निर्माण तर्क की जरूरत नहीं है, या पुनर्रचना के बाद जब आप ऐसा करेंगे। मुझे लगता है कि यह उन संस्थाओं के लिए लायक नहीं है जिन्हें एक से अधिक तरीकों से निर्माण करने की आवश्यकता नहीं है।wikipedia बताते हैं कि कारखाने का उपयोग प्रत्येक कन्स्ट्रक्टर को अधिक स्पष्ट और अलग-अलग करने के लिए किया जाता है। मेरे उदाहरण में, मेकन्यू फैक्ट्री बताती है कि इस विशेष निर्माण का उद्देश्य उद्देश्य के रूप में कार्य करता है: एक नया उत्पाद बनाने के लिए। आपके पास मेकएक्सिस्टिंग, मेक नमूना, मेकडेप्रेटेड इत्यादि जैसे अधिक फैक्ट्री हो सकते हैं। इनमें से प्रत्येक कारखाना एक उत्पाद बनाएगा लेकिन विभिन्न उद्देश्यों के लिए और थोड़ा अलग तरीकों से। फैक्ट्री के बिना, इन सभी रचनाकारों को उत्पाद() नाम दिया जाएगा और यह जानना मुश्किल होगा कि कौन सा है और क्या करता है। नकारात्मकता यह है कि जब आप अपनी इकाई का विस्तार करते हैं तो कारखाने के साथ काम करना कठिन होता है, बच्चे की इकाई बच्चे को बनाने के लिए पैरेंट फैक्ट्री का उपयोग नहीं कर सकती है, यही कारण है कि मैं कन्स्ट्रक्टर के अंदर सभी निर्माण तर्क करता हूं, और केवल फैक्ट्री का उपयोग करता हूं उनके लिए एक सुंदर नाम है।
मैं उलझन में हूँ ... productId लाना एक तरफ अगर मेरे उत्पाद वर्ग एक सेवा जैसे GetSystemDateTime() (मुझे पता है, बुरा उदाहरण लेकिन एक गैर db कॉल प्रदर्शित करने के लिए कोशिश कर रहा है), जहां से कुछ अन्य डेटा की जरूरत क्या यह सेवा विधि कहलाएगी?
मान लें कि दिनांक कार्यान्वयन बुनियादी ढांचे का विवरण था। आप अपने आवेदन में उपयोग करने के लिए इसके चारों ओर एक अमूर्तता बनाएंगे। यह एक इंटरफ़ेस से शुरू होगा, शायद IDateTimeProvider जैसे कुछ। इस इंटरफेस में एक विधि GetSystemDateTime() होगी।
आपकी एप्लिकेशन सेवाएं किसी आईडीटाइमप्रोवाइडर को तत्काल करने के लिए स्वतंत्र होंगी और किसी भी समय इसकी विधियों को कॉल करने के लिए स्वतंत्र होगी, इससे परिणाम, संस्थाओं, डोमेन सेवाओं, या जो कुछ भी इसकी आवश्यकता होगी, के परिणाम को पारित कर सकता है।
आपकी डोमेन सेवा क्लास फ़ील्ड के रूप में IDateTimeProvider का संदर्भ रखने के लिए स्वतंत्र होगी, लेकिन इसे इंस्टेंस स्वयं नहीं बनाना चाहिए। या तो यह निर्भरता इंजेक्शन के माध्यम से प्राप्त करता है, या यह सेवा लोकेटर के माध्यम से इसके लिए पूछता है।
अंत में, आपकी प्रविष्टियां और कुल रूट्स और वैल्यू ऑब्जेक्ट्स GetSystemDateTime() और IDateTimeProvider के अन्य तरीकों को कॉल करने के लिए स्वतंत्र होंगे, लेकिन सीधे नहीं। इसे डबल प्रेषण के माध्यम से जाना होगा, जहां आप इसे किसी एक विधि के पैरामीटर के रूप में एक डोमेन सेवा देंगे, और यह उस डोमेन सेवा का उपयोग उस जानकारी की क्वेरी करने के लिए करेगा, जिसकी इच्छित जानकारी है, या जिस व्यवहार की आवश्यकता है उसे पूरा करें। यह स्वयं डोमेन सेवा पर वापस भी हो सकता है, जहां डोमेन सेवा क्वेरीिंग और सेटिंग करेगी।
यदि आप अपनी आईडीटीटाइमप्रोवाइडर को वास्तव में एक डोमेन सेवा मानते हैं, तो यूबिकिटस भाषा के हिस्से के रूप में, आपकी संस्थाओं और कुल रूट्स से सीधे इसे सीधे तरीके से कॉल कर सकते हैं, यह सिर्फ कक्षा के रूप में इसका संदर्भ नहीं रख सकता फ़ील्ड, लेकिन विधि पैरामीटर के स्थानीय चर ठीक हैं।
डीडीडी में सेवाएं तर्क डंप हैं जहां तर्क डोमेन ऑब्जेक्ट पर नाटकीय नहीं है, है ना? तो यह एक साथ गोंद कैसे करता है?
मुझे लगता है कि मेरा पूरा जवाब पहले से ही यह स्पष्ट हो गया है। असल में, आपके पास यह सब चमकाने के लिए 3 संभावनाएं हैं (जिन्हें मैं कम से कम अब तक सोच सकता हूं)।
1) एक एप्लिकेशन सेवा एक डोमेन सेवा को तुरंत चालू करती है, उस पर एक विधि कॉल करती है, और परिणामस्वरूप वापसी मूल्यों को किसी और चीज को पास करता है जिसकी आवश्यकता होती है (रेपो, इकाई, कुल रूट, मूल्य वस्तु, अन्य डोमेन सेवा, कारखानों आदि) ।)।
2) एक डोमेन सेवा को एप्लिकेशन डोमेन द्वारा तत्काल किया जाता है और इसका उपयोग करने वाले किसी विधि की पैरामीटर के रूप में पारित किया जाता है। जो कुछ भी इसका उपयोग करता है, वह स्थायी संदर्भ नहीं रखता है, यह केवल स्थानीय चर है।
3) एक डोमेन सेवा को एप्लिकेशन डोमेन द्वारा तत्काल किया जाता है और इसका उपयोग करने वाले किसी विधि की पैरामीटर के रूप में पारित किया जाता है। जो भी इसका उपयोग करता है, गैर-निर्भर तरीके से डोमेन सेवा का उपयोग करने के लिए डबल प्रेषण का उपयोग करता है। इसका अर्थ यह है कि यह डोमेन सेवा की विधि को डोमेन संदर्भ में ही संदर्भित करता है। कुछ ऐसा (यह, नाम, पता)।
उम्मीद है कि इससे मदद मिलती है। टिप्पणियों का स्वागत है अगर मैंने कुछ गलत किया या डीडीडी के सर्वोत्तम प्रथाओं के खिलाफ चला जाता है।
सेवाएं ऐसे कार्य करती हैं जो ऑब्जेक्ट स्वयं के लिए नहीं कर सकती हैं। एक भेद यह है कि सेवाएं डेटा स्टोर तक पहुंच सकती हैं। आपकी उत्पाद आईडी समस्या एक बहुत अच्छा उदाहरण है: यदि उत्पाद आईडी एक ग्रिड था, तो उत्पाद के लिए अपने कन्स्ट्रक्टर में उत्पाद आईडी जारी करना ठीक होगा। आपके मामले में, आपको किसी अन्य सिस्टम से ProductId प्राप्त करने की आवश्यकता है ताकि आपको एक सेवा प्रविष्टि करनी पड़े। –
हाँ मुझे पता है कि मुझे अपनी आईडी प्राप्त करने के लिए एक सेवा प्रविष्टि करने की आवश्यकता है, लेकिन मेरा सवाल यह है कि मैं सेवा कहां कहूं। मेरे डोमेन क्लास या बाहर के भीतर और इसे कन्स्ट्रक्टर में पास कर दें? –