एकल जिम्मेदारी सिद्धांत के बारे में चिंता मत करो। यह यहाँ आपको एक अच्छा निर्णय लेने में मदद करने वाला नहीं है क्योंकि आप "जिम्मेदारी" के रूप में किसी विशेष अवधारणा को चुन सकते हैं। आप कह सकते हैं कि वर्ग की जिम्मेदारी डेटाबेस के लिए डेटा दृढ़ता का प्रबंधन कर रही है, या आप कह सकते हैं कि उपयोगकर्ता बनाने से संबंधित सभी कार्य करने के लिए इसकी जिम्मेदारी है। ये अनुप्रयोग के व्यवहार के केवल विभिन्न स्तर हैं, और वे दोनों "एकल जिम्मेदारी" के वैध वैचारिक अभिव्यक्ति हैं। तो यह सिद्धांत आपकी समस्या को हल करने के लिए अनपेक्षित है।
इस मामले में लागू करने के लिए सबसे उपयोगी सिद्धांत कम से कम आश्चर्य का सिद्धांत है । तो चलिए सवाल पूछते हैं: क्या यह आश्चर्यजनक है कि डेटाबेस को डेटा जारी रखने की प्राथमिक भूमिका वाला रिपॉजिटरी भी ई-मेल भेजता है?
हां, यह बहुत आश्चर्य की बात है। ये दो पूरी तरह से अलग बाहरी सिस्टम हैं, और नाम का SaveChanges
अर्थ सूचनाओं को भेजना भी नहीं है। तथ्य यह है कि आप इसे एक घटना के लिए सौंपते हैं व्यवहार को और भी आश्चर्यचकित करता है, क्योंकि कोड पढ़ने वाला कोई भी व्यक्ति अब आसानी से नहीं देख सकता है कि अतिरिक्त व्यवहार क्या हैं। अप्रत्यक्षता पठनीयता को नुकसान पहुँचाती है। कभी-कभी, लाभ पठनीय लागतों के लायक होते हैं, लेकिन तब नहीं जब आप स्वचालित रूप से एक अतिरिक्त बाहरी प्रणाली को लागू कर रहे हैं, जो उपयोगकर्ताओं को समाप्त करने के लिए अवलोकन योग्य है। (लॉगिंग को यहां बाहर रखा जा सकता है क्योंकि इसका प्रभाव अनिवार्य रूप से डिबगिंग उद्देश्यों के लिए रिकॉर्ड रखना है। अंतिम उपयोगकर्ता लॉग का उपभोग नहीं करते हैं, इसलिए हमेशा लॉगिंग में कोई नुकसान नहीं होता है।) इससे भी बदतर, यह समय में लचीलापन कम कर देता है। ई-मेल भेजने के लिए, इसे बचाने और अधिसूचना के बीच अन्य संचालन को बाधित करना असंभव है।
यदि आपका कोड आमतौर पर उपयोगकर्ता द्वारा सफलतापूर्वक बनाए जाने पर एक अधिसूचना भेजने की आवश्यकता है, तो आप एक ऐसा तरीका बना सकते हैं जो ऐसा करता है:
public void AddUserAndNotify(IUserRepository repo, IEmailNotification notifier, MyUser user)
{
repo.Add(user);
repo.SaveChanges();
notifier.SendUserCreatedNotification(user);
}
लेकिन क्या यह मूल्य जोड़ता है यह आपके आवेदन की बारीकियों पर निर्भर करता है।
मैं वास्तव में SaveChanges
विधि के अस्तित्व को हतोत्साहित करता हूँ । यह विधि संभवतः एक डेटाबेस लेन-देन करेगी, लेकिन अन्य रिपॉजिटरी ने उसी लेनदेन में डेटाबेस को संशोधित किया हो सकता है । तथ्य यह है कि यह उन सभी को फिर से आश्चर्यचकित करता है, क्योंकि SaveChanges
विशेष रूप से उपयोगकर्ता भंडार के इस उदाहरण से बंधा हुआ है।
एक डेटाबेस लेनदेन के प्रबंधन के लिए सबसे सीधा पैटर्न एक बाहरी using
ब्लॉक है:
using (DataContext context = new DataContext())
{
_userRepository.Add(context, user);
context.SaveChanges();
notifier.SendUserCreatedNotification(user);
}
यह प्रोग्रामर को स्पष्ट नियंत्रण देता है जब सभी रिपॉजिटरी के लिए परिवर्तन सहेजे जाते हैं, कोड को स्पष्ट रूप से उन घटनाओं के अनुक्रम को दस्तावेज़ित करने के लिए मजबूर करता है जो एक कमिट से पहले होने चाहिए, यह सुनिश्चित करता है कि एक रोलबैक त्रुटि पर जारी किया गया है (यह मानते हुए कि रोलबैक जारी करता है DataContext.Dispose
), और छिपा हुआ है राज्य वर्गों के बीच संबंध।
मैं भी अनुरोध में सीधे ई-मेल नहीं भेजना पसंद करूंगा। एक कतार में अधिसूचना की आवश्यकता को रिकॉर्ड करना अधिक मजबूत होगा । यह बेहतर विफलता से निपटने के लिए अनुमति देगा। विशेष रूप से, यदि कोई त्रुटि ई-मेल भेजने में होती है, तो इसे बाद में उपयोगकर्ता को बचाने में बाधा डाले बिना फिर से कोशिश की जा सकती है, और यह उस मामले से बचा जाता है जहां उपयोगकर्ता बनाया जाता है लेकिन साइट द्वारा एक त्रुटि वापस की जाती है।
using (DataContext context = new DataContext())
{
_userRepository.Add(context, user);
_emailNotificationQueue.AddUserCreateNotification(user);
_emailNotificationQueue.Commit();
context.SaveChanges();
}
अधिसूचना कतार को पहले करना बेहतर है क्योंकि कतार का उपभोक्ता यह सत्यापित कर सकता है कि ई-मेल भेजने से पहले उपयोगकर्ता मौजूद है, इस घटना में कि context.SaveChanges()
कॉल विफल हो जाती है। (अन्यथा, आपको हाइजेनबग्स से बचने के लिए एक पूर्ण विकसित दो चरण की रणनीति की आवश्यकता होगी।)
लब्बोलुआब यह है कि व्यावहारिक होना चाहिए। असल में कोड लिखने के परिणामों (जोखिम और लाभ दोनों) के माध्यम से सोचें। मुझे लगता है कि "एकल जिम्मेदारी सिद्धांत" बहुत बार मुझे ऐसा करने में मदद नहीं करता है, जबकि "कम से कम आश्चर्य का सिद्धांत" अक्सर मुझे एक और डेवलपर के सिर में प्रवेश करने में मदद करता है (इसलिए बोलने के लिए) और सोचें कि क्या हो सकता है।