एकल जिम्मेदारी सिद्धांत का उपयोग करते समय, एक "जिम्मेदारी" क्या होती है


198

यह बहुत स्पष्ट लगता है कि "सिंगल रिस्पॉन्सिबिलिटी प्रिंसिपल" का मतलब यह नहीं है कि "केवल एक ही चीज है।" यही तरीके हैं।

public Interface CustomerCRUD
{
    public void Create(Customer customer);
    public Customer Read(int CustomerID);
    public void Update(Customer customer);
    public void Delete(int CustomerID);
}

बॉब मार्टिन का कहना है कि "वर्गों को बदलने का केवल एक कारण होना चाहिए।" लेकिन अगर आपके पास SOLID के लिए एक नया प्रोग्रामर है तो अपने दिमाग को लपेटना मुश्किल है।

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

तो आप इसे कैसे करते हैं? आप यह निर्धारित करते हैं कि प्रत्येक वर्ग के लिए कौन सी ज़िम्मेदारियाँ होनी चाहिए, और आप SRP के संदर्भ में एक ज़िम्मेदारी कैसे निर्धारित करते हैं?


28
कोड की समीक्षा करने के लिए पोस्ट करें और अलग हो जाएं :-D
Jörg W Mittag

8
@ JörgWMittag अरे अब, लोगों को डराओ मत :)
फ्लैम्बिनो

117
इस तरह अनुभवी सदस्यों से सवाल है कि नियमों और सिद्धांतों हम प्रयास नहीं भी तरह से कर रहे हैं करने के लिए पकड़ करने के लिए प्रदर्शित सीधा या सरल । वे [तरह के] आत्म-विरोधाभासी और रहस्यमय हैं ... जैसा कि नियमों का कोई अच्छा सेट होना चाहिए। और, मैं इस विनम्र बुद्धिमान की तरह सवालों पर विश्वास करना चाहता हूं, और उन लोगों को आशा देता हूं जो निराशाजनक रूप से बेवकूफ हैं। धन्यवाद, रॉबर्ट!
svidgen

41
मुझे आश्चर्य है कि अगर इस सवाल को नीचा दिखाया जाता + तो सीधे डुप्लिकेट चिह्नित होता अगर यह एक noob द्वारा पोस्ट किया गया था :)
बेपन्स

9
@rmunn: या दूसरे शब्दों में - बड़ा प्रतिनिधि और भी अधिक आकर्षित करता है, क्योंकि स्टैटेक्सचेंज पर बुनियादी मानव पूर्वाग्रह को किसी ने भी रद्द नहीं किया है
वृषभ

जवाबों:


117

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

उदाहरण के लिए:

नई व्यावसायिक आवश्यकता: कैलिफोर्निया में स्थित उपयोगकर्ताओं को विशेष छूट मिलती है।

"अच्छा" परिवर्तन का उदाहरण: मुझे एक वर्ग में कोड को संशोधित करने की आवश्यकता है जो छूट की गणना करता है।

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

या:

नई गैर-जरूरी आवश्यकता: हम SQL सर्वर के बजाय Oracle का उपयोग करना शुरू करेंगे

अच्छे बदलाव का उदाहरण: डेटा एक्सेस लेयर में एक एकल वर्ग को संशोधित करने की आवश्यकता है जो यह निर्धारित करता है कि डीटीओ में डेटा को कैसे बनाए रखा जाए।

बुरा परिवर्तन: मुझे अपने सभी व्यावसायिक परत वर्गों को संशोधित करने की आवश्यकता है क्योंकि उनमें SQL सर्वर-विशिष्ट तर्क हैं।

यह विचार भविष्य के संभावित परिवर्तनों के पदचिह्न को कम करने के लिए है, परिवर्तन के प्रति क्षेत्र के एक क्षेत्र में कोड संशोधनों को प्रतिबंधित करना।

बहुत कम से कम, आपकी कक्षाओं को तार्किक चिंताओं को शारीरिक चिंताओं से अलग करना चाहिए। उदाहरण के एक महान सेट में पाया जा सकता है System.IOनाम स्थान: वहाँ हम शारीरिक धाराओं (जैसे की एक विभिन्न प्रकार प्राप्त कर सकते हैं FileStream, MemoryStreamया NetworkStream) और विभिन्न पाठकों और लेखकों ( BinaryWriter, TextWriter) है कि एक तार्किक स्तर पर काम करते हैं। उन्हें इस तरह से अलग करके, हम combinatoric विस्फोट से बचने: की आवश्यकता होगी, के बजाय FileStreamTextWriter, FileStreamBinaryWriter, NetworkStreamTextWriter, NetworkStreamBinaryWriter, MemoryStreamTextWriter, और MemoryStreamBinaryWriter, आप बस ऊपर लेखक और धारा हुक और आप आप क्या चाहते हो सकता है। फिर बाद में हम XmlWriterइसे अलग से मेमोरी, फाइल और नेटवर्क के लिए फिर से लागू करने की आवश्यकता के बिना जोड़ सकते हैं, कह सकते हैं ।


34
जबकि मैं आगे की सोच से सहमत हूं, YAGNI जैसे सिद्धांत हैं और TDD थार जैसे तरीके विपरीत हैं।
रॉबर्ट हार्वे

87
YAGNI हमें वह सामान बनाने के लिए कहता है जिसकी हमें आज जरूरत नहीं है यह एक तरह से सामान का निर्माण नहीं करना बताता है जो कि एक्स्टेंसिबल है। खुला / बंद सिद्धांत भी देखें , जिसमें कहा गया है कि "सॉफ्टवेयर इकाइयां (कक्षाएं, मॉड्यूल, फ़ंक्शन, आदि) विस्तार के लिए खुली होनी चाहिए, लेकिन संशोधन के लिए बंद हो जाना चाहिए।"
जॉन वू

