एकल जिम्मेदारी सिद्धांत की प्रयोज्यता


40

मैं हाल ही में एक मामूली तुच्छ वास्तु समस्या से आया था। मेरे पास मेरे कोड में एक साधारण भंडार था जिसे इस तरह बुलाया गया था (कोड # C में है):

var user = /* create user somehow */;
_userRepository.Add(user);
/* do some other stuff*/
_userRepository.SaveChanges();

SaveChanges एक साधारण आवरण था जो डेटाबेस में परिवर्तन करता है:

void SaveChanges()
{
    _dataContext.SaveChanges();
    _logger.Log("User DB updated: " + someImportantInfo);
}

फिर, कुछ समय बाद, मुझे नए तर्क को लागू करने की आवश्यकता हुई जो हर बार सिस्टम में एक उपयोगकर्ता द्वारा बनाई गई ईमेल सूचनाएं भेजेगा। चूंकि सिस्टम में _userRepository.Add()और इसके SaveChangesआसपास कई कॉल थे , इसलिए मैंने SaveChangesइस तरह से अपडेट करने का फैसला किया :

void SaveChanges()
{
    _dataContext.SaveChanges();
    _logger.Log("User DB updated: " + someImportantInfo);
    foreach (var newUser in dataContext.GetAddedUsers())
    {
       _eventService.RaiseEvent(new UserCreatedEvent(newUser ))
    }
}

इस तरह, बाहरी कोड UserCreatedEvent की सदस्यता ले सकता है और आवश्यक व्यावसायिक तर्क को संभाल सकता है जो सूचनाएं भेजेगा।

लेकिन यह मेरी ओर इशारा किया गया था कि मेरे संशोधन SaveChangesने सिंगल रिस्पॉन्सिबिलिटी सिद्धांत का उल्लंघन किया है, और यह SaveChangesकेवल किसी भी घटना को बचाने और आग नहीं करना चाहिए।

क्या यह एक वैध बिंदु है? यह मुझे लगता है कि यहां एक घटना को उठाना अनिवार्य रूप से लॉगिंग के समान ही है: फ़ंक्शन में कुछ साइड कार्यक्षमता जोड़ना। और एसआरपी आपको अपने कार्यों में लॉगिंग या फायरिंग घटनाओं का उपयोग करने से प्रतिबंधित नहीं करता है, यह सिर्फ यह कहता है कि इस तरह के तर्क को अन्य कक्षाओं में समझाया जाना चाहिए, और इन अन्य वर्गों को कॉल करने के लिए एक रिपॉजिटरी के लिए यह ठीक है।


22
आपका मुंहतोड़ जवाब है: "ठीक है, तो आप इसे कैसे लिखेंगे ताकि यह SRP का उल्लंघन न करे लेकिन फिर भी संशोधन के एक बिंदु की अनुमति देता है?"
रॉबर्ट हार्वे

43
मेरा अवलोकन यह है कि किसी घटना को बढ़ाने से अतिरिक्त जिम्मेदारी नहीं जुड़ती। वास्तव में, बिल्कुल विपरीत: यह कहीं और जिम्मेदारी को दर्शाता है।
रॉबर्ट हार्वे

मुझे लगता है कि आपका सहकर्मी सही है, लेकिन आपका सवाल वैध और उपयोगी है, इसलिए उलझा हुआ है!
एंड्रेस एफ।

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

जवाबों:


14

हां, एक रिपॉजिटरी के लिए एक वैध आवश्यकता हो सकती है जो कुछ घटनाओं पर कुछ घटनाओं को आग लगाती है जैसे - Addया SaveChangesऔर मैं इस पर (कुछ अन्य उत्तर की तरह) सवाल नहीं करने जा रहा हूं क्योंकि आपके उपयोगकर्ताओं को जोड़ने और ईमेल भेजने का आपका विशिष्ट उदाहरण एक लग सकता है थोड़ा संघर्ष किया। निम्नलिखित में, मान लें कि यह आवश्यकता आपके सिस्टम के संदर्भ में पूरी तरह से उचित है।

तो हां , ईवेंट मैकेनिक के साथ-साथ लॉगिंग को एन्कोडिंग करने के साथ-साथ एक विधि में बचत एसआरपी का उल्लंघन करती है । बहुत सारे मामलों के लिए, यह संभवतः एक स्वीकार्य उल्लंघन है, खासकर जब कोई भी कभी भी "परिवर्तन सहेजें" और "घटना को बढ़ाने" के रखरखाव की जिम्मेदारियों को अलग-अलग टीमों / अनुरक्षकों को वितरित नहीं करना चाहता है। लेकिन एक दिन मान लें कि कोई व्यक्ति वास्तव में ऐसा करना चाहता है, तो क्या इसे सरल तरीके से हल किया जा सकता है, शायद उन चिंताओं के कोड को अलग-अलग वर्ग के पुस्तकालयों में डालकर?

इसका समाधान यह है कि अपने मूल भंडार को डेटाबेस में परिवर्तन करने के लिए ज़िम्मेदार रहने दें, और कुछ नहीं, और प्रॉक्सी रिपॉजिटरी बनाएं जिसमें बिल्कुल वही सार्वजनिक इंटरफ़ेस है, जो मूल रिपॉज़िटरी का पुन: उपयोग करता है और विधियों में अतिरिक्त ईवेंट मैकेनिक्स जोड़ता है।

// In EventFiringUserRepo:
public void SaveChanges()
{
  _basicRepo.SaveChanges();
   FireEventsForNewlyAddedUsers();
}

private void FireEventsForNewlyAddedUsers()
{
  foreach (var newUser in _basicRepo.DataContext.GetAddedUsers())
  {
     _eventService.RaiseEvent(new UserCreatedEvent(newUser))
  }
}

आप @ पीटर के अत्यधिक मतदान वाले उत्तर की पंक्तियों के साथ NotifyingRepositoryया ObservableRepositoryयदि आप चाहें तो प्रॉक्सी वर्ग को कॉल कर सकते हैं (जो वास्तव में SRP उल्लंघन को हल करने का तरीका नहीं बताता है, केवल यह कहना कि उल्लंघन ठीक है)।

नए और पुराने रिपॉजिटरी वर्ग को एक सामान्य इंटरफ़ेस से प्राप्त करना चाहिए, जैसे कि क्लासिक प्रॉक्सी पैटर्न विवरण में दिखाया गया है

फिर, अपने मूल कोड में, _userRepositoryनए EventFiringUserRepoवर्ग के ऑब्जेक्ट द्वारा इनिशियलाइज़ करें । इस तरह, आप मूल रिपोजिटरी को इवेंट मैकेनिक्स से अलग रखते हैं। यदि आवश्यक हो, तो आप घटना फायरिंग रिपॉजिटरी और मूल रिपॉजिटरी साइड-बाय-साइड कर सकते हैं और कॉल करने वालों को यह तय करने दें कि क्या वे पूर्व या उत्तरार्द्ध का उपयोग करते हैं।

टिप्पणियों में उल्लिखित एक चिंता को स्वीकार करने के लिए: क्या वह समीपता के शीर्ष पर परदे के पीछे नहीं है, और इसी तरह से? दरअसल, इवेंट मैकेनिक्स को जोड़ने से घटनाओं की सदस्यता लेने के द्वारा "ईमेल भेजें" प्रकार की आगे की आवश्यकताओं को जोड़ने के लिए एक नींव तैयार हो जाती है, इसलिए एसआरपी को उन आवश्यकताओं के साथ चिपका दिया जाता है, बिना किसी अतिरिक्त प्रॉक्सी के। लेकिन यहां एक बार जो चीज डालनी है, वह घटना यांत्रिकी ही है।

यदि आपके सिस्टम के संदर्भ में इस तरह का अलगाव वास्तव में इसके लायक है तो आप और आपके समीक्षक को खुद ही निर्णय लेना होगा। मैं शायद मूल कोड से लॉगिंग को अलग नहीं करूंगा, न ही किसी अन्य प्रॉक्सी का उपयोग करके श्रोता घटना में लकड़हारा जोड़कर नहीं, हालांकि यह संभव होगा।


3
इस जवाब के अलावा। AOP की तरह समीपता के विकल्प हैं ।
लावि

1
मुझे लगता है कि आप इस बिंदु को याद करते हैं, यह नहीं कि एक घटना को उठाने से एसआरपी टूट जाता है जो केवल "नए" उपयोगकर्ताओं के लिए एक घटना को बढ़ाता है, यह जानने के लिए कि "न्यूली मी" के बजाय "नया" उपयोगकर्ता का गठन करने के लिए रेपो को जिम्मेदार होना चाहिए। "उपयोगकर्ता
इवान

@ ईवान: कृपया प्रश्न को फिर से पढ़ें। यह कोड में एक जगह के बारे में था जो कुछ कार्यों को करता है जिसे उस वस्तु की जवाबदेही के बाहर अन्य कार्यों के साथ युग्मित करने की आवश्यकता होती है। और कार्रवाई और घटना को एक ही स्थान पर रखकर एक समीक्षक द्वारा एसआरपी को तोड़ने के रूप में पूछताछ की गई। "नए उपयोगकर्ताओं को बचाने" का उदाहरण केवल प्रदर्शन के उद्देश्य के लिए है, यदि आपको पसंद है, तो उदाहरण से वंचित कॉल करें, लेकिन यह IMHO प्रश्न का बिंदु नहीं है।
डॉक ब्राउन

2
यह सबसे अच्छा / सही उत्तर IMO है। यह न केवल एसआरपी को बनाए रखता है, बल्कि यह ओपन / बंद सिद्धांत को भी बनाए रखता है। और उन सभी स्वचालित परीक्षणों के बारे में सोचें जो कक्षा के भीतर बदल जाते हैं। नई कार्यक्षमता जोड़े जाने पर मौजूदा परीक्षणों को संशोधित करना एक बड़ी गंध है।
कीथ पायने

1
यदि कोई लेन-देन प्रगति में है तो यह समाधान कैसे काम करता है? जब वह चल रहा होता है, SaveChanges()तो वास्तव में डेटाबेस रिकॉर्ड नहीं बनाता है, और यह अंत में लुढ़का हुआ हो सकता है। ऐसा लगता है कि आपको या तो ओवरराइड करना होगा AcceptAllChangesया TransactionCompleted इवेंट की सदस्यता लेनी होगी।
जॉन वू

29

एक सूचना भेजना कि लगातार डेटा स्टोर बदल गया है जब बचत करने के लिए एक समझदार चीज की तरह लगता है।

बेशक आप एक विशेष मामले के रूप में ऐड का इलाज नहीं कर रहे हैं - आपको संशोधित करने और हटाने के लिए घटनाओं को भी फायर करना होगा। यह "ऐड" केस का विशेष उपचार है जिसमें बदबू आती है, पाठक को यह समझाने के लिए मजबूर करता है कि यह क्यों बदबू आ रही है, और अंततः कोड के कुछ पाठकों को यह निष्कर्ष निकालने के लिए प्रेरित करता है कि इसे एसआरपी का उल्लंघन करना चाहिए।

"नोटिफ़ाइंग" रिपॉजिटरी जो कि बदलाव पर घटनाओं को बदल सकती है, बदल सकती है और आग लगा सकती है, एक पूरी तरह से सामान्य वस्तु है। आप किसी भी शालीनता से आकार की परियोजना में इसके कई रूपों को खोजने की उम्मीद कर सकते हैं।


लेकिन क्या एक "अधिसूचित" भंडार वास्तव में आपको क्या चाहिए? आपने C # का उल्लेख किया है: बहुत से लोग इस बात से सहमत होंगे कि बाद System.Collections.ObjectModel.ObservableCollection<>की बजाय System.Collections.Generic.List<>जब आप की जरूरत है तो इसका उपयोग करना सभी प्रकार के बुरे और गलत हैं, लेकिन कुछ तुरंत SRP को इंगित करेंगे।

अब आप जो कर रहे हैं, वह आपके UserList _userRepositoryसाथ स्वैप कर रहा है ObservableUserCollection _userRepository। यदि यह कार्रवाई का सबसे अच्छा कोर्स है या नहीं, तो आवेदन पर निर्भर करता है। लेकिन जब यह निर्विवाद रूप से _userRepositoryकाफी हल्का हो जाता है, मेरी विनम्र राय में यह एसआरपी का उल्लंघन नहीं करता है।


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

@DocBrown मैंने ज्ञात वर्गों ObservableCollection<>और List<>तुलना और संदर्भ के लिए आवेदन किया । मुझे आंतरिक कार्यान्वयन या बाहरी इंटरफ़ेस के लिए वास्तविक कक्षाओं का उपयोग करने की सिफारिश करने का मतलब नहीं था।
पीटर

ठीक है, लेकिन भले ही ओपी "संशोधित करें" और "हटाएं" की घटनाओं को जोड़ देगा (जो मुझे लगता है कि ओपी ने सवाल को संक्षिप्त रखने के लिए छोड़ दिया, सरलता के लिए), मुझे लगता है कि एक समीक्षक आसानी से निष्कर्ष पर आ सकता है एक SRP उल्लंघन यह शायद एक स्वीकार्य है, लेकिन यदि आवश्यक हो तो कोई भी हल नहीं किया जा सकता है।
डॉक्टर ब्राउन

16

हां, यह एकल जिम्मेदारी सिद्धांत और एक मान्य बिंदु का उल्लंघन है।

बेहतर डिजाइन यह होगा कि एक अलग प्रक्रिया रिपॉजिटरी से 'नए उपयोगकर्ताओं' को पुनः प्राप्त करें और ईमेल भेजें। जिनको देखते हुए उपयोगकर्ताओं को एक ईमेल भेजा गया है, विफलताओं, resend, आदि, आदि।

इस तरह से आप त्रुटियों, दुर्घटनाओं और इस तरह के साथ-साथ अपनी रिपॉजिटरी को हर आवश्यकता को हथियाने से बच सकते हैं, जिसमें यह विचार है कि घटनाएं "तब होती हैं जब डेटाबेस के लिए कुछ किया जाता है"।

रिपॉजिटरी को पता नहीं है कि आपके द्वारा जोड़ा गया उपयोगकर्ता एक नया उपयोगकर्ता है। इसकी जिम्मेदारी केवल उपयोगकर्ता को संचय करना है।

यह शायद नीचे टिप्पणी पर विस्तार करने लायक है।

रिपॉजिटरी को पता नहीं है कि आपके द्वारा जोड़ा गया उपयोगकर्ता एक नया उपयोगकर्ता है - हां यह करता है, इसमें ऐड नामक एक विधि है। इसके शब्दार्थ का अर्थ है कि सभी जोड़े गए उपयोगकर्ता नए उपयोगकर्ता हैं। सहेजें कॉल करने से पहले ऐड में दिए गए सभी तर्कों को मिलाएं - और आपको सभी नए उपयोगकर्ता मिलते हैं

गलत। आप "रिपोजिटरी में जोड़ा" और "नया" का संगम कर रहे हैं।

"रिपोजिटरी में जोड़ा गया" का अर्थ है कि यह क्या कहता है। मैं उपयोगकर्ताओं को विभिन्न रिपॉजिटरी में जोड़ और हटा और पुनः जोड़ सकता हूं।

"नया" व्यावसायिक नियमों द्वारा परिभाषित उपयोगकर्ता की एक अवस्था है।

वर्तमान में व्यवसाय नियम "नया == सिर्फ रिपॉजिटरी में जोड़ा जा सकता है", लेकिन इसका मतलब यह नहीं है कि उस नियम के बारे में जानना और लागू करना एक अलग जिम्मेदारी नहीं है।

इस तरह की डेटाबेस-केंद्रित सोच से बचने के लिए आपको सावधान रहना होगा। आपके पास किनारे मामले की प्रक्रियाएं होंगी जो गैर-नए उपयोगकर्ताओं को भंडार में जोड़ती हैं और जब आप उन्हें ईमेल भेजते हैं तो सभी व्यवसाय कहेंगे "बेशक वे 'नए' उपयोगकर्ता नहीं हैं! वास्तविक नियम एक्स है"

यह उत्तर IMHO बिंदु काफी गायब है: रेपो कोड में ठीक एक केंद्रीय स्थान है जो जानता है कि नए उपयोगकर्ता कब जोड़े जाते हैं

गलत। उपरोक्त कारणों के लिए, इसके अलावा यह एक केंद्रीय स्थान नहीं है जब तक कि आप वास्तव में केवल एक घटना को बढ़ाने के बजाय कक्षा में ईमेल भेजने वाले कोड को शामिल नहीं करते हैं।

आपके पास ऐसे एप्लिकेशन होंगे जो रिपॉजिटरी क्लास का उपयोग करते हैं, लेकिन ईमेल भेजने के लिए कोड नहीं है। जब आप उन एप्लिकेशन में उपयोगकर्ताओं को जोड़ते हैं तो ईमेल नहीं भेजा जाएगा।


11
रिपॉजिटरी को पता नहीं है कि आपके द्वारा जोड़ा गया उपयोगकर्ता एक नया उपयोगकर्ता है - हां यह करता है, इसमें एक विधि है Add। इसके शब्दार्थ का अर्थ है कि सभी जोड़े गए उपयोगकर्ता नए उपयोगकर्ता हैं। Addकॉल करने से पहले दिए गए सभी तर्कों को मिलाएं Save- और आपको सभी नए उपयोगकर्ता मिलते हैं।
आंद्रे बोर्जेस

मुझे यह सुझाव पसंद आया। हालाँकि, पवित्रता पर व्यावहारिकता हावी है। परिस्थितियों के आधार पर, किसी मौजूदा एप्लिकेशन में एक पूरी तरह से नई वास्तुशिल्प परत को जोड़ना उचित ठहराना मुश्किल हो सकता है अगर आपको केवल एक उपयोगकर्ता को जोड़ने पर एक ईमेल भेजना है।
अलेक्जेंडर

लेकिन इवेंट उपयोगकर्ता को जोड़ा नहीं कह रहा है। यह कहते हैं कि उपयोगकर्ता बनाया। यदि हम चीजों को सही तरीके से नाम देने पर विचार करते हैं और हम ऐड और क्रिएट के बीच के अंतर के साथ सहमत हैं, तो स्निपेट में घटना या तो गलत है या नाम गलत है। मुझे नहीं लगता कि समीक्षक के पास रिपॉजिटरी के लिए कुछ भी नहीं है। संभवतः यह घटना के प्रकार और इसके दुष्प्रभावों के बारे में चिंतित था।
लावि

7
@ रेपो में नया, लेकिन व्यवसायिक अर्थों में "नया" जरूरी नहीं है। यह इन दो विचारों का संगम है जो पहली नज़र से अतिरिक्त जिम्मेदारी को छिपा रहा है। मैं अपने नए रिपॉजिटरी में पुराने उपयोगकर्ताओं का एक टन आयात कर सकता हूं, या किसी उपयोगकर्ता को हटा सकता हूं या फिर से जोड़ सकता हूं आदि "एक नया उपयोगकर्ता" से परे क्या है के बारे में व्यावसायिक नियम होंगे "डीबी में जोड़ा गया है"
इवान

1
मॉडरेटर नोट: आपका जवाब एक पत्रकार साक्षात्कार नहीं है। यदि आपके पास संपादन हैं, तो उन्हें पूरे "ब्रेकिंग न्यूज" प्रभाव पैदा किए बिना स्वाभाविक रूप से अपने उत्तर में शामिल करें। हम एक चर्चा मंच नहीं हैं।
रॉबर्ट हार्वे

7

क्या यह एक वैध बिंदु है?

हां यह है, हालांकि यह आपके कोड की संरचना पर बहुत कुछ निर्भर करता है। मेरे पास पूरा संदर्भ नहीं है इसलिए मैं सामान्य रूप से बात करने की कोशिश करूंगा।

यह मुझे लगता है कि यहां एक घटना को उठाना अनिवार्य रूप से लॉगिंग के समान ही है: फ़ंक्शन में कुछ साइड कार्यक्षमता जोड़ना।

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

और एसआरपी आपको अपने कार्यों में लॉगिंग या फायरिंग घटनाओं का उपयोग करने से प्रतिबंधित नहीं करता है, यह सिर्फ यह कहता है कि इस तरह के तर्क को अन्य कक्षाओं में समझाया जाना चाहिए, और इन अन्य वर्गों को कॉल करने के लिए एक रिपॉजिटरी के लिए यह ठीक है।

SRP ISP (S और I के साथ SOLID) के साथ मिलकर काम करता है। आप कई वर्गों और विधियों के साथ समाप्त होते हैं जो बहुत विशिष्ट चीजें करते हैं और कुछ नहीं। वे बहुत केंद्रित हैं, अद्यतन करने या बदलने में बहुत आसान हैं, और परीक्षण करने के लिए सामान्य आसान (एर) में हैं। बेशक अभ्यास में आपके पास कुछ बड़े वर्ग होंगे जो ऑर्केस्ट्रेशन से निपटते हैं: उनके पास कई निर्भरताएं होंगी, और वे परमाणु कार्यों पर नहीं, बल्कि व्यावसायिक कार्यों पर ध्यान केंद्रित करेंगे, जिसमें कई चरणों की आवश्यकता हो सकती है। जब तक व्यावसायिक संदर्भ स्पष्ट है, तब तक उन्हें भी एकल जिम्मेदारी कहा जा सकता है, लेकिन जैसा कि आपने सही कहा है, जैसे-जैसे कोड बढ़ता है, आप इसमें से कुछ को नई कक्षाओं / इंटरफेस में सार करना चाह सकते हैं।

अब अपने विशेष उदाहरण पर वापस आते हैं। यदि आप किसी उपयोगकर्ता द्वारा बनाए जाने पर पूरी तरह से एक सूचना भेज सकते हैं और शायद अन्य विशिष्ट कार्य भी कर सकते हैं, तो आप एक अलग सेवा बना सकते हैं जो इस आवश्यकता को पूरा करती है, कुछ ऐसा UserCreationService, जो एक विधि को उजागर करता है Add(user), जो दोनों भंडारण (कॉल) को संभालता है आपकी रिपॉजिटरी के लिए) और एकल व्यावसायिक कार्रवाई के रूप में अधिसूचना। या अपने मूल स्निपेट में, उसके बाद करें_userRepository.SaveChanges();


