दिलचस्प पोस्ट
जावास्क्रिप्ट – एक अन्य सरणी के आधार पर क्रमबद्ध सरणी कैसे int.TryParse वास्तव में काम करता है निन्जा के लिए दृश्य सी ++ कंपाइलर उपकरण का पता लगाने के लिए CMake द्वारा उपयोग किए गए पर्यावरण चर गैर-स्थिर क्षेत्र के लिए एक स्थिर संदर्भ नहीं बना सकता अपने एपीआई का उपयोग करके एक मूल मेलचिप साइनअप फ़ॉर्म बनाएं एक सूची में तत्व की प्रत्येक जोड़ी पर ऑपरेशन मेरे एंड्रॉइड ऐप में पाठ को कैसे प्रतिलिपि करें? लाइब्रेरी किस क्रम में जुड़ी हुई है, कभी-कभी जीसीसी में त्रुटियां क्यों होती हैं? आधार क्लास पॉइंटर से सी ++ एक्सेस व्युत्पन्न क्लास सदस्य JSON.stringify () प्रोटोटाइप.जेएस के साथ सरणी विचित्रता एमपीएफआई फाइलों (क्यूटी-फास्टस्टार्ट) में 'मोओव एटम' को स्थानांतरित करने के लिए ffmpeg में पोस्ट प्रोसेसिंग वीम में चयन के लिए खोजें सी # JSON.NET सम्मेलन जो रूबी प्रॉपर्टी नामकरण सम्मेलनों का पालन करता है? कोयोनर 2 ऐप में 'प्रवेश-नियंत्रण-अनुमति-उत्पत्ति' शीर्षलेख नहीं Gitlab निजी रिपॉज़िटरी से npm मॉड्यूल इंस्टॉल करें

क्या मुझे डोमेन परत से सत्यापन ढांचा का सार होना चाहिए?

मैं अपने सेवा संचालन को मान्य करने के लिए FluentValidation का उपयोग कर रहा हूँ मेरा कोड ऐसा दिखता है:

using FluentValidation; IUserService { void Add(User user); } UserService : IUserService { public void Add(User user) { new UserValidator().ValidateAndThrow(user); userRepository.Save(user); } } 

UserValidator FluentValidation.AbstractValidator लागू करता है

डीडीडी का कहना है कि डोमेन परत को प्रौद्योगिकी स्वतंत्र होना चाहिए।

मैं क्या कर रहा हूँ कस्टम अपवादों के बजाय एक सत्यापन ढांचा का उपयोग कर रहा है

यह डोमेन परत में सत्यापन ढांचे को लगाने का एक बुरा विचार है?

Solutions Collecting From Web of "क्या मुझे डोमेन परत से सत्यापन ढांचा का सार होना चाहिए?"

बस रिपॉजिटरी अमूर्त की तरह?

ठीक है, मैं आपके डिजाइन के साथ कुछ समस्याएं देखता हूं, भले ही आप IUserValidator इंटरफ़ेस को घोषित करके ढांचे से अपने डोमेन को ढाल दें।

सबसे पहले, ऐसा लगता है कि अगर वह रिपॉजिटरी और अन्य बुनियादी ढांचे की चिंताओं के लिए उसी अमूर्त रणनीति की ओर ले जाएगा, लेकिन मेरी राय में एक बड़ा अंतर है

repository.save(...) का उपयोग करते समय, आप वास्तव में डोमेन परिप्रेक्ष्य से सभी कार्यान्वयन पर ध्यान नहीं रखते, क्योंकि चीजों को जारी रखने के लिए डोमेन चिंता का विषय नहीं है।

हालांकि, अपरिवर्तनीय प्रवर्तन एक डोमेन चिंता का विषय है और आपको आधारभूत विवरण विवरण में खोने के लिए नहीं होना चाहिए (यह अब उपयोगकर्ता के रूप में देखा जा सकता है) यह देखने के लिए कि वे क्या शामिल हैं और यह मूल रूप से है कि आप क्या करेंगे, यदि आप उस पथ को नीचे करते हैं चूंकि नियम ढांचे के रूप में व्यक्त किए जाएंगे और डोमेन के बाहर रहेंगे।