18
@ जॉन: आपकी YAGNI टिप्पणी के लिए +1 अकेले। मैं विश्वास नहीं कर सकता कि मुझे लोगों को कितना समझाना है कि YAGNI एक कठोर, अनम्य प्रणाली का निर्माण करने का बहाना नहीं है जो परिवर्तन पर प्रतिक्रिया नहीं कर सकता है - विडंबना यह है कि SRP और ओपन / बंद रियासतों के लिए बहुत विपरीत हैं।
ग्रेग बरगार्ड

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

9
@ जॉनोहू हमने एसक्यूएल 2008 से 2012 तक स्विच किया। कुल दो प्रश्न थे जिन्हें बदलने की आवश्यकता थी। और SQL प्रामाणिक से विश्वसनीय करने के लिए? यह भी एक कोड परिवर्तन क्यों होगा; कॉन्फ़िग फ़ाइल में कनेक्शनस्ट्रीमिंग को बदलना पर्याप्त है। फिर, YAGNI। YAGNI और SRP कभी-कभी चिंता का कारण बनते हैं, और आपको यह निर्धारित करने की आवश्यकता होती है कि किसकी बेहतर लागत / लाभ है।
एंडी

76

व्यावहारिक रूप से, जिम्मेदारियां उन चीजों से बंधी होती हैं, जिन्हें बदलने की संभावना है। इस प्रकार, दुर्भाग्य से एक जिम्मेदारी का गठन करने के लिए कोई वैज्ञानिक या फार्मूलाबद्ध तरीका नहीं है। यह एक निर्णय कॉल है।

यह आपके अनुभव में क्या है, इसे बदलने की संभावना है।

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

इसलिए, यदि डिवीजनों को संभावित परिवर्तनों से प्रेरित नहीं किया जाता है , तो वे वास्तव में SRP 1 की सेवा में नहीं हैं यदि YAGNI अधिक लागू हो। दोनों एक ही परम लक्ष्य की सेवा करते हैं। और दोनों निर्णय के मामले हैं - उम्मीद के मुताबिक निर्णय।

जब अंकल बॉब इस बारे में लिखते हैं, तो वे सुझाव देते हैं कि हम "जो परिवर्तन के लिए पूछ रहे हैं" के संदर्भ में "जिम्मेदारी" के बारे में सोचते हैं। दूसरे शब्दों में, हम नहीं चाहते कि पार्टी ए अपनी नौकरी खो दे क्योंकि पार्टी बी ने बदलाव के लिए कहा।

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

अच्छे और अनुभवी डेवलपर्स के पास एक समझ होगी जिसके लिए बदलाव की संभावना है। और वह मानसिक सूची उद्योग और संगठन द्वारा कुछ हद तक भिन्न होगी।

आपके विशेष संगठन में, आपके विशेष एप्लिकेशन में एक जिम्मेदारी का गठन होता है, जो अंततः अनुभवी निर्णय है। यह बदलने की संभावना के बारे में है। और, एक मायने में, यह मॉड्यूल के आंतरिक तर्क का मालिक है।


1. स्पष्ट होना, इसका मतलब यह नहीं है कि वे बुरे विभाजन हैं। वे महान विभाजन हो सकते हैं जो नाटकीय रूप से कोड पठनीयता में सुधार करते हैं। इसका मतलब है कि वे एसआरपी द्वारा संचालित नहीं हैं।


11
सर्वश्रेष्ठ उत्तर, और वास्तव में अंकल बॉब के विचारों का उद्धरण। जैसा कि बदलने की संभावना है, हर कोई I / O पर एक बड़ा सौदा करता है, "अगर हम डेटाबेस को बदलते हैं तो क्या होगा?" या "क्या होगा अगर हम XML से JSON पर स्विच करते हैं?" मुझे लगता है कि यह आमतौर पर गुमराह है। असली सवाल यह होना चाहिए "क्या होगा अगर हमें इस उदाहरण को फ्लोट में बदलने, फ़ील्ड जोड़ने और इस स्ट्रिंग को सूची की सूची में बदलने की आवश्यकता है?"
user949300 1

2
यह धोखा है। स्वयं के द्वारा एकल जिम्मेदारी "परिवर्तन अलगाव" का एक प्रस्तावित तरीका है। समझाते हुए, कि आपको जिम्मेदारी को "एकल" रखने के लिए परिवर्तनों को अलग करना होगा, यह सुझाव नहीं देता कि यह कैसे करना है, बस आवश्यकता की उत्पत्ति की व्याख्या करता है।
बसिलेव्स

6
@Basilevs मैं इस उत्तर में जो कमी आप देख रहा हूँ, उस पर सान करने की कोशिश कर रहा हूँ - अंकल बॉब के उत्तर का उल्लेख नहीं करने के लिए! लेकिन, शायद मुझे यह स्पष्ट करने की आवश्यकता है कि एसआरपी यह सुनिश्चित करने के बारे में नहीं है कि "एक परिवर्तन" केवल 1 वर्ग को प्रभावित करेगा। यह सुनिश्चित करने के बारे में है कि प्रत्येक वर्ग केवल "एक परिवर्तन" का जवाब देगा। ... यह प्रत्येक वर्ग से एकल स्वामी तक आपके तीर खींचने की कोशिश करने के बारे में है। प्रत्येक मालिक से एकल वर्ग तक नहीं।
svidgen