2
लॉगिंग व्यवसाय प्रवाह का हिस्सा नहीं है - यह एसआरपी के संदर्भ में कैसे प्रासंगिक है? यदि मेरी घटना का उद्देश्य Google Analytics में नया उपयोगकर्ता डेटा भेजना है - तो इसे अक्षम करना लॉगिंग को अक्षम करने के समान व्यवसाय प्रभाव होगा: महत्वपूर्ण नहीं, लेकिन बहुत परेशान करने वाला। किसी फ़ंक्शन में नए तर्क जोड़ने / न जोड़ने के लिए एक अंगूठे का नियम क्या है? "क्या यह अक्षम करने से प्रमुख व्यावसायिक दुष्प्रभाव होंगे?"
आंद्रे बोर्जेस

2
If the purpose of my event would be to send new user data to Google Analytics - then disabling it would have the same business effect as disabling logging: not critical, but pretty upsetting । क्या होगा यदि आप नकली "समाचार" के कारण समय से पहले की घटनाओं को दूर कर रहे हैं। क्या होगा यदि एनालिटिक्स "उपयोगकर्ताओं" को ध्यान में रख रहे हैं जो अंततः डीबी लेनदेन के साथ त्रुटियों के कारण नहीं बने थे? क्या होगा अगर कंपनी गलत आंकड़ों के आधार पर झूठे परिसरों पर निर्णय ले रही है? आप मुद्दे के तकनीकी पक्ष पर भी केंद्रित हैं। "कभी-कभी आप पेड़ों के लिए लकड़ी नहीं देख सकते हैं"
लैवि