यह बाहर क्यों रहेंगे?

 domain -> IUserRepository infrastructure -> HibernateUserRepository domain -> IUserValidator infrastructure -> FluentUserValidator 

हमेशा वैध संस्थाएं

शायद आपके डिजाइन के साथ एक और मौलिक मुद्दा है और आप उस प्रश्न का भी सवाल नहीं पूछेंगे, अगर आप उस स्कूल का पालन करते हैं: हमेशा-वैध संस्थाएं

उस दृष्टिकोण से, अपरिवर्तनीय प्रवर्तन डोमेन इकाई की जिम्मेदारी है और इसलिए भी वैध होने के बिना अस्तित्व में नहीं होना चाहिए। इसलिए, अपरिवर्तनीय नियमों को केवल अनुबंध के रूप में व्यक्त किया जाता है और इनका उल्लंघन होने पर अपवाद फेंक दिए जाते हैं।

इसके पीछे तर्क यह है कि बहुत सारी बग इस तथ्य से आती है कि वस्तुओं को किसी अवस्था में है, वे कभी नहीं होनी चाहिए। उदाहरण के लिए मैंने ग्रेग यंग से पढ़ा है:

मान SendUserCreationEmailService कि अब हमारे पास एक SendUserCreationEmailService जो एक UserProfile लेता है … हम उस सेवा में कैसे तर्कसंगत बना सकते हैं कि Name null नहीं है? क्या हम इसे फिर से जांचते हैं? या अधिक होने की संभावना … आप केवल जांच करने के लिए परेशान नहीं हैं और आपको आशा है कि किसी को इसे भेजने से पहले इसे सत्यापित करने के लिए परेशान किया जाए। बेशक टीडीडी का उपयोग हम पहले परीक्षणों में से एक है, जो कि मुझे लिखना चाहिए कि अगर मैं किसी null नाम से एक ग्राहक भेजूं, तो उसे एक त्रुटि उठानी चाहिए। लेकिन एक बार हम इन प्रकार के परीक्षणों को लिखना शुरू कर देते हैं और फिर से हमें एहसास होता है … "अगर हम नाम रिक्त होने की अनुमति कभी नहीं देते तो प्रतीक्षा करें हम इन सभी परीक्षणों को नहीं करेंगे" – ग्रेग यंग http://jeffreypalermo.com पर टिप्पणी करते हुए / ब्लॉग /-भ्रम ऑफ द हमेशा वैध-इकाई /

अब मुझे गलत मत समझो, जाहिर है आप सभी वैधता नियमों को इस तरह से लागू नहीं कर सकते, क्योंकि कुछ नियम कुछ व्यावसायिक कार्यों के लिए विशिष्ट हैं, जो उस दृष्टिकोण को रोकता है (उदाहरण के लिए किसी संस्था की मसौदा प्रतियां सुरक्षित करना), लेकिन इन नियमों को नहीं देखा जा सकता है उसी तरह अपरिवर्तनीय प्रवर्तन के रूप में, जो नियम हैं जो हर परिदृश्य में लागू होते हैं (जैसे ग्राहक का नाम होना चाहिए)।

अपने कोड में हमेशा-मान्य सिद्धांत लागू करना

