एकल जिम्मेदारी सिद्धांत - क्या मैं इसका अत्यधिक उपयोग कर रहा हूं?


13

संदर्भ के लिए - http://en.wikipedia.org/wiki/Single_responsibility_principle

मेरे पास एक परीक्षण परिदृश्य है जहां आवेदन के एक मॉड्यूल में खाता बही प्रविष्टियां बनाने के लिए जिम्मेदार है। तीन बुनियादी कार्य हैं जिन्हें पूरा किया जा सकता है -

  • तालिका स्वरूप में मौजूदा खाता-बही प्रविष्टियाँ देखें।
  • Create बटन का उपयोग करके नया लेज़र एंट्री बनाएँ।
  • तालिका में एक लेज़र प्रविष्टि पर क्लिक करें (पहले पॉइंटर में उल्लिखित) और अगले पृष्ठ में इसके विवरण देखें। आप इस पृष्ठ में एक लेज़र प्रविष्टि को शून्य कर सकते हैं।

(प्रत्येक पृष्ठ में कुछ और संचालन / मान्यताएँ हैं लेकिन संक्षिप्तता के कारण मैं इसे इन तक सीमित करूँगा)

इसलिए मैंने तीन अलग-अलग कक्षाएं बनाने का फैसला किया -

  • LedgerLandingPage
  • CreateNewLedgerEntryPage
  • ViewLedgerEntryPage

ये वर्ग उन सेवाओं की पेशकश करते हैं जिन्हें उन पृष्ठों में किया जा सकता है और सेलेनियम परीक्षण इन कक्षाओं का उपयोग एक राज्य में आवेदन करने के लिए करता है जहां मैं कुछ दावे कर सकता हूं।

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


2
IMHO सामान्य तौर पर आपके प्रश्न का उत्तर देने की कोशिश नहीं करता है, दो चीजों को जाने बिना: ये कक्षाएं (विधि गणना और LOC द्वारा) कितनी बड़ी हैं? और कितना बड़ा / अधिक जटिल वे भविष्य के भविष्य में बढ़ने की उम्मीद कर रहे हैं?
पेटर तोर्क

2
10 विधियाँ प्रत्येक IMHO का एक स्पष्ट संकेत है कि कोड को 30 विधियों के साथ एक कक्षा में न डालें।
डॉक ब्राउन

6
यह सीमावर्ती क्षेत्र है: 100 एलओसी और 10 विधियों का एक वर्ग बहुत छोटा नहीं है , और 300 एलओसी में से एक बहुत बड़ा नहीं है । हालांकि, एक एकल कक्षा में 30 विधियां मेरे लिए बहुत ज्यादा ध्वनि हैं। कुल मिलाकर, मैं @ डॉक के साथ सहमत हूं कि इसमें कई छोटे वर्गों के मुकाबले एक ही अधिक वजन वाले वर्ग के लिए कम जोखिम है। विशेष रूप से इस बात को ध्यान में रखते हुए कि कक्षाएं स्वाभाविक रूप से समय के साथ वजन बढ़ने
लगती हैं

1
@ PéterTörök - मैं मानता हूं कि जब तक कि कोड को एक वर्ग में रिफैक्ट नहीं किया जा सकता है जो कि सहज रूप से इस्तेमाल किया जा सकता है जो कोड की नकल करने के बजाय कोड का पुन: उपयोग करता है जैसे मुझे उम्मीद है कि ओपी के पास है।
सोय्लेंटग्रे

1
शायद एमवीसी को लागू करने से यह सब स्पष्ट हो जाएगा: तीन विचार, एक मॉडल (लेजर), और शायद तीन नियंत्रक।
केविन क्लाइन

जवाबों:


19

यहाँ @YannisRizos का हवाला देते हुए :

यह एक सहज दृष्टिकोण है और यह शायद सही है, क्योंकि बदलाव के लिए अधिक संभावित है कि प्रबंधन के नेतृत्व के तर्क क्या हैं। अगर ऐसा होता है, तो एक वर्ग को तीन की तुलना में बनाए रखना बहुत आसान होगा।

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

LedgerLandingPage

CreateNewLedgerEntryPage

ViewLedgerEntryPage

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

यदि आपके पास उन 3 वर्गों के बीच सामान्य कार्यक्षमताएं हैं, तो वे या तो एक सामान्य आधार वर्ग में होते हैं, Ledgerवर्ग स्वयं (मेरा मानना ​​है कि आपके पास एक है, कम से कम, CRUD संचालन के लिए) या एक अलग सहायक वर्ग में।