@Laiv, आप एक वैध बिंदु बना रहे हैं, लेकिन यह मेरे प्रश्न या इस उत्तर का बिंदु नहीं है। सवाल यह है कि क्या यह एसआरपी के संदर्भ में एक वैध समाधान है, तो मान लें कि डीबी लेनदेन में कोई त्रुटि नहीं है।
आंद्रे बोर्जेस

आप मूल रूप से मुझे यह बताने के लिए कह रहे हैं कि आप क्या सुनना चाहते हैं। मैं सिर्फ आपको गुंजाइश देता हूं। आपके लिए यह तय करने की व्यापक गुंजाइश है कि एसआरपी मायने रखती है या नहीं क्योंकि एसआरपी उचित संदर्भ के बिना बेकार है। IMO जिस तरह से आप चिंता के करीब आ रहे हैं वह गलत है क्योंकि आप केवल तकनीकी समाधान पर ध्यान केंद्रित कर रहे हैं। आपको पूरे संदर्भ के लिए पर्याप्त प्रासंगिकता देनी चाहिए। और हाँ, DB विफल हो सकता है। ऐसा होने का एक मौका है और आपको इसे छोड़ना नहीं चाहिए, क्योंकि जैसा कि आप जानते हैं, चीजें होती हैं और ये चीजें आपके दिमाग को एसआरपी या अन्य अच्छी प्रथाओं के बारे में संदेह के बारे में बदल सकती हैं।
लैवि

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