अगर हम अब आपके कोड को देखते हैं और हमेशा-मान्य दृष्टिकोण को लागू करने की कोशिश करते हैं, तो हम स्पष्ट रूप से यह देखते हैं कि UserValidator ऑब्जेक्ट की जगह नहीं है।

 UserService : IUserService { public void Add(User user) { //We couldn't even make it that far with an invalid User new UserValidator().ValidateAndThrow(user); userRepository.Save(user); } } 

इसलिए, इस बिंदु पर डोमेन में FluentValidation के लिए कोई स्थान नहीं है यदि आप अभी भी आश्वस्त नहीं हैं, तो अपने आप से पूछें कि आप मूल्य वस्तुओं को कैसे एकीकृत करेंगे? क्या आपके पास यूजरनाम वैल्यू ऑब्जेक्ट को हर बार मान्यता प्राप्त करने के लिए Username वाइडिटेटर होगा? जाहिर है, यह किसी भी अर्थ नहीं करता है और मूल्य ऑब्जेक्ट्स का उपयोग गैर हमेशा-वैध दृष्टिकोण के साथ एकीकृत करने में काफी मुश्किल होगा।

अपवादों को फेंकने पर हम सभी त्रुटियों को वापस कैसे रिपोर्ट कर सकते हैं?

यह वास्तव में कुछ है जिसके साथ मैं संघर्ष कर रहा हूं और मैं कुछ समय के लिए खुद से पूछ रहा हूं (और मैं अभी भी पूरी तरह से सहमत नहीं हूं कि मैं क्या कहूँगा)।

असल में, मुझे समझने के लिए क्या आया है कि यह त्रुटियों को एकत्रित और वापस करने के लिए डोमेन का काम नहीं है, यह एक यूआई चिंता का विषय है। यदि अमान्य डेटा डोमेन के तरीके से बनाते हैं, तो यह केवल आप पर फेंकता है

इसलिए, FluentValidation जैसे ढांचे UI में अपने प्राकृतिक घर पाएंगे और डोमेन इकाइयों के बजाय दृश्य मॉडल को मान्य करेंगे।

मुझे पता है, यह स्वीकार करना कठिन लगता है कि दोहराव का कुछ स्तर होगा, लेकिन यह मुख्य रूप से है क्योंकि आप शायद मेरे जैसे एक पूर्ण-स्टैक डेवलपर हैं जो कि यूआई और डोमेन के साथ काम करता है, जब वास्तव में ये और देखा जा सकता है पूरी तरह से अलग परियोजनाओं के रूप में इसके अलावा, केवल दृश्य मॉडल और डोमेन मॉडल की तरह, मॉडल मान्यता और डोमेन मान्यता देखें समान हो सकता है, लेकिन एक अलग उद्देश्य प्रदान करता है।

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

डोमेन में आस्थगित मान्यता के साथ लेनदेन

मैं उन लोगों को फिर से नहीं समझाऊंगा, लेकिन डोमेन में आस्थगित मान्यताओं के साथ निपटने के लिए विभिन्न दृष्टिकोण हैं जैसे कि वर्ड कनिंघम में उनके चेक पैटर्न भाषा में निर्दिष्ट विशिष्टता पैटर्न और डिफर्ड वैलिडेशन दृष्टिकोण। यदि आपके पास वॉन वर्नोन की डोमेन-प्रेरित डिजाइन पुस्तक लागू है, तो आप पृष्ठ 208-215 से भी पढ़ सकते हैं

यह हमेशा ट्रेड-ऑफ का सवाल है

सत्यापन एक अत्यंत कठिन विषय है और इसका सबूत यह है कि आज के दिन लोग यह भी मानते हैं कि यह कैसे किया जाना चाहिए। बहुत सारे कारक हैं, लेकिन अंत में जो आप चाहते हैं वह एक ऐसा समाधान है जो व्यावहारिक, व्यावहारिक, और अभिव्यंजक है। आप हमेशा शुद्ध नहीं हो सकते हैं और इस तथ्य को स्वीकार कर लेना चाहिए कि कुछ नियम टूट जाएंगे (जैसे आपको अपने ओआरएम का उपयोग करने के लिए किसी संस्था में कुछ निश्चिंत दृढ़ता के विवरण को रिसाव करना पड़ सकता है)।

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

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

अगर मैं इसे सही ढंग से समझा, तो मुझे ऐसा करने में कोई समस्या नहीं दिखाई देगी, जब तक कि यह आपके बुनियादी ढांचे के रूप में समझा जा रहा है जैसे आपके रेपो निरंतरता को निरस्त करता है।

एक उदाहरण के रूप में, मैंने अपने प्रोजेक्ट्स के लिए एक IObjectValidator बनाया है जो ऑब्जेक्ट प्रकार के द्वारा वैलेटर्स को रिटर्न करता है, और इसके एक स्थिर कार्यान्वयन करता है, जिससे कि मुझे तकनीक के साथ युग्मित न हो।

 public interface IObjectValidator { void Validate<T>(T instance, params string[] ruleSet); Task ValidateAsync<T>(T instance, params string[] ruleSet); } 

और फिर मैंने इसे उसी तरह फ़्लुट मान्यकरण के साथ कार्यान्वित किया:

 public class FluentValidationObjectValidator : IObjectValidator { private readonly IDependencyResolver dependencyResolver; public FluentValidationObjectValidator(IDependencyResolver dependencyResolver) { this.dependencyResolver = dependencyResolver; } public void Validate<T>(T instance, params string[] ruleSet) { var validator = this.dependencyResolver .Resolve<IValidator<T>>(); var result = ruleSet.Length == 0 ? validator.Validate(instance) : validator.Validate(instance, ruleSet: ruleSet.Join()); if(!result.IsValid) throw new ValidationException(MapValidationFailures(result.Errors)); } public async Task ValidateAsync<T>(T instance, params string[] ruleSet) { var validator = this.dependencyResolver .Resolve<IValidator<T>>(); var result = ruleSet.Length == 0 ? await validator.ValidateAsync(instance) : await validator.ValidateAsync(instance, ruleSet: ruleSet.Join()); if(!result.IsValid) throw new ValidationException(MapValidationFailures(result.Errors)); } private static List<ValidationFailure> MapValidationFailures(IEnumerable<FluentValidationResults.ValidationFailure> failures) { return failures .Select(failure => new ValidationFailure( failure.PropertyName, failure.ErrorMessage, failure.AttemptedValue, failure.CustomState)) .ToList(); } } 

कृपया ध्यान दें कि मैंने अपने आईओसी कंटेनर को एक आधिकारिक रिज़ॉल्वर के साथ भी समेट लिया है ताकि मैं जो कुछ भी क्रियान्वयन कर सकता हूं उसका उपयोग कर सकूं। (फिलहाल Autofac का उपयोग कर)

तो यहां autofac के लिए कुछ बोनस कोड है;)

 public class FluentValidationModule : Module { protected override void Load(ContainerBuilder builder) { // registers type validators builder.RegisterGenerics(typeof(IValidator<>)); // registers the Object Validator and configures the Ambient Singleton container builder .Register(context => SystemValidator.SetFactory(() => new FluentValidationObjectValidator(context.Resolve<IDependencyResolver>()))) .As<IObjectValidator>() .InstancePerLifetimeScope() .AutoActivate(); } } 

यह कोड मेरे कुछ सहायक और एक्सटेंशन को याद कर सकता है, लेकिन मुझे विश्वास है कि यह आपको जाने के लिए पर्याप्त होगा

मुझे आशा है कि मैंने मदद की होगी 🙂

संपादित करें:

चूंकि कुछ साथी कॉडर्स "सर्विस लोकेटर विरोधी पैटर्न" का उपयोग नहीं करना पसंद करते हैं, इसलिए यह कैसे निकालना है और अभी भी खुश रहना बहुत आसान उदाहरण है 🙂

कोड एक शब्दकोश प्रॉपर्टी प्रदान करता है जिसे टाइप करके आपके सभी मान्यताओं से भरना चाहिए।

 public class SimpleFluentValidationObjectValidator : IObjectValidator { public SimpleFluentValidationObjectValidator() { this.Validators = new Dictionary<Type, IValidator>(); } public Dictionary<Type, IValidator> Validators { get; private set; } public void Validate<T>(T instance, params string[] ruleSet) { var validator = this.Validators[typeof(T)]; if(ruleSet.Length > 0) // no ruleset option for this example throw new NotImplementedException(); var result = validator.Validate(instance); if(!result.IsValid) throw new ValidationException(MapValidationFailures(result.Errors)); } public Task ValidateAsync<T>(T instance, params string[] ruleSet) { throw new NotImplementedException(); } private static List<ValidationFailure> MapValidationFailures(IEnumerable<FluentValidationResults.ValidationFailure> failures) { return failures .Select(failure => new ValidationFailure( failure.PropertyName, failure.ErrorMessage, failure.AttemptedValue, failure.CustomState)) .ToList(); } }