2
एक व्यावहारिक प्रतिक्रिया प्रदान करने के लिए धन्यवाद! यहां तक ​​कि अंकल बॉब ने एजाइल आर्किटेक्चर में एसओएलआईडी सिद्धांतों के प्रति उत्साही पालन के खिलाफ चेतावनी दी है । मेरे पास बोली लगाने का काम नहीं है, लेकिन वह मूल रूप से कहता है कि जिम्मेदारियों को विभाजित करने से आपके कोड में अमूर्तता का स्तर बढ़ जाता है और यह कि सभी अमूर्त लागत पर आते हैं, इसलिए सुनिश्चित करें कि SRP (या अन्य सिद्धांतों) का पालन करने का लाभ लागत को कम करता है अधिक अमूर्त जोड़ने के लिए। (अगली टिप्पणी पर चर्चा करेंगे)
माइकल एल।

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

29

मैं पालन करता हूं "वर्गों को बदलने का केवल एक कारण होना चाहिए"।

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

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

व्यावहारिक रूप से, मुझे लगता है कि इकाई परीक्षण यहां मदद करते हैं। यदि आपका कोड अनम्य है, तो परीक्षण करना कठिन होगा। यदि आप मोक्स या अन्य परीक्षण डेटा को इंजेक्ट नहीं कर सकते हैं, तो आप शायद उस SupportChineseकोड को इंजेक्ट करने में सक्षम नहीं होंगे ।

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


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

16
मैं "लिफ्ट पिच" ​​विचार के लिए एक बड़ा वकील हूं। यदि यह स्पष्ट करना कठिन है कि एक वाक्य में एक वर्ग क्या करता है या दो आप जोखिम वाले क्षेत्र में हैं।
इवान

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

1
स्पष्ट लाभों के अलावा, "लिफ्ट पिचों" का उपयोग करके आपके कोड का दस्तावेजीकरण भी आपको यह सोचने में मदद करता है कि आपका कोड प्राकृतिक भाषा का उपयोग करके क्या कर रहा है जो मुझे कई जिम्मेदारियों को उजागर करने में उपयोगी लगता है।
अलेक्जेंडर

1
@KevinKrumwiede "चिकन अपने सिर को काटकर इधर-उधर भाग रहा है" और "वाइल्ड गूज चेस" के तरीके हैं!

26

कोई नहीं जानता। या कम से कम, हम एक परिभाषा पर सहमत होने में असमर्थ हैं। यही बात एसपीआर (और अन्य ठोस सिद्धांतों) को काफी विवादास्पद बनाती है।

मुझे लगता है कि यह पता लगाने में सक्षम है कि क्या है या एक जिम्मेदारी नहीं है एक कौशल सॉफ्टवेयर डेवलपर को अपने कैरियर के दौरान सीखना होगा। जितना अधिक कोड आप लिखते हैं और समीक्षा करते हैं, उतना ही अनुभव आपको यह निर्धारित करना होगा कि क्या कुछ एकल या कई जिम्मेदारियां हैं। या यदि कोड के अलग-अलग हिस्सों में एकल जिम्मेदारी खंडित है।

मैं तर्क दूंगा कि SRP का प्राथमिक उद्देश्य कठोर नियम नहीं है। यह हमें याद दिलाना है कि कोड में सामंजस्य होना चाहिए और हमेशा यह निर्धारित करने में कुछ सचेत प्रयास करना चाहिए कि कौन सा कोड सामंजस्यपूर्ण है और क्या नहीं है।


20
नए प्रोग्रामर के पास सॉलिड के साथ ऐसा व्यवहार करने की प्रवृत्ति है जैसे कि यह कानूनों का एक समूह है, जो यह नहीं है। क्लास डिजाइन में लोगों को बेहतर बनाने में मदद करने के लिए केवल अच्छे विचारों का समूह है। अफसोस, लोग इन सिद्धांतों को बहुत गंभीरता से लेते हैं; मैंने हाल ही में एक जॉब पोस्टिंग देखी है जिसमें एसओएलआईडी को नौकरी की जरूरतों में से एक बताया गया है।
रॉबर्ट हार्वे

9
अंतिम पैराग्राफ के लिए +42। जैसा @RobertHarvey कहते हैं, SPR, SOLID और YAGNI जैसी चीजों को " पूर्ण नियम " के रूप में नहीं लिया जाना चाहिए , लेकिन "अच्छी सलाह" के सामान्य सिद्धांत के रूप में। उनके (और अन्य लोगों के बीच) सलाह कभी-कभी विरोधाभासी होगी, लेकिन उस सलाह को संतुलित करते हुए (नियमों के कठोर सेट के विपरीत) समय के साथ, जैसा कि आपका अनुभव बढ़ता है, आपको बेहतर सॉफ्टवेयर का उत्पादन करने के लिए मार्गदर्शन करता है। सॉफ्टवेयर विकास में केवल एक "पूर्ण नियम" होना चाहिए: " कोई पूर्ण नियम नहीं हैं "।
ट्रिपहाउंड

यह एसआरपी के एक पहलू पर बहुत अच्छा स्पष्टीकरण है। लेकिन, भले ही ठोस सिद्धांत कठोर नियम नहीं हैं, वे बहुत मूल्यवान नहीं हैं यदि कोई नहीं समझता है कि उनका क्या मतलब है - इससे भी कम अगर आपका दावा है कि "कोई नहीं जानता" वास्तव में सच है! ... यह समझने के लिए कठिन होने के लिए उन्हें समझ में आता है। किसी भी कौशल के साथ, कुछ ऐसा है जो अच्छे को कम अच्छे से अलग करता है ! लेकिन ... "कोई नहीं जानता है" यह एक प्रेतवाधित अनुष्ठान के अधिक बनाता है। (और मुझे विश्वास नहीं है कि यह SOLID का इरादा है!)
svidgen

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