4

एसआरपी, सैद्धांतिक रूप से, लोगों के बारे में है , जैसा कि अंकल बॉब अपने लेख द सिंगल रिस्पॉन्सिबिलिटी प्रिंसिपल में बताते हैं । धन्यवाद रॉबर्ट हार्वे आपकी टिप्पणी में प्रदान करने के लिए।

सही प्रश्न है:

किस "हितधारक" ने "ईमेल भेजें" आवश्यकता को जोड़ा?

यदि वह हितधारक डेटा दृढ़ता (बिना संभव लेकिन संभव) के प्रभारी भी है तो यह एसआरपी का उल्लंघन नहीं करता है। अन्यथा, यह करता है।


2
दिलचस्प है - मैंने एसआरपी की इस व्याख्या के बारे में कभी नहीं सुना। क्या आपके पास इस व्याख्या के बारे में अधिक जानकारी / साहित्य के लिए कोई संकेत है?
सेल्स्के

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

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

1
हां। यही हाल REST शब्द का हुआ। यहां तक ​​कि रॉय फील्डिंग का कहना है कि लोग इसका गलत इस्तेमाल कर रहे हैं।
रॉबर्ट हार्वे

हालाँकि, यह संबंधित है, मुझे लगता है कि यह उत्तर याद आता है कि "ईमेल भेजें" आवश्यकता एसआरपी उल्लंघन प्रश्न के बारे में प्रत्यक्ष आवश्यकताओं में से कोई भी नहीं है। हालांकि, "कौन सा" हितधारक "" घटना बढ़ाएं "आवश्यकता को जोड़कर , यह उत्तर वास्तविक प्रश्न से अधिक संबंधित हो जाएगा। मैंने इसे और अधिक स्पष्ट करने के लिए अपने स्वयं के उत्तर को थोड़ा संशोधित किया।
डॉक्टर ब्राउन

