क्या शुद्ध कार्यों को गैर-सार्वजनिक करने का एक अच्छा कारण है?


25

मेरी एक सहकर्मी के साथ थोड़ी बहस चल रही थी। सीधे शब्दों में कहें, क्या शुद्ध होने वाले कार्यों को छिपाने / अतिक्रमण करने का एक अच्छा कारण है?

"शुद्ध" से मेरा मतलब है विकिपीडिया परिभाषा :

  • हमेशा एक ही इनपुट से एक ही परिणाम देता है। (इस चर्चा के Foo Create(){ return new Foo(); }लिए मान को अपवित्र Fooनहीं माना जाता है ।)
  • पारस्परिक स्थिति (स्थानीय चर को छोड़कर) या I / O का उपयोग नहीं करता है।
  • साइड इफेक्ट का उत्पादन नहीं करता है।

26
ऐसा तर्क दिया जा सकता है कि इस तरह के समारोह को किसी वर्ग का सदस्य नहीं बनाया जाए।
पीटर बी

6
@PieterB - वास्तव में, हालांकि सभी भाषाएं इसका समर्थन नहीं करती हैं, और कुछ भाषाएं मुफ्त कार्यों के लिए भी मॉड्यूल को आंतरिक अनुमति देती हैं।
15

3
आपकी क्या राय थी? मुझे नहीं लगता है कि फ़ंक्शन की शुद्धता सार्वजनिक एपीआई से संबंधित है या नहीं।
एंड्रेस एफ।

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

2
@Telastyn यदि यह पुन: प्रयोज्य है, लेकिन वर्तमान वर्ग की जिम्मेदारी का हिस्सा नहीं है, तो यह संभवतः एक अलग वर्ग / मॉड्यूल / जो कुछ भी आपकी-भाषा है, में होना चाहिए। फिर नए वर्ग / मॉड्यूल की जिम्मेदारी का हिस्सा होने के नाते, यह आवश्यक रूप से सार्वजनिक किया जाएगा। चूंकि आप परीक्षण का उल्लेख करते हैं, इसलिए मैं ध्यान दूंगा कि जब आप ऐसा करते हैं तो जरूरी नहीं कि आपको विधि का मजाक ही बनाना पड़े। "कार्यान्वयन विवरण" के रूप में, परीक्षणों के दौरान इसका मजाक उड़ाने से बहुत कम लाभ मिलता है।
jpmc26

जवाबों:


76

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


33
+1। आपकी कक्षा के सार्वजनिक सदस्य इसके एपीआई हैं। यह सवाल नहीं है कि "क्या यह सार्वजनिक है अगर यह मुझे चोट पहुंचा सकता है?", बल्कि "क्या यह एपीआई का हिस्सा होना चाहिए?"
साधारण

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

1
मैं सार्वजनिक कक्षाओं को सील कर दूंगा जो कि विस्तारित होने के लिए नहीं हैं।
डेन

+1 यह इंगित करने के लिए कि एक फ़ंक्शन (या वर्ग) को छिपाना या दिखाना एक एपीआई की रक्षा और बनाए रखने के मुख्य रूप से प्रश्न हैं, और कोड के प्रकार से संबंधित नहीं है।
मार्को

42

सवाल पीछे की तरफ है।

आप किसी फ़ंक्शन को गैर-सार्वजनिक करने के लिए किसी कारण की तलाश नहीं करते हैं। यह (मेरी राय में) के साथ शुरू करने के लिए एक गलत मानसिकता है। तर्क को दूसरे रास्ते पर जाना चाहिए।

दूसरे शब्दों में - "मैं इसे निजी क्यों बनाऊंगा?" मत पूछो। पूछें: "मैं इसे सार्वजनिक क्यों करूंगा?"

जब संदेह हो, तो उसे उजागर न करें। यह ओखम के रेजर की तरह है - आवश्यकता से अधिक गुणा नहीं करता है।

संपादित करें: टिप्पणियों में @Telastyn द्वारा लाए गए प्रतिवादों को संबोधित करना (वहां विस्तारित चर्चा से बचने के लिए):

मैंने सुना है कि समय के साथ, और यहां तक ​​कि काफी समय तक इसकी जासूसी की, लेकिन मेरे अनुभव में, चीजें बहुत निजी होती हैं।

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

लेकिन protectedपर्याप्त होगा - और यह अभी भी गैर-सार्वजनिक है।

यह बहुत सी कोड डुप्लीकेशन और ओवरहेड की ओर जाता है जो "उन चीजों को प्राप्त करने के लिए है जो सार्वजनिक नहीं होनी चाहिए" अभी तक अप्रत्यक्ष रूप से किसी भी तरह से एक्सेस की जाती हैं।