यदि आपको बहुत सारी छोटी कक्षाओं को बनाने के लिए अधिक तर्क की आवश्यकता है, तो मैं रॉबर्ट मार्टिन की पुस्तक "क्लीन कोड" पर एक नज़र डालने की सलाह देता हूं ।


यही कारण है कि मैं एक कक्षा में सब कुछ धकेलने के बजाय तीन अलग-अलग वर्गों के साथ आया। चूंकि इनमें से किसी में भी मेरी कोई सामान्य कार्यक्षमता नहीं है इसलिए मेरे पास कोई सामान्य वर्ग नहीं है। लिंक के लिए धन्यवाद।
तरुण

2
"छोटी कक्षाओं को लगभग हर मामले में बनाए रखना बेहतर होता है जो मैं सोच सकता हूं।" मुझे नहीं लगता कि क्लीन कोड भी इतनी दूर जाएगा। क्या आप वास्तव में तर्क देंगे कि, एक एमवीसी पैटर्न में, प्रति पृष्ठ एक नियंत्रक होना चाहिए (या उपयोग-केस, जैसा कि आप इसे डालते हैं), उदाहरण के लिए। रिफैक्टरिंग में, फाउलर में दो कोड-स्मेल एक साथ होती हैं: एक एक वर्ग (SRP) को बदलने के कई कारणों का उल्लेख करता है, और एक एक परिवर्तन के लिए कई वर्गों को संपादित करने का उल्लेख करता है।
पीडीआर

@pdr, ओपी बताता है कि इन वर्गों के बीच कोई सामान्य कार्यक्षमता नहीं है, इसलिए (मेरे लिए) ऐसी स्थिति की कल्पना करना कठिन है जब आपको एक से अधिक बदलाव करने के लिए एक से अधिक को छूने की आवश्यकता हो।
Péter Török

@pdr: यदि आपके पास एक परिवर्तन के लिए संपादित करने के लिए बहुत सी कक्षाएं हैं, तो यह ज्यादातर एक संकेत है कि आपने सामान्य कार्यक्षमता को अलग स्थान पर नहीं भेजा है। लेकिन उपर्युक्त उदाहरण में, यह संभवतः एक चतुर्थ वर्ग का नेतृत्व करेगा, और केवल एक नहीं।
Doc Brown

2
@pdr: BTW, क्या आपने वास्तव में "क्लीन कोड" पढ़ा है? बॉब मार्टिन छोटी इकाइयों में कोड को तोड़ने में बहुत दूर जाता है ।
डॉक्टर ब्राउन

11

एकल उत्तरदायित्व सिद्धांत, या किसी अन्य सिद्धांत का एक निश्चित कार्यान्वयन नहीं है। आपको यह तय करना चाहिए कि परिवर्तन के लिए अधिक संभावित क्या है।

जैसा @Karpie पहले वाले उत्तर में लिखता है :

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

यह एक सहज दृष्टिकोण है और यह शायद सही है, क्योंकि बदलाव के लिए अधिक संभावित है कि प्रबंधन के नेतृत्व के तर्क क्या हैं। अगर ऐसा होता है, तो एक वर्ग को तीन की तुलना में बनाए रखना बहुत आसान होगा।

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

डिजाइन सिद्धांतों के अति प्रयोग के विषय पर एक समान सवाल, कि मुझे लगता है कि आप दिलचस्प पाएंगे: डिज़ाइन पैटर्न: कब और कब उपयोग करना है?


1
एसआरपी, मेरी समझ में, वास्तव में एक डिजाइन पैटर्न नहीं है।
डॉक्टर ब्राउन

@DocBrown बेशक एक डिजाइन पैटर्न नहीं है, लेकिन सवाल पर चर्चा बेहद प्रासंगिक है ... अच्छा पकड़ हालांकि, मैंने जवाब अपडेट किया है
yannis

4

आइए इन वर्गों की जांच करें:

  • LedgerLandingPage: इस वर्ग की भूमिका लीडर्स की सूची दिखाना है। जैसे-जैसे एप्लिकेशन बढ़ता है, आप संभवतः अपने डेटा स्रोतों से डेटा में सॉर्टिंग, फ़िल्टरिंग, हाइलाइटिंग और पारदर्शी रूप से फ़्यूज़ के लिए तरीके जोड़ना चाहेंगे।

  • ViewLedgerEntryPage: यह पृष्ठ खाता बही को विस्तार से दिखाता है। बहुत सीधे आगे लगता है। जब तक डेटा सीधे आगे है। आप यहाँ बही को शून्य कर सकते हैं। आप इसे सही करना चाहते हैं। या यह टिप्पणी करें, या एक फाइल, रसीद या बाहरी बुकिंग नंबर या जो भी संलग्न करें। और एक बार जब आप संपादन की अनुमति देते हैं, तो आप निश्चित रूप से एक इतिहास दिखाना चाहते हैं।

  • CreateLedgerEntryPage: यदि ViewLedgerEntryPageपूर्ण संपादन क्षमता है, तो इस श्रेणी की जिम्मेदारी संभवतः "रिक्त प्रविष्टि" को संपादित करके पूरी की जा सकती है, जो समझ में नहीं आती है या नहीं हो सकती है।

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