2

जबकि तकनीकी रूप से रिपॉजिटरी घटनाओं को सूचित करने के साथ कुछ भी गलत नहीं है, मैं इसे एक कार्यात्मक दृष्टिकोण से देखने का सुझाव दूंगा जहां इसकी सुविधा आपकी चिंताओं को बढ़ाती है।

एक उपयोगकर्ता बनाना, यह तय करना कि एक नया उपयोगकर्ता क्या है और इसकी दृढ़ता 3 अलग-अलग चीजें हैं

मेरा प्रेम

यह निर्धारित करने से पहले पिछले आधार पर विचार करें कि क्या व्यावसायिक घटनाओं (SRP की परवाह किए बिना) को अधिसूचित करने के लिए रिपॉजिटरी उचित स्थान है। ध्यान दें कि मैंने व्यावसायिक कार्यक्रम कहा है क्योंकि मेरे UserCreatedपास 1UserStored या UserAdded 1 की तुलना में एक अलग अर्थ है । मैं उन घटनाओं में से प्रत्येक को अलग-अलग दर्शकों को संबोधित करने पर भी विचार करूंगा।

एक तरफ, उपयोगकर्ता बनाना एक व्यापार-विशिष्ट नियम है जिसमें दृढ़ता शामिल हो सकती है या नहीं भी हो सकती है। इसमें अधिक डेटाबेस / नेटवर्क संचालन को शामिल करते हुए अधिक व्यावसायिक संचालन शामिल हो सकते हैं। संचालन की परत से अनजान है। दृढ़ता परत में यह तय करने के लिए पर्याप्त संदर्भ नहीं है कि उपयोग मामला सफलतापूर्वक समाप्त हुआ या नहीं।