1
मैं दिल से दूसरे @TripeHound और अन्य जिन्होंने बताया है कि ये सभी "नियम" विकास के एक सच्चे धर्म को परिभाषित करने के लिए मौजूद नहीं हैं, लेकिन बनाए रखने योग्य सॉफ़्टवेयर के विकास की संभावना को बढ़ाने के लिए। "सर्वोत्तम अभ्यास" का पालन करने से बहुत सावधान रहें यदि आप यह नहीं समझा सकते हैं कि यह कैसे बनाए रखने योग्य सॉफ़्टवेयर को बढ़ावा देता है, गुणवत्ता में सुधार करता है या विकास की क्षमता बढ़ाता है ..
माइकल एल।

5

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

  • अधिकार के साथ जवाबदेही है।
  • किसी भी दो संस्थाओं को एक ही चीज के लिए जिम्मेदार नहीं होना चाहिए।

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

इन दोनों के अलावा, एक तीसरा सिद्धांत उचित लगता है:

  • जिम्मेदारी सौंपी जा सकती है

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

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


मुझे यकीन नहीं है कि यह पूरी तरह से इसे समझाता है। लेकिन, मुझे लगता है कि "अधिकार" के संबंध में "जिम्मेदारी" की व्याख्या करना यह वाक्यांश के लिए एक व्यावहारिक तरीका है! (+1)
svidgen

Pirsig ने कहा, "आप मशीन में अपनी समस्याओं का निर्माण करते हैं", जो मुझे विराम देता है।

@nocomprende आप मशीन में अपनी ताकत का निर्माण भी करते हैं। मैं तर्क दूंगा कि जब आपकी ताकत और आपकी कमजोरी एक ही चीज होती है, तभी यह दिलचस्प होती है।
Cort Ammon

5

येल में इस सम्मेलन में, अंकल बॉब ने यह मजेदार उदाहरण दिया:

यहां छवि विवरण दर्ज करें

वह कहता है कि Employeeपरिवर्तन के तीन कारण हैं, परिवर्तन आवश्यकताओं के तीन स्रोत, और यह विनोदी और जीभ-इन-गाल देता है , लेकिन फिर भी, उदाहरण के लिए, स्पष्टीकरण:

  • यदि CalcPay()विधि में त्रुटि है और कंपनी की लाखों अमेरिकी डॉलर की लागत है, तो सीएफओ आपको आग देगा

  • यदि ReportHours()विधि में कोई त्रुटि है और कंपनी की लाखों अमेरिकी डॉलर की लागत है, तो सीओओ आपको आग देगा

  • यदि WriteEmmployee() विधि में एक त्रुटि है जो बहुत सारे डेटा को नष्ट करने का कारण बनती है और कंपनी के लाखों अमेरिकी डॉलर खर्च करती है, तो सीटीओ आपको आग देगा

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

वह यह समाधान देता है जो एसआरपी के उल्लंघन को हल करता है, लेकिन अभी तक डीआईपी के उल्लंघन को हल करना है जो वीडियो में नहीं दिखाया गया है।

यहां छवि विवरण दर्ज करें


यह उदाहरण एक वर्ग की तरह दिखता है जिसमें गलत जिम्मेदारियां हैं।
रॉबर्ट हार्वे

4
@RobertHarvey जब किसी वर्ग में बहुत अधिक जिम्मेदारियां होती हैं, तो इसका मतलब है कि अतिरिक्त जिम्मेदारियां गलत जिम्मेदारियां हैं।
ट्यूलेंस कोरडोवा

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

@ रोबर्टहवे, क्या अंतर है? वे स्थितियाँ मुझे सम-विषम लगती हैं।
पॉल ड्रेपर

3

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

यदि दोनों प्रश्नों के उत्तर हां हैं, तो यह सुझाव देगा कि कार्रवाई अलग-अलग कक्षाओं द्वारा की जानी चाहिए। यदि दोनों प्रश्नों के उत्तर नहीं हैं, तो यह सुझाव देगा कि सार्वजनिक दृष्टिकोण से एक वर्ग होना चाहिए; यदि उस के लिए कोड अस्पष्ट होगा, तो इसे आंतरिक रूप से निजी वर्गों में विभाजित किया जा सकता है। यदि पहले प्रश्न का उत्तर नहीं है, लेकिन दूसरा हाँ है, प्रत्येक कार्रवाई के लिए एक अलग वर्ग होना चाहिए और एक समग्र वर्ग जिसमें दूसरों के उदाहरणों के संदर्भ शामिल हों।

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

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


यह ध्वनि सलाह है। यह इंगित करने के लायक हो सकता है कि आप केवल एसआरपी से अधिक मानदंडों के अनुसार जिम्मेदारियों को विभाजित करते हैं।
जोर्जेन फॉग

1
कार सादृश्य: मुझे यह जानने की आवश्यकता नहीं है कि किसी और के टैंक में कितनी गैस है, या किसी और के वाइपर को चालू करना चाहते हैं। (लेकिन यह इंटरनेट की परिभाषा है) (Shh! आप कहानी को बर्बाद कर देंगे)

1
@nocomprende - "मैं, पता करने के लिए कितना गैस किसी और के टैंक में है की जरूरत नहीं है" - जब तक आप एक किशोरी तय करने के लिए जो परिवार की कारों की अपनी अगली यात्रा के लिए "उधार" करने की कोशिश कर रहे हैं ...;)
alephzero

3

एसआरपी सही होना मुश्किल है। यह ज्यादातर आपके कोड को 'जॉब' सौंपने और प्रत्येक भाग की स्पष्ट जिम्मेदारियाँ सुनिश्चित करने का मामला है। वास्तविक जीवन की तरह, कुछ मामलों में लोगों के बीच काम को विभाजित करना काफी स्वाभाविक हो सकता है, लेकिन अन्य मामलों में यह वास्तव में मुश्किल हो सकता है, खासकर यदि आप उन्हें (या काम) नहीं जानते हैं।

