क्या ओपन / बंद सिद्धांत का एक उदाहरण है?


12

विकिपीडिया कहता है

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

शब्द कार्यों ने मेरी आंखों को पकड़ लिया, और मुझे अब आश्चर्य होता है कि क्या हम यह मान सकते हैं कि किसी विधि के लिए अधिभार बनाना ओपन / बंद सिद्धांत का एक उदाहरण माना जा सकता है या नहीं?

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

bool IsAdmin(userId)

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

public bool IsAdmin(string username)
{
    int userId = UserManager.GetUser(username).Id;
    return IsAdmin(userId);
}

इस तरह, हमने इसके लिए एक अधिभार बनाने के माध्यम से अपने कार्य को बढ़ाया है (कार्य विस्तार के लिए खुला होना चाहिए)।

क्या यह एक खुला / बंद सिद्धांत उदाहरण है?

जवाबों:


5

मैं व्यक्तिगत रूप से विकी कथन की व्याख्या इस प्रकार करूंगा:

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

पैर में शॉट हालांकि यह है कि यदि आपका कोड 'cUserInfo' वर्ग का उपयोग कर रहा है, जिसमें IsAdmin (int) रहता है, तो आप अनिवार्य रूप से नियम को तोड़ रहे हैं और कक्षा को बदल रहे हैं। यदि आप एक नया वर्ग cUserWithNameInfo: सार्वजनिक cUserInfo वर्ग बनाते हैं और अपना IsAdmin (स्ट्रिंग) ओवरराइड वहां डालते हैं, तो नियम केवल दुख की बात होगा। अगर मेरे पास कोड आधार है तो मैं कभी भी नियम नहीं मानूंगा। मैं कहता हूं कि बोललॉक और आप जो भी सुझाव दें, उसे बदल दें।


3

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

public bool IsAdmin(int userid)
{
    User user = UserManager.GetUser(userid);
    return user.IsAdmin();
}

public bool IsAdmin(string username)
{
    int userId = UserManager.GetUser(username).Id;
    return IsAdmin(userId);
}

आपको वास्तव में उस वर्ग का विस्तार करना चाहिए ।

public bool IsAdmin(int userid)
{
    User user = UserManager.GetUserById(userid);
    return user.IsAdmin();
}

public bool IsUsernameAdmin(string username)
{
    User userId = UserManager.GetUserByName(username);
    return user.IsAdmin();
}

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

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

जैसा कि अंकल बॉब कहते हैं (मेरा जोर दें):

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


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

@SaeedNeamati: मैं जो बिंदु बना रहा था, वह यह नहीं है कि अगर आप एक ऐसी विधि जोड़ रहे हैं जो मौजूदा पद्धति का उपयोग कर रही है या ऐसी विधि जोड़ रही है जो पूरी तरह से स्वतंत्र हो, तो या तो आपकी कक्षा का विस्तार करने के लिए खुला था। लेकिन, यदि आपको इसे प्राप्त करने के लिए मौजूदा विधि इंटरफ़ेस को संशोधित करना था, तो आप संशोधन के लिए बंद नहीं होंगे।
पीडीआर

2

खुले-बंद सिद्धांत के अनुरूप मॉड्यूल में दो प्राथमिक गुण होते हैं।

  1. वे "एक्सटेंशन के लिए ओपन" हैं। इसका मतलब है कि मॉड्यूल के व्यवहार को बढ़ाया जा सकता है। कि हम मॉड्यूल को नए और अलग-अलग तरीकों से व्यवहार में परिवर्तन कर सकते हैं जैसे कि अनुप्रयोग परिवर्तन की आवश्यकताएं, या नए अनुप्रयोगों की आवश्यकताओं को पूरा करने के लिए।
  2. वे “मोदी के लिए बंद” हैं। इस तरह के एक मॉड्यूल का स्रोत कोड इनवॉयलेट है। किसी को भी स्रोत कोड परिवर्तन करने की अनुमति नहीं है।
  1. अपनी पद्धति को ओवरलोड करके आप मौजूदा मॉड्यूल की कार्यक्षमता का विस्तार कर रहे हैं, इस प्रकार आपके एप्लिकेशन की नई जरूरतों को पूरा कर रहे हैं

  2. आप किसी मौजूदा पद्धति में कोई बदलाव नहीं कर रहे हैं, इसलिए आप दूसरे नियम का उल्लंघन नहीं कर रहे हैं।

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

रेफरी: http://www.objectmentor.com/resources/articles/ocp.pdf


1

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

लेकिन मान लीजिए कि आपके पास एक फ़ंक्शन था जिसे कॉल किया गया था BigContrivedMethod(int1, int2, string1)BigContrivedMethodतीन चीजें करता है: thing1, thing2 और thing3 इस बिंदु पर, बीसीएम का पुन: उपयोग करना शायद कठिन है, क्योंकि यह बहुत अधिक करता है। यह पुनर्रचना (यदि संभव हो) में ContrivedFunction1(int), ContrivedFunction2(int)है, और ContrivedFunction3(string)आप तीन छोटे, अधिक केंद्रित तरीकों देता है कि आप और अधिक आसानी से जोड़ सकते हैं।

और यह तरीकों / कार्यों के संबंध में OCP की कुंजी है: रचना। आप अन्य कार्यों से उन्हें कॉल करके "विस्तार" कार्य करते हैं।

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


मुझे लगता है कि आप यहां सिंगल रिस्पांसिबिलिटी प्रिंसिपल की बात करते हैं, OCP की नहीं।
सईद नेमाटी

1
मैं कह रहा हूं कि आप वास्तविक रूप से एसआरपी के बिना ओसीपी नहीं कर सकते। कोड जो बहुत अधिक है, उसे बढ़ाया नहीं जा सकता है, उसका पुन: उपयोग नहीं किया जा सकता है। एसओएलआईडी लगभग महत्व के क्रम में लिखा गया है, प्रत्येक सिद्धांत के लिए संभव होने से पहले लोगों पर निर्भर है।
कोडेक्सअर्बनम

इस उत्तर को और बढ़ा दिया जाना चाहिए।
आशीष गुप्ता

0

आप खुले-बंद सिद्धांत का पालन कर रहे हैं यदि आप पुराने कोड को बदलने के बजाय नए कोड लिखकर अपने कार्यक्रम के व्यवहार को बदल रहे हैं।

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

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

तो, यह आपके मामले में कैसे लागू होता है:

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

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

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