दूसरी तरफ, यह जरूरी नहीं कि यह सच है _dataContext.SaveChanges();जिसने उपयोगकर्ता को सफलतापूर्वक जारी रखा है। यह डेटाबेस के लेनदेन की अवधि पर निर्भर करेगा। उदाहरण के लिए, यह MongoDB जैसे डेटाबेस के लिए सही हो सकता है, जो लेनदेन परमाणु हैं, लेकिन यह पारंपरिक RDBMS के लिए ACID लेनदेन को लागू करने के लिए नहीं हो सकता है, जहां अधिक लेनदेन शामिल हो सकते हैं और अभी तक प्रतिबद्ध हो सकते हैं।

क्या यह एक वैध बिंदु है?

यह हो सकता था। हालांकि, मैं यह कहने की हिम्मत करूंगा कि यह केवल एसआरपी (तकनीकी रूप से बोलने वाला) की बात नहीं है, यह सुविधा की बात भी है (कार्यात्मक रूप से बोलना)।

  • क्या यह प्रगति में व्यापार के संचालन से अनजान घटकों से व्यावसायिक घटनाओं को आग लगाने के लिए सुविधाजनक है?
  • क्या वे सही जगह का प्रतिनिधित्व करते हैं जितना कि इसे करने के लिए सही क्षण?
  • क्या मुझे इन घटकों को इस तरह से सूचनाओं के माध्यम से अपने व्यावसायिक तर्क को ऑर्केस्ट्रेट करने की अनुमति देनी चाहिए?
  • क्या मैं समयपूर्व घटनाओं के कारण होने वाले दुष्प्रभावों को अमान्य कर सकता हूं? 2

यह मुझे लगता है कि यहां एक घटना को उठाना अनिवार्य रूप से लॉगिंग के समान है