मैं हमेशा आपको केवल सरल कोड लिखने की सलाह देता हूं जो पहले काम करता है , फिर थोड़ा रिफ्लेक्टर करें: आप यह देखना चाहेंगे कि कोड क्लस्टर्स स्वाभाविक रूप से थोड़ी देर बाद कैसे हो। मुझे लगता है कि कोड (या लोगों) और किए जाने वाले काम को जानने से पहले जिम्मेदारियों को लागू करना एक गलती है।

एक बात आप ध्यान देंगे जब मॉड्यूल बहुत अधिक काम करना शुरू कर देता है और डिबग / बनाए रखना कठिन होता है। यह पलटा करने वाला क्षण है; मुख्य कार्य क्या होना चाहिए और दूसरे मॉड्यूल को कौन से कार्य दिए जा सकते हैं? उदाहरण के लिए, क्या इसे सुरक्षा जांच और अन्य कार्य को संभालना चाहिए, या क्या आपको पहले कहीं और सुरक्षा जांच करनी चाहिए, या इससे कोड अधिक जटिल हो जाएगा?

भी कई indirections का उपयोग करें और यह KISS, YAGNI, आदि जैसे, फिर एक मेस हो जाता है ... के रूप में अन्य सिद्धांतों के लिए, यह एक दूसरों के साथ संघर्ष में हो जाएगा सब कुछ संतुलन की बात है।


क्या एसआरपी सिर्फ कॉन्सटेंटाइन का सामंजस्य नहीं है?
निक किली

यदि आप लंबे समय तक कोड करते हैं, तो आप स्वाभाविक रूप से उन पैटर्नों को पा लेंगे, लेकिन आप उनका नामकरण करके सीखने की गति बढ़ा सकते हैं और यह संचार में मदद करता है ...
क्रिस्टोफ़ रूसो

@NickKeighley मुझे लगता है कि यह सामंजस्य है, इतना बड़ा लेखन नहीं, लेकिन दूसरे दृष्टिकोण से देखा।
सुधाम

3

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

जब तक हम बग को ठीक नहीं कर रहे हैं, तब तक परिवर्तन एक नई या परिवर्तित व्यावसायिक आवश्यकता के कारण होगा। आपको कोड के बाहर स्वयं सोचना होगा, और कल्पना करना होगा कि बाहर के कारकों के कारण स्वतंत्र रूप से परिवर्तन की आवश्यकताएं क्या हो सकती हैं । कहते हैं:

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

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

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

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

अंकल बॉब को उद्धृत करने के लिए जिन्होंने इस शब्द का आविष्कार किया:

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

इसलिए योग करने के लिए: एक "जिम्मेदारी" एक एकल व्यावसायिक कार्य के लिए खानपान है। यदि एक से अधिक अभिनेता आपको क्लास बदलने के लिए प्रेरित कर सकते हैं, तो शायद क्लास इस सिद्धांत को तोड़ देता है।


उनकी पुस्तक "क्लीन आर्किटेक्चर" के अनुसार यह बिल्कुल सही है। व्यावसायिक नियम एक स्रोत से, और एक बार केवल स्रोत से आने चाहिए। इसका मतलब यह है कि मानव संसाधन, संचालन और आईटी सभी को एक "एकल जिम्मेदारी" में तैयार करने की आवश्यकताओं को सहयोग करने की आवश्यकता है। और वह सिद्धांत है। +1
बेनी स्कोबर्गबर्ग

2

एक अच्छा लेख जो SOLID प्रोग्रामिंग सिद्धांतों की व्याख्या करता है और इस सिद्धांत का पालन करने और न करने दोनों के लिए कोड के उदाहरण देता है https://scotch.io/bar-talk/solid-the-first-five-principles-of-object-ediented- डिजाइन

एसआरपी से संबंधित उदाहरण में वह कुछ आकार वर्गों (वृत्त और वर्ग) का उदाहरण देता है और एक वर्ग जिसे कई आकारों के कुल क्षेत्रफल की गणना करने के लिए डिज़ाइन किया गया है।

अपने पहले उदाहरण में वह क्षेत्र की गणना करने वाला वर्ग बनाता है और इसे HTML के रूप में अपना आउटपुट देता है। बाद में उन्होंने फैसला किया कि वह इसे JSON के रूप में प्रदर्शित करना चाहते हैं और उन्हें अपने क्षेत्र की गणना करने वाले वर्ग को बदलना होगा।

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

यह एक सरल उदाहरण है (और लेख को आसानी से समझा जा सकता है क्योंकि इसमें कोड स्निपेट हैं) लेकिन एसआरपी के मूल विचार को प्रदर्शित करता है।


0

सबसे पहले, जो आपके पास है वह वास्तव में दो अलग-अलग समस्याएं हैं: आपकी कक्षाओं में किन तरीकों को रखा जाए, और इंटरफ़ेस ब्लोट की समस्या।

इंटरफेस

आपके पास यह इंटरफ़ेस है:

public Interface CustomerCRUD
{
  public void Create(Customer customer);
  public Customer Read(int CustomerID);
  public void Update(Customer customer);
  public void Delete(int CustomerID);
}

मुमकिन है, आपके पास कई वर्ग हैं जो CustomerCRUDइंटरफ़ेस के अनुरूप हैं (अन्यथा एक इंटरफ़ेस अनावश्यक है), और कुछ फ़ंक्शन do_crud(customer: CustomerCRUD)जो एक अनुरूप वस्तु में लेता है। लेकिन आपने एसआरपी को पहले ही तोड़ दिया है: आपने इन चार अलग-अलग ऑपरेशनों को एक साथ जोड़ दिया है।