SRP अति प्रयोग जैसी कोई चीज है : यदि आपको एक फ़ाइल की सामग्री को पढ़ने के लिए एक दर्जन कक्षाओं की आवश्यकता होती है, तो यह मान लेना सुरक्षित है कि आप ऐसा कर रहे हैं।

यदि आप दूसरी तरफ से एसआरपी को देखते हैं, तो यह वास्तव में कहता है, कि एक एकल वर्ग द्वारा एक जिम्मेदारी का ध्यान रखा जाना चाहिए। हालांकि, कृपया ध्यान दें कि जिम्मेदारियां केवल अमूर्त स्तरों के भीतर मौजूद हैं। तो यह एक उच्च स्तर के वर्ग के लिए पूरी तरह से समझ में आता है, जो निचले स्तर के घटक को काम सौंपकर अपनी जिम्मेदारी को पूरा करता है, जो कि निर्भरता उलटा के माध्यम से सबसे अच्छा प्राप्त होता है


मुझे लगता है कि यहां तक ​​कि मैं इन वर्गों की जिम्मेदारी का वर्णन नहीं कर सकता था जो आपने किया था।
तरुण

2

क्या उन वर्गों के पास बदलाव का केवल एक कारण है?

यदि आप इसे (अभी तक) नहीं जानते हैं, तो आप सट्टा डिज़ाइन / ओवर इंजीनियरिंग ट्रैप (बहुत सारी कक्षाएं, बहुत जटिल डिज़ाइन पैटर्न लागू) में कदम रख सकते हैं। आपने YAGNI को संतुष्ट नहीं किया है । सॉफ़्टवेयर जीवन चक्र के शुरुआती चरणों में (कुछ) आवश्यकताएँ स्पष्ट नहीं हो सकती हैं। इस प्रकार परिवर्तन की दिशा वर्तमान में आपके लिए दिखाई नहीं दे रही है। यदि आपको लगता है कि, इसे एक या न्यूनतम कक्षाओं में रखें। हालांकि यह एक दायित्व के साथ आता है: जैसे ही आवश्यकताएं और परिवर्तन की दिशा स्पष्ट होती है, आपको वर्तमान डिजाइन पर पुनर्विचार करने और परिवर्तन के कारण को पूरा करने के लिए एक रिफैक्टिंग करने की आवश्यकता होती है।

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

पूरा बिंदु है:

  • बदलाव के लिए वाहन चालकों पर नजर रखें।
  • एक लचीली डिज़ाइन का चुनाव करें, जिसे रिफैक्ट किया जा सके।
  • रिफैक्टर कोड के लिए तैयार रहें।

यदि आपके पास यह मानसिकता है, तो आप अटकलें डिजाइन / इंजीनियरिंग से अधिक डर के बिना कोड को आकार देंगे।

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


1

SRP को वर्ग विभाजित करने के कारण के रूप में लागू करने के तीन कारण हैं:

  • ताकि भविष्य में आवश्यकताओं में बदलाव से कुछ वर्ग अपरिवर्तित रह सकें
  • ताकि एक बग को और अधिक तेजी से अलग किया जा सके
  • कक्षा को छोटा बनाने के लिए

एक वर्ग को विभाजित करने से इनकार करने के तीन कारण हैं:

  • ताकि भविष्य में आवश्यकताओं में बदलाव के कारण आपको कई वर्गों में समान परिवर्तन नहीं करना पड़े
  • ताकि बग-खोज में अप्रत्यक्ष के लंबे रास्तों को शामिल न किया जा सके
  • एनकैप्सुलेशन-ब्रेकिंग तकनीकों (गुणों, मित्रों, जो भी) का विरोध करने के लिए सभी को जानकारी या तरीकों का खुलासा करना चाहिए जब उन्हें केवल एक संबंधित वर्ग द्वारा आवश्यक हो