बिलकुल नहीं। लॉगिंग का कोई साइड इफेक्ट नहीं है, हालांकि, जैसा कि आपने सुझाव दिया है कि इस घटना के UserCreatedकारण अन्य व्यावसायिक संचालन होने की संभावना है। पसंद सूचनाएं। 3

यह सिर्फ यह कहता है कि इस तरह के तर्क को अन्य वर्गों में समझाया जाना चाहिए, और एक रिपॉजिटरी के लिए इन अन्य वर्गों को कॉल करना ठीक है

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


1: चीजों का नामकरण पर्याप्त रूप से भी मायने रखता है।

2: कहें कि हमने UserCreatedबाद में भेजा है _dataContext.SaveChanges();, लेकिन कनेक्शन मुद्दों या बाधाओं के उल्लंघन के कारण पूरा डेटाबेस लेनदेन बाद में विफल हो गया। घटनाओं के समय से पहले प्रसारण के साथ सावधान रहें, क्योंकि इसके दुष्प्रभाव पूर्ववत करना मुश्किल हो सकता है (यदि यह भी संभव है)।

3: पर्याप्त रूप से व्यवहार नहीं की गई अधिसूचना प्रक्रियाओं के कारण आप उन सूचनाओं को आग लगा सकते हैं जो पूर्ववत नहीं की जा सकती हैं


1
+1 लेन-देन अवधि के बारे में बहुत अच्छी बात है। यह उपयोगकर्ता को बनाने के लिए समय से पहले बनाया जा सकता है, क्योंकि रोलबैक हो सकता है; और एक लॉग के विपरीत, यह संभावना है कि ऐप का कुछ अन्य हिस्सा घटना के साथ कुछ करता है।
एंड्रेस एफ।

2
ठीक ठीक। घटनाक्रम निश्चितता को दर्शाता है। कुछ हुआ लेकिन खत्म हो गया।
Laiv

1
@ लीव: को छोड़कर जब वे नहीं करते। माइक्रोसॉफ्ट के साथ उपसर्ग घटनाओं के सभी प्रकार है Beforeया Previewकि निश्चितता के बारे में बिल्कुल भी कोई गारंटी नहीं।
रॉबर्ट हार्वे

1
@ jpmc26: विकल्प के बिना, आपका सुझाव मददगार नहीं है।
रॉबर्ट हार्वे

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

1

नहीं, यह एसआरपी का उल्लंघन नहीं करता है।

कई लोग सोचते हैं कि सिंगल रिस्पॉन्सिबिलिटी प्रिंसिपल का मतलब है कि एक फंक्शन को केवल "एक काम" करना चाहिए, और फिर "एक चीज" का गठन करने के बारे में चर्चा में फंस जाना चाहिए।

लेकिन सिद्धांत का मतलब यह नहीं है। यह व्यवसाय-स्तर की चिंताओं के बारे में है। एक वर्ग को कई चिंताओं या आवश्यकताओं को लागू नहीं करना चाहिए जो व्यावसायिक स्तर पर स्वतंत्र रूप से बदल सकते हैं। कहते हैं कि एक वर्ग दोनों को उपयोगकर्ता को संग्रहीत करता है और ईमेल के माध्यम से हार्डकोडेड स्वागत संदेश भेजता है। एकाधिक स्वतंत्र चिंताएं इस तरह की कक्षा की आवश्यकताओं को बदल सकती हैं। डिजाइनर को मेल के html / स्टाइलशीट को बदलने की आवश्यकता हो सकती है। संचार विशेषज्ञ को बदलने के लिए मेल के शब्दांकन की आवश्यकता हो सकती है। और UX विशेषज्ञ यह तय कर सकता है कि मेल वास्तव में ऑनबोर्डिंग प्रवाह में एक अलग बिंदु पर भेजा जाना चाहिए। इसलिए वर्ग स्वतंत्र स्रोतों से कई आवश्यकता परिवर्तन के अधीन है। यह एसआरपी का उल्लंघन करता है।

लेकिन किसी घटना को फायर करना SRP का उल्लंघन नहीं करता है, क्योंकि घटना केवल उपयोगकर्ता को बचाने पर निर्भर करती है और किसी अन्य चिंता पर नहीं। घटनाक्रम वास्तव में एसआरपी को बनाए रखने के लिए एक बहुत अच्छा तरीका है, क्योंकि आपके पास बचाने के लिए बचाने वाले ईमेल को ट्रिगर किया जा सकता है, जिसके बिना भंडार प्रभावित हो रहा है - या मेल के बारे में भी जानना।


1

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

इस मामले में लागू करने के लिए सबसे उपयोगी सिद्धांत कम से कम आश्चर्य का सिद्धांत है । तो चलिए सवाल पूछते हैं: क्या यह आश्चर्यजनक है कि डेटाबेस को डेटा जारी रखने की प्राथमिक भूमिका वाला रिपॉजिटरी भी ई-मेल भेजता है?

हां, यह बहुत आश्चर्य की बात है। ये दो पूरी तरह से अलग बाहरी सिस्टम हैं, और नाम का 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()कॉल विफल हो जाती है। (अन्यथा, आपको हाइजेनबग्स से बचने के लिए एक पूर्ण विकसित दो चरण की रणनीति की आवश्यकता होगी।)