मान लीजिए कि बाद में आपको डेटाबेस दृश्य पर काम करना होगा। एक डेटाबेस दृश्य है केवलRead विधि इसके लिए उपलब्ध। लेकिन आप एक ऐसा फंक्शन लिखना चाहते हैं, do_query_stuff(customer: ???)जो ऑपरेटर्स पूरी तरह से टेबुल टेबल या व्यूज पर ट्रांसपेरेंट हों; यह केवल Readविधि का उपयोग करता है , सब के बाद।

इसलिए एक इंटरफ़ेस बनाएं

सार्वजनिक इंटरफ़ेस CustomerReader {सार्वजनिक ग्राहक पढ़ें (customerID: int)}

और अपना CustomerCrudइंटरफ़ेस फ़ैक्टर करें :

public interface CustomerCRUD extends CustomerReader
{
  public void Create(Customer customer);
  public void Update(Customer customer);
  public void Delete(int CustomerID);
}

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

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

let do_customer_stuff customer = customer.read ... customer.update ...

जो भी तरीके हमें पसंद हैं, कहता है। OCaml यह निर्धारित करने के लिए कि हम इन विधियों को लागू करने वाले किसी भी ऑब्जेक्ट में पारित कर सकते हैं, प्रकार का उपयोग करेगा। इस उदाहरण में, यह निर्धारित किया जाएगा कि customerप्रकार है <read: int -> unit, update: int -> unit, ...>

कक्षाएं

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


4
"अर्थहीन" थोड़ा मजबूत है। मैं "रहस्यमय" या "ज़ेन" के पीछे पड़ सकता हूं। लेकिन, फ्लैट-आउट व्यर्थ नहीं!
svidgen

क्या आप थोड़ा और समझा सकते हैं कि संरचनात्मक सबटाइपिंग एक समाधान क्यों है?
रॉबर्ट हार्वे


4
मैं इंटरफेस का उपयोग तब भी करता हूं जब मेरे पास इसे लागू करने वाला केवल एक वर्ग होता है। क्यों? यूनिट-परीक्षणों में नकली।
Eternal21

0

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

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


0

यह हासिल करना है कि कई आवश्यकताएं बदलती हैं, आपके घटक को बदलने की आवश्यकता नहीं है

लेकिन सौभाग्य यह है कि पहली नज़र में, जब आप पहली बार SOLID के बारे में सुनते हैं।


मैं बहुत सारी टिप्पणियां देख रहा हूं जिसमें कहा गया है कि SRP और YAGNI एक-दूसरे का विरोधाभास कर सकते हैं, लेकिन TDD (GOOS, लंदन स्कूल) द्वारा लागू किए गए YAGN ने मुझे अपने घटकों को एक ग्राहक के दृष्टिकोण से सोचने और डिजाइन करने के लिए सिखाया। मैंने अपने इंटरफेस को डिजाइन करना शुरू कर दिया है कि कोई भी ग्राहक यह करना चाहेगा कि यह कितना कम होना चाहिए । और उस अभ्यास को टीडीडी के किसी भी ज्ञान के बिना किया जा सकता है।

मुझे चाचा बॉब द्वारा बताई गई तकनीक पसंद है (मुझे दुःख की बात नहीं है कि वह कहां से याद कर सकता है), जो कुछ इस तरह है:

अपने आप से पूछें, यह वर्ग क्या करता है?

अपने जवाब में से किसी को शामिल किया था और या या

यदि हां, तो उत्तर के उस हिस्से को निकालें, यह स्वयं की जिम्मेदारी है

यह तकनीक एक निरपेक्ष है, और जैसा कि @svidgen ने कहा, SRP एक निर्णय कॉल है, लेकिन जब कुछ नया सीखना, निरपेक्षता सबसे अच्छी होती है, तो बस कुछ करना हमेशा आसान होता है। सुनिश्चित करें कि आप जो कारण अलग नहीं करते हैं; एक शिक्षित अनुमान, और नहीं क्योंकि आप नहीं जानते कि कैसे। यह कला है, और यह अनुभव लेती है।


मुझे लगता है कि एसआरपी के बारे में बात करने पर बहुत सारे उत्तर डिकम्प्लिंग के लिए तर्क देने लगते हैं ।

SRP यह सुनिश्चित करने के लिए नहीं है कि कोई परिवर्तन निर्भरता ग्राफ को नीचे नहीं फैलाता है।

सैद्धांतिक रूप से, एसआरपी के बिना , आपके पास कोई निर्भरता नहीं होगी ...

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

इसलिए जब SOLID को समग्र रूप से पढ़ाते हैं, तो यह पढ़ाने के लिए सावधान रहें कि SRP आपको आवश्यकता के अनुसार कम कोड बदलने की अनुमति देता है , जब वास्तव में, यह आपको कम नया कोड लिखने की अनुमति देता है ।


3
When learning something new, absolutes are the best, it is easier to just always do something.- मेरे अनुभव में, नए प्रोग्रामर बहुत अधिक हठधर्मी हैं। निरपेक्षता गैर-विचारशील डेवलपर्स और कार्गो-पंथ प्रोग्रामिंग के लिए नेतृत्व करती है। "बस ऐसा करो" कहना ठीक है, इसलिए जब तक आप समझते हैं कि आप जिस व्यक्ति से बात कर रहे हैं, उसे बाद में अनजान होना पड़ेगा कि आपने उन्हें क्या सिखाया है।
रॉबर्ट हार्वे

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

@RobertHarvey, एक त्वरित वास्तविक जीवन उदाहरण: आप अपने बच्चों को हमेशा ईमानदार होना सिखा सकते हैं , लेकिन जैसे-जैसे वे बड़े होते जाते हैं, उन्हें शायद कुछ अपवादों का एहसास होगा जहां लोग अपने सबसे ईमानदार विचारों को नहीं सुनना चाहते हैं। एक 5 साल की उम्र के लिए एक सही निर्णय लेने की उम्मीद करना ईमानदार होने के बारे में सबसे अच्छा है। :)
क्रिस वोहलर्ट