यदि यह समस्याग्रस्त हो जाता है, तो बस इसे सार्वजनिक करें! आवश्यकता है कि मैं किस बारे में बात कर रहा था :)

मेरा कहना यह है कि आपको इसे केवल मामले में नहीं करना चाहिए (YAGNI और सभी)।

ध्यान दें कि निजता को वापस खींचकर निजी फ़ंक्शन को सार्वजनिक करना हमेशा आसान होता है। उत्तरार्द्ध मौजूदा कोड को तोड़ने की संभावना है।


मैंने सुना है कि समय के साथ, और यहां तक ​​कि काफी समय तक इसकी जासूसी की, लेकिन मेरे अनुभव में, चीजें बहुत निजी होती हैं। यह बहुत सी कोड डुप्लीकेशन और ओवरहेड की ओर जाता है जो "उन चीजों को प्राप्त करने के लिए है जो सार्वजनिक नहीं होनी चाहिए" अभी तक अप्रत्यक्ष रूप से किसी भी तरह से एक्सेस की जाती हैं।
तेलस्टिन

3
@ टेलस्टाइन IMHO, जो लगता है कि एप्लिकेशन कुछ डिज़ाइन मिसस्टेप्स से ग्रस्त है; यदि आप अपने आप को एक विधि को उजागर करने के लिए इच्छुक पाते हैं, क्योंकि आपको इसे असतत कोड रास्तों पर लागू करने की आवश्यकता है, तो यह संभवतः एक संकेत है कि इस विधि को अपने स्वयं के मॉड्यूल में तोड़ दिया जाना चाहिए जो कि इंजेक्ट किया जा सकता है या जहां उपयुक्त हो, विशेष रूप से यदि यह एक शुद्ध कार्य है ।
लेओ

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

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

@ टेलस्टाइन राइट। मेरा क्या मतलब है, अगर आपकी 'पूर्णांक विधि' विधि एक सार्वजनिक विधि के एन्कैप्सुलेटेड कार्यान्वयन विवरण के रूप में शुरू हुई है, लेकिन आप पाते हैं कि आपको अन्य स्थानों पर निजी पद्धति को लागू करने की आवश्यकता है, तो शायद यह संकेत है कि निजी पद्धति एक अलग तरीके से है मॉड्यूल / पैकेज / वर्ग ताकि इसे तर्क के स्वतंत्र रूप से आयात किया जा सके जो इसे लागू करता है। बस विधि को सार्वजनिक करने के रूप में इसका मतलब यह होगा कि विधि मनमाने ढंग से पहले मॉड्यूल में स्थित है जहां आपको यह उपयोगी लगा।
leo

6

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


5

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

यहाँ एक मामले में जहां दृश्यता का केवल एक उदाहरण है सकता है एक समस्या का कारण।

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

चूंकि यह एक शुद्ध कार्य है (स्ट्रिंग में आता है, इसे किसी तरह से बदलना, एक नया स्ट्रिंग लौटना), यह परिणाम के बिना सार्वजनिक या निजी हो सकता है। या कर सकता था?

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

फ़ंक्शन को निजी रखने से, किसी को कभी भी कोड पर भरोसा करने का अवसर नहीं मिलता है जो कक्षा की एकल जिम्मेदारी का हिस्सा नहीं है।


2
मैं यह तर्क दूंगा कि इसमें केवल ऐसे कार्य शामिल होने चाहिए जो इसकी एकल जिम्मेदारी का हिस्सा हैं, न कि केवल उजागर।
तेलस्टिन

1
मुझे लगता है कि एक ग्रे क्षेत्र है। क्या आपको वास्तव StringTransformerमें कोड की दो या तीन पंक्तियों को अलग करने के लिए एक अलग वर्ग की आवश्यकता है जो केवल एक ही स्थान पर उपयोग किए जाते हैं? मैं मानता हूं कि एक बार कोड का उपयोग कई स्थानों पर करने के बाद इसे एक जिम्मेदारी के साथ एक नए वर्ग में अलग करना सबसे अच्छा होता है, लेकिन एक व्यापार है।

निश्चित रूप से। दिशानिर्देश दिशानिर्देश हैं, नियम नहीं।
तेलस्टाइन

@ गैर जावा में आप केवल कार्यों का एक पुस्तकालय बनाते हैं।
पीटर बी।

@ पीटर यह जावा के बारे में नहीं है। वी कुछ और। इसे सही मायने में OO बनाने के लिए आपको एक फैक्ट्री, कुछ अमूर्त वर्गों आदि की आवश्यकता होगी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.