लब्बोलुआब यह है कि व्यावहारिक होना चाहिए। असल में कोड लिखने के परिणामों (जोखिम और लाभ दोनों) के माध्यम से सोचें। मुझे लगता है कि "एकल जिम्मेदारी सिद्धांत" बहुत बार मुझे ऐसा करने में मदद नहीं करता है, जबकि "कम से कम आश्चर्य का सिद्धांत" अक्सर मुझे एक और डेवलपर के सिर में प्रवेश करने में मदद करता है (इसलिए बोलने के लिए) और सोचें कि क्या हो सकता है।


4
क्या यह आश्चर्य की बात है कि एक डेटाबेस के लिए डेटा को बनाए रखने की प्राथमिक भूमिका के साथ एक रिपॉजिटरी भी ई-मेल भेजता है - मुझे लगता है कि आपने मेरे प्रश्न का बिंदु याद किया। मेरा भंडार ईमेल नहीं भेज रहा है। यह सिर्फ एक घटना को बढ़ाता है, और इस घटना को कैसे नियंत्रित किया जाता है - बाहरी कोड की जिम्मेदारी है।
आंद्रे बोर्जेस

4
आप मूल रूप से तर्क दे रहे हैं "घटनाओं का उपयोग न करें।"
रॉबर्ट हार्वे

3
[श्रग] इवेंट अधिकांश UI फ्रेमवर्क के लिए केंद्रीय होते हैं। घटनाओं को खत्म करें, और उन चौखटे काम नहीं करते हैं।
रॉबर्ट हार्वे

2
@ jpmc26: इसे ASP.NET वेबफॉर्म कहा जाता है। यह बेकार है।
रॉबर्ट हार्वे

2
My repository is not sending emails. It just raises an eventकारण प्रभाव। रिपॉजिटरी अधिसूचना प्रक्रिया को ट्रिगर कर रही है।
लैवि

0

वर्तमान SaveChangesमें दो काम करता है: यह परिवर्तनों और लॉग को बचाता है जो ऐसा करता है। अब आप इसमें एक और चीज़ जोड़ना चाहते हैं: ईमेल सूचनाएँ भेजें।

आपके पास एक घटना को जोड़ने के लिए चतुर विचार था, लेकिन यह एकल जिम्मेदारी सिद्धांत (एसआरपी) का उल्लंघन करने के लिए आलोचना की गई थी, यह ध्यान दिए बिना कि यह पहले से ही उल्लंघन किया गया था।

एक शुद्ध एसआरपी समाधान प्राप्त करने के लिए, पहले घटना को ट्रिगर करें, फिर उस घटना के लिए सभी हुक को कॉल करें, जिनमें से अब तीन हैं: बचत, लॉगिंग और अंत में ईमेल भेजना।

या तो आप पहले घटना को ट्रिगर करते हैं, या आपको जोड़ना पड़ता है SaveChanges। आपका समाधान दोनों के बीच एक संकर है। यह मौजूदा उल्लंघन को संबोधित नहीं करता है जबकि यह इसे तीन चीजों से आगे बढ़ने से रोकने के लिए प्रोत्साहित करता है। SRP का पालन करने के लिए मौजूदा कोड को रिफलेक्ट करने से अधिक काम करने की आवश्यकता हो सकती है। यह आपके प्रोजेक्ट पर निर्भर है कि वे कितनी दूर तक एसआरपी लेना चाहते हैं।


-1

कोड ने पहले ही SRP का उल्लंघन किया था - डेटा संदर्भ और लॉगिंग के साथ संचार के लिए एक ही वर्ग जिम्मेदार था।

आप इसे 3 जिम्मेदारियों के लिए अपग्रेड करते हैं।

1 जिम्मेदारी से चीजों को वापस करने का एक तरीका सार को अमूर्त करना होगा _userRepository; इसे कमांड-ब्रॉडकास्टर बनाएं।

इसमें कमांड का एक सेट है, साथ ही श्रोताओं का एक सेट है। यह आज्ञा प्राप्त करता है, और अपने श्रोताओं के लिए उन्हें प्रसारित करता है। संभवतः उन श्रोताओं को आदेश दिया गया है, और शायद वे यह भी कह सकते हैं कि कमांड विफल हो गई है (जो बदले में उन श्रोताओं को प्रसारित किया जाता है जिन्हें पहले ही अधिसूचित किया गया था)।

अब, अधिकांश कमांड में केवल 1 श्रोता (डेटा संदर्भ) हो सकता है। SaveChanges, आपके परिवर्तनों से पहले, 2 है - डेटा संदर्भ, और फिर लकड़हारा।

आपका परिवर्तन तब परिवर्तनों को सहेजने के लिए एक और श्रोता जोड़ता है, जो कि ईवेंट सेवा में नए उपयोगकर्ता द्वारा बनाई गई ईवेंट को उठाना है।

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

यह सब तब तय हो जाता है जब _userRepositoryबनाया जाता है और वायर्ड हो जाता है (या, हो सकता है, उन अतिरिक्त सुविधाओं को फ्लाई पर जोड़ा / हटा दिया जाता है; एप्लिकेशन रन का उपयोग करते समय लॉगिंग को जोड़ने / बढ़ाने में सक्षम हो सकता है)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.