2009-09-29 10 views
6

प्रभावी सी ++ राज्यों के आइटम 23 के बारे में प्रश्न: सदस्य कार्यों के लिए गैर-सदस्य गैर-मित्र कार्यों को प्राथमिकता दें।Encapsulation का "शिखर" - प्रभावशाली सी ++

आइटम का पूरा उद्देश्य encapsulation को प्रोत्साहित करना था, साथ ही साथ पैकेज लचीलापन और कार्यात्मक विस्तारशीलता, लेकिन मेरा सवाल यह है कि यह सलाह लेने के लिए आप कितनी दूर जाते हैं?

उदाहरण के लिए, आप अपनी कक्षा, अपने निजी डेटा सदस्यों को प्राप्त कर सकते हैं, और फिर अपने निजी डेटा सदस्यों के लिए केवल एक्सेसर्स और/या म्यूटेटर को सार्वजनिक कार्यों को कम करके कम से कम दृष्टिकोण ले सकते हैं। फिर, हर एक अन्य समारोह एक गैर-सदस्य समारोह हो सकता है।

हालांकि, क्या आप जगह पर एक्सेसर्स और म्यूटेटर के साथ कोड स्पष्टता के संभावित बलिदान पर encapsulation बढ़ाने के इच्छुक होंगे? रेखा कहां खींची गई है?

+4

उन लोगों के लिए प्रभावी सी ++ की प्रतिलिपि के बिना, मेयर्स http://www.ddj.com/cpp/184401197 पर एक समान तर्क प्रस्तुत करते हैं। –

उत्तर

9

सबसे पहले, हर कोई इस सलाह से सहमत नहीं है। मुझे नहीं लगता कि मैंने किसी को भी देखा है लेकिन मेयर्स (संपादित करें: और Herb Sutter) यह सलाह दें, और मैंने इसे केवल सी ++ के संदर्भ में देखा है।उदाहरण के लिए, जावा या सी # में "गैर-सदस्य गैर-मित्र फ़ंक्शंस" बनाना वास्तव में संभव नहीं है, क्योंकि जावा और सी # में कोई नि: शुल्क फ़ंक्शन नहीं है, और रूबी डेवलपर्स (उदाहरण के लिए) "humane interfaces" पसंद करते हैं जो जानबूझकर सदस्य फ़ंक्शन बनाते हैं जो समान करते हैं चीजें गैर-सदस्य, केवल उन कार्यों के कॉलर्स पर जीवन को आसान बनाने के लिए कर सकती हैं।

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

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

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

+2

हर्ब सटर मेयर्स के साथ सहमत है, और एक बेहतर उदाहरण प्रदान करता है: http://www.gotw.ca/gotw/084.htm –

+0

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

+0

अलेक्जेंडर स्टेपानोव सदस्य कार्य कार्यों में मित्र कार्यों की अनुशंसा करने के लिए अब तक गैर-सदस्यीय कार्यों को पसंद करते हैं। –

0

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

+1

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

3

एक कदम पीछे ले लो और वर्ग के उद्देश्य पर विचार करें: क्या एक काम कर रहा है? यह वर्ग नौकरी को यह सुनिश्चित करना चाहिए कि वह एक नौकरी बेहतर तरीके से करे? कक्षा के उद्देश्य में उप-वर्ग और ओवरराइडिंग की भूमिका क्या भूमिका निभाती है?

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

कक्षा एक विशेष मामले हैं - शायद एक कदम ऊपर पारंपरिक सी-तरह struct s से कुछ अपरिवर्तनशीलताओं की रक्षा करने में सक्षम होने के द्वारा, लेकिन "अभी मुश्किल से" ;-)।

एक अच्छा OOP डिजाइन में

अधिकांश कक्षाएं व्यवहार होगा - और भी बहुत कुछ के रूप में मैं सामान्य प्रोग्रामिंग की तरह, सी ++ उपयोग करने के लिए एक कारण कई मानदंड, जो बीच में OOP मिटाई गई नहीं किया जाना चाहिए की अपनी मजबूत मिश्रण है -!)

2

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

इस दृष्टिकोण के बाद भविष्य में अंतर्निहित कार्यान्वयन को बदलना आसान है, जो पहले स्थान पर encapsulation का बिंदु है।

0

सही आकार की इकाइयों में चीजों को पैकेज करने के तरीके पर कार्य करना एक व्यक्तिपरक कला है।

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

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

एफिल के बारे में उन अच्छी चीजों में से एक, कोई पैरामीटर वाले विधि को वैरिएबल के समान तरीके से एक्सेस किया जाता है, और इसलिए उन तत्वों के बीच बदलना पारदर्शी है।

संबंधित मुद्दे