जब मैं आपके मामले को देखता हूं और परिवर्तनों की कल्पना करता हूं, तो उनमें से कुछ कई वर्गों में परिवर्तन का कारण बनेंगे (उदाहरण के लिए एक फ़ील्ड को लेज़र में जोड़ें, आपको तीनों को बदलने की आवश्यकता होगी) लेकिन बहुत से नहीं होंगे - उदाहरण के लिए लेज़र की सूची में छंटनी या नए नियम प्रविष्टि को जोड़ने पर सत्यापन नियमों को बदलना। आपके सहकर्मी की प्रतिक्रिया शायद इसलिए है क्योंकि यह जानना मुश्किल है कि बग की तलाश कहाँ की जाए। यदि कुछ लोनर्स की सूची में गलत दिखता है, तो क्या यह गलत तरीके से जोड़ा गया है, या सूची में कुछ गड़बड़ है? यदि सारांश और विवरण के बीच कोई विसंगति है, जो गलत है?

यह भी संभव है कि आपका सहकर्मी यह सोचता है कि आवश्यकताओं में परिवर्तन का मतलब है कि आपको सभी तीन वर्गों को बदलना होगा, उन परिवर्तनों की तुलना में कहीं अधिक संभावना है जहां आप केवल एक को बदलने के साथ दूर हो जाएंगे। यह एक बहुत उपयोगी बातचीत हो सकती है।


एक अलग दृष्टिकोण को देखने के लिए अच्छा है
तरुण

0

मुझे लगता है कि अगर सीसा db में एक टेबल होता है, तो मैं सुझाव देता हूं कि इन थ्रेस टास्क को एक क्लास (जैसे DAO) में डाल दें। यदि लेज़र में अधिक तर्क है और db में टेबल नहीं था, तो मेरा सुझाव है कि हमें इन कार्यों को करने के लिए और क्लास बनाना चाहिए। (दो या तीन वर्ग हो सकते हैं) और ग्राहक के लिए बस करने के लिए एक मुखौटा वर्ग प्रदान करें।


अच्छी तरह से, बही यूआई में एक विशेषता है और इसके लिए कई संबंधित संचालन हैं जो विभिन्न पृष्ठों से किए जा सकते हैं।
तरुण

0

IMHO आपको कक्षाओं का उपयोग नहीं करना चाहिए। यहां कोई डेटा सार नहीं हैं। एक ठोस डेटा प्रकार हैं। उन्हें हेरफेर करने और प्रदर्शित करने के तरीके कार्य और प्रक्रियाएं हैं। निश्चित रूप से उपयोग किए जाने वाले कई कार्य किए जाएंगे, जैसे कि दिनांक को प्रारूपित करना। किसी भी डेटा को प्रदर्शित और चयन दिनचर्या में एक वर्ग में सारगर्भित और छिपे हुए के लिए बहुत कम जगह है।

लेज़र संपादन के लिए एक वर्ग में राज्य को छिपाने के लिए कुछ मामला है।

आप SRP को गाली दे रहे हैं या नहीं, आप कुछ अधिक मौलिक गाली दे रहे हैं: आप अमूर्तता का उपयोग कर रहे हैं। यह एक विशिष्ट समस्या है, जो मिथकीय धारणा से प्रेरित है OO एक समझदार विकास प्रतिमान है।

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


-1

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


2
मेरे लिए एक '... प्रबंधक' वर्ग आमतौर पर दिखाता है कि आप इसे आगे तोड़ने के लिए परेशान नहीं हो सकते। वर्ग प्रबंधन क्या है? प्रस्तुति, दृढ़ता?
सेबेस्टियनजिगर

-1। 3 या अधिक उपयोग के मामलों को 1 वर्ग में रखना बिल्कुल वही बात है जो SRP बचने की कोशिश कर रहा है - और अच्छे कारणों से।
डॉक्टर ब्राउन

@sebastiangeiger तो ओपी के तीन वर्ग क्या कर रहे हैं? प्रस्तुति या हठ?
सेवंसेकाट

@ कर्क मैं ईमानदारी से प्रस्तुति की उम्मीद कर रहा हूं। दी गई, उदाहरण वास्तव में अच्छा नहीं है, लेकिन मुझे उम्मीद है कि एक वेबसाइट में '... पेज' एक दृश्य के समान है।
सेबस्टियनजिगर

2
वास्तव में, आपको पूरे एप्लिकेशन के लिए केवल एक वर्ग की आवश्यकता है, जो उपयोगकर्ताओं को खुश करने की एकल जिम्मेदारी के साथ; ;-)
Péter Török
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.