0

इसका कोई स्पष्ट उत्तर नहीं है। यद्यपि यह प्रश्न संकीर्ण है, स्पष्टीकरण नहीं हैं।

मेरे लिए, यह कुछ ऐसा है जैसे ओसम का रेजर अगर आप चाहते हैं। यह एक आदर्श है जहां मैं अपने वर्तमान कोड को मापने की कोशिश करता हूं। इसे सरल और सरल शब्दों में नीचे करना मुश्किल है। एक और रूपक होगा »एक विषय« जो सार के रूप में है, अर्थात कठिन है, जैसा कि "एकल जिम्मेदारी" है। एक तीसरा विवरणक »अमूर्त के एक स्तर के साथ काम करना होगा«।

व्यावहारिक रूप से इसका क्या अर्थ है?

हाल ही में मैं कोडिंग की एक शैली का उपयोग करता हूं जिसमें अधिकतर दो चरण होते हैं:

चरण I को रचनात्मक अराजकता के रूप में वर्णित किया गया है। इस चरण में मैं कोड लिखता हूं क्योंकि विचार प्रवाहित होते हैं - यानी कच्चे और बदसूरत।

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

मैं अब ज्यादातर पायथन में काम कर रहा हूं, जो मुझे बाद में वस्तुओं और कक्षाओं के बारे में सोचने की अनुमति देता है। प्रथम चरण I - मैं केवल फ़ंक्शन लिखता हूं और उन्हें विभिन्न मॉड्यूलों में यादृच्छिक रूप से फैलाता हूं। में द्वितीय चरण , के बाद मैं जा रहा चीजें मिल गया, मैं क्या मॉड्यूल सौदों जो समाधान का हिस्सा के साथ पर गहन चर्चा की है। और मॉड्यूल के माध्यम से स्किमिंग करते समय, मेरे लिए विषय उभर रहे हैं। कुछ फ़ंक्शन थीम से संबंधित हैं। ये कक्षाओं के अच्छे उम्मीदवार हैं । और मैंने कक्षाओं में कार्य करने के बाद - जो लगभग इंडेंटेशन के साथ किया है और selfपायथॉन में पैरामीटर सूची में जोड़ रहा है;) - मैं SRPअन्य मॉड्यूल और कक्षाओं के लिए कार्यक्षमता को बाहर निकालने के लिए ओक्टम के रेजर की तरह उपयोग करता हूं ।

एक वर्तमान उदाहरण दूसरे दिन छोटी निर्यात कार्यक्षमता लिख सकता है ।

एक ज़िप में csv , एक्सेल और संयुक्त एक्सेल शीट की आवश्यकता थी ।

सादा कार्यक्षमता प्रत्येक को तीन दृश्यों (= कार्यों) में किया गया था । प्रत्येक फ़ंक्शन ने फ़िल्टर को निर्धारित करने के लिए एक सामान्य विधि और डेटा को पुनः प्राप्त करने के लिए एक दूसरी विधि का उपयोग किया। फिर प्रत्येक फ़ंक्शन में निर्यात की तैयारी हुई और सर्वर से प्रतिक्रिया के रूप में वितरित की गई।

अमूर्त के कई स्तर मिश्रित थे:

आई) आने वाले / बाहर जाने वाले अनुरोध / प्रतिक्रिया से निपटना

II) फिल्टर का निर्धारण

III) डेटा पुनर्प्राप्त करना

IV) डेटा का रूपांतरण

exporterपहले चरण में II-IV परतों से निपटने के लिए आसान कदम एक अमूर्त ( ) का उपयोग करना था ।

केवल अवशेष अनुरोधों / प्रतिक्रियाओं से निपटने वाला विषय था । अमूर्त के एक ही स्तर पर अनुरोध पैरामीटर निकाल रहा है जो ठीक है। इसलिए मुझे इस एक "जिम्मेदारी" को देखना था ।

दूसरा, मुझे निर्यातक को तोड़ना था, जैसा कि हमने देखा कि अमूर्त की कम से कम तीन अन्य परतें शामिल थीं।

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

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

वर्गों और मॉड्यूलों के गठन के साथ, चीजें स्पष्ट हो गईं कि क्या कहां हैं। और हमेशा अव्यक्त प्रश्न, क्या वर्ग बहुत अधिक करता है

आप यह निर्धारित करते हैं कि प्रत्येक वर्ग के लिए कौन सी ज़िम्मेदारियाँ होनी चाहिए, और आप SRP के संदर्भ में एक ज़िम्मेदारी कैसे निर्धारित करते हैं?

इसका पालन करने के लिए एक नुस्खा देना कठिन है। अगर मैं मदद करता है तो निश्चित रूप से मैं गूढ़ »स्तर के« - नियम को दोहरा सकता था।

ज्यादातर मेरे लिए यह एक तरह का "कलात्मक अंतर्ज्ञान" है जो वर्तमान डिजाइन की ओर जाता है; मैं एक मॉडल कोड की तरह एक कलाकार मिट्टी की मूर्ति बना सकता हूं या पेंटिंग कर सकता हूं।

मुझे एक कोडिंग बॉब रॉस के रूप में कल्पना करो ;)


0

मैं SRP के बाद आने वाले कोड को लिखने के लिए क्या करने की कोशिश करता हूं:

  • एक विशिष्ट समस्या चुनें जिसे आपको हल करने की आवश्यकता है;
  • कोड लिखें जो इसे हल करता है, सब कुछ एक विधि में लिखें (जैसे: मुख्य);
  • कोड का सावधानीपूर्वक विश्लेषण करें और व्यवसाय के आधार पर, उन जिम्मेदारियों को परिभाषित करने का प्रयास करें जो सभी कार्यों में दिखाई दे रहे हैं (यह व्यक्तिपरक हिस्सा है जो व्यवसाय / परियोजना / ग्राहक पर भी निर्भर करता है);
  • कृपया, ध्यान दें कि सभी कार्यक्षमता पहले से ही लागू है; आगे क्या केवल कोड का संगठन है (इस दृष्टिकोण में अब से कोई अतिरिक्त सुविधा या तंत्र लागू नहीं किया जाएगा);
  • उन जिम्मेदारियों के आधार पर जिन्हें आपने पिछले चरणों में परिभाषित किया था (जो कि व्यवसाय और "विचार बदलने का एक कारण) के आधार पर परिभाषित किया गया है", प्रत्येक के लिए एक अलग वर्ग या विधि निकालें;
  • कृपया ध्यान दें कि यह दृष्टिकोण केवल SPR के बारे में परवाह करता है; आदर्श रूप में अन्य सिद्धांतों का पालन करने के लिए यहां अतिरिक्त कदम होना चाहिए।

उदाहरण:

समस्या: उपयोगकर्ता से दो नंबर प्राप्त करें, उनकी राशि की गणना करें और उपयोगकर्ता को परिणाम दें:

//first step: solve the problem right away
static void Main(string[] args)
{
    Console.WriteLine("Number 1: ");
    int firstNumber = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("Number 2: ");
    int secondNumber = Convert.ToInt32(Console.ReadLine());

    int result = firstNumber + secondNumber;

    Console.WriteLine("Hi there! The result is: {0}", result);

    Console.ReadLine();
}

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

//Responsible for getting two integers from the user
class Input {
    public int FirstNumber { get; set; }
    public int SecondNumber { get; set; }
    public void Read() {
        Console.WriteLine("Number 1: ");
        FirstNumber = Convert.ToInt32(Console.ReadLine());

        Console.WriteLine("Number 2: ");
        SecondNumber = Convert.ToInt32(Console.ReadLine());
    }
}

//Responsible for calculating the sum of two integers
class SumOperation {
    public int Result { get; set; }
    public void Calculate(int a, int b) {
        Result = a + b;
    }
}

//Responsible for the output of some value to the user
class Output {
    public void Write(int result) {
        Console.WriteLine("Hello! The result is: {0}", result);
    }
}

फिर, रिफलेक्टेड प्रोग्राम बन जाता है:

//Program: responsible for main execution.
//Gets two numbers from user and output their sum.
static void Main(string[] args)
{
    var input = new Input();
    input.Read();

    var operation = new SumOperation();
    operation.Calculate(input.FirstNumber, input.SecondNumber);

    var output = new Output();
    output.Write(operation.Result);

    Console.ReadLine();
}

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


1
आपका उदाहरण एसआरपी को पर्याप्त रूप से स्पष्ट करने के लिए बहुत सरल है। वास्तविक जीवन में कोई भी ऐसा नहीं करेगा।
रॉबर्ट हार्वे

हां, वास्तविक परियोजनाओं में मैं अपने उदाहरण में सटीक कोड लिखने के बजाय कुछ छद्मकोड लिखता हूं। स्यूडोकोड के बाद, मैं उन जिम्मेदारियों को विभाजित करने की कोशिश करता हूं जैसे मैंने उदाहरण में किया था। वैसे भी, बस यही है कि मैं यह कैसे करते हैं।
एमर्सन कार्डसो

0

रॉबर्ट सी। मार्टिंस की पुस्तक क्लीन आर्किटेक्चर: ए क्राफ्ट्समैन की गाइड टू सॉफ्टवेयर स्ट्रक्चर एंड डिजाइन , 10 सितंबर 2017 को प्रकाशित, रॉबर्ट पेज 62 पर निम्नलिखित लिखते हैं:

ऐतिहासिक रूप से, SRP को इस तरह वर्णित किया गया है:

एक मॉड्यूल में एक, और केवल एक होना चाहिए, बदलने का कारण

सॉफ्टवेयर सिस्टम को उपयोगकर्ताओं और हितधारकों को संतुष्ट करने के लिए बदल दिया जाता है; उन उपयोगकर्ताओं और हितधारकों को "बदलने का कारण" है। उस सिद्धांत की बात हो रही है। वास्तव में, हम यह कहने के लिए सिद्धांत को दोहरा सकते हैं:

एक मॉड्यूल एक, और केवल एक, उपयोगकर्ता या हितधारक के लिए जिम्मेदार होना चाहिए

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

इस प्रकार एसआरपी का अंतिम संस्करण है:

एक मॉड्यूल एक, और केवल एक, अभिनेता के लिए जिम्मेदार होना चाहिए।

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


मुझे यकीन नहीं है कि आप भेद क्यों कर रहे हैं कि "यह कोड के बारे में नहीं है।" बेशक यह कोड के बारे में है; यह सॉफ्टवेयर डेवलपमेंट है।
रॉबर्ट हार्वे

@RobertHarvey मेरा कहना है कि आवश्यकताओं का प्रवाह एक स्रोत से आता है, अभिनेता। उपयोगकर्ता और हितधारक कोड में नहीं हैं, वे व्यावसायिक नियमों में हैं जो आवश्यकताओं के रूप में हमारे पास आते हैं। इसलिए एसआरपी इन आवश्यकताओं को नियंत्रित करने की एक प्रक्रिया है, जो मेरे लिए कोड नहीं है। यह सॉफ्टवेयर डेवलपमेंट (!) है, लेकिन कोड नहीं।
बजे बेनी स्कोबर्गबर्ग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.