कम से कम विस्मय का सिद्धांत (POLA) और इंटरफेस


17

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

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

कीचड़ के रूप में स्पष्ट है?

इन विधियों के साथ एक इंटरफ़ेस पर विचार करें (डेटा फ़ाइलों को बनाने के लिए):

OpenFile
SetHeaderString
WriteDataLine
SetTrailerString
CloseFile

अब आप निश्चित रूप से क्रम में इन के माध्यम से जा सकते हैं, लेकिन कहते हैं कि आपने फ़ाइल नाम (विचार a.out) या हेडर और ट्रेलर स्ट्रिंग के बारे में परवाह नहीं की , आप बस कॉल कर सकते हैं AddDataLine

एक कम चरम उदाहरण हेडर और ट्रेलर को छोड़ सकता है।

फ़ाइल खोलने से पहले हेडर और ट्रेलर स्ट्रिंग्स सेट करना एक और कारण हो सकता है।

क्या यह इंटरफ़ेस डिज़ाइन का एक सिद्धांत है जिसे मान्यता दी गई है या सिर्फ एक नाम दिए जाने से पहले केवल POLA तरीका है?

एनबी इस इंटरफ़ेस के टकसाल में फंस नहीं जाता है, यह इस प्रश्न के लिए सिर्फ एक उदाहरण है।


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


7
@KilianFoth: मुझे पूरा यकीन है कि विकिपीडिया इस बारे में गलत है - POLA केवल यूजर इंटरफेस डिज़ाइन के बारे में नहीं है, शब्द "कम से कम आश्चर्य का सिद्धांत" (जो कि काफी समान है) भी बॉब मार्टिन द्वारा उनके और समारोह में वर्ग डिजाइन के लिए उपयोग किया जाता है। "क्लीन कोड" पुस्तक।
डॉक ब्राउन

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

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

जवाबों:


25

एक तरीका जिसमें आप कम से कम विस्मय के सिद्धांत से चिपके रह सकते हैं, वह है आईएसपी और एसआरपी जैसे अन्य सिद्धांतों या यहां तक ​​कि DRY पर विचार करना

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

संपादित करें / अपडेट करें: यह यह भी बताता है कि एपीआई खुद उपयोगकर्ता को DRY का उल्लंघन करने के लिए कह रहा है, क्योंकि उन्हें हर बार एपीआई का उपयोग करने के लिए समान चरणों को दोहराने की आवश्यकता होगी

वैकल्पिक API पर विचार करें जहां IO ऑपरेशन डेटा ऑपरेशन से अलग होते हैं। और जहां एपीआई ही 'ऑर्डर' का मालिक है:

ContentBuilder

SetHeader( ... )
AddLine( ... )
SetTrailer ( ... )

FileWriter

Open(filename) 
Write(content) throws InvalidContentException
Close()

उपरोक्त अलगाव के साथ, ContentBuilderलाइनों / हेडर / ट्रेलर को स्टोर करने के अलावा वास्तव में "कुछ" करने की आवश्यकता नहीं है (शायद यह भी एक ContentBuilder.Serialize()विधि है जो आदेश को जानता है)। अन्य ठोस सिद्धांतों का पालन करने से यह अब मायने नहीं रखता है कि आप हेडर या ट्रेलर को लाइनों को जोड़ने से पहले या बाद में सेट करते हैं, क्योंकि ContentBuilderवास्तव में कुछ भी फाइल करने के लिए नहीं लिखा जाता है जब तक कि इसे पारित नहीं किया जाता है FileWriter.Write

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

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


वास्तव में मैं क्या देख रहा था - धन्यवाद! ISP लेख से: "(ISP) कहता है कि किसी भी ग्राहक को उन तरीकों पर निर्भर होने के लिए मजबूर नहीं किया जाना चाहिए जो इसका उपयोग नहीं करते हैं"
रॉबी डी

5
यह एक बुरा जवाब नहीं है, फिर भी कंटेंट बिल्डर को इस तरह से लागू किया जा सकता है, जहां कॉल SetHeaderया AddLineमामलों का क्रम हो । इस आदेश को खत्म करने के लिए निर्भरता न तो ISP है और न ही SRP, यह केवल POLA है।
डॉक ब्राउन

जब आदेश मायने रखता है, तो आप अभी भी संचालन को परिभाषित करके POLA को संतुष्ट कर सकते हैं जैसे कि बाद के चरणों का प्रदर्शन करने के लिए पूर्व चरणों से लौटाए गए मान की आवश्यकता होती है, जिससे प्रकार प्रणाली के साथ आदेश लागू होता है। FileWriterतब सभी इनपुट सामग्री को पूरा करने के लिए विधि ContentBuilderमें अंतिम चरण से मूल्य की आवश्यकता हो सकती Writeहै, InvalidContentExceptionअनावश्यक बना रही है ।
दान ल्योन

@DanLyons मुझे लगता है कि पूछने वाले से बचने की कोशिश कर रहे स्थिति के करीब है; जहां API के उपयोगकर्ता को आदेश के बारे में जानना या देखभाल करना आवश्यक है। आदर्श रूप से, एपीआई को खुद ही आदेश को लागू करना चाहिए, अन्यथा यह संभावित रूप से उपयोगकर्ता को DRY का उल्लंघन करने के लिए कह रहा है। यही कारण है कि बाहर बंटवारे ContentBuilderऔर FileWriter.Writeज्ञान के उस बिट encapsulate करने के लिए अनुमति देता है। अपवाद कुछ भी हो सकता है अगर सामग्री के साथ कुछ भी नहीं होता है, (जैसे कि एक लापता हेडर)। एक रिटर्न भी काम कर सकता है, लेकिन मैं अपवादों को रिटर्न कोड में बदलने का प्रशंसक नहीं हूं।
बेन कॉटरेल

लेकिन निश्चित रूप से DRY के बारे में और नोट्स जोड़ने और जवाब देने का आदेश देने के लायक है।
बेन कॉटरेल

12

यह न केवल POLA के बारे में है, बल्कि बग के संभावित स्रोत के रूप में अमान्य स्थिति को रोकने के बारे में भी है।

आइए देखें कि बिना ठोस कार्यान्वयन प्रदान किए हम आपके उदाहरण के लिए कुछ बाधाएँ कैसे प्रदान कर सकते हैं:

पहला चरण: किसी फ़ाइल को खोलने से पहले उसे कुछ भी कहने की अनुमति न दें।

CreateDataFileInterface
  + OpenFile(filename : string) : DataFileInterface

DataFileInterface
  + SetHeaderString(header : string) : void
  + WriteDataLine(data : string) : void
  + SetTrailerString(trailer : string) : void
  + Close() : void

अब यह स्पष्ट CreateDataFileInterface.OpenFileहोना चाहिए कि एक DataFileInterfaceउदाहरण को पुनः प्राप्त करने के लिए कहा जाना चाहिए , जहां वास्तविक डेटा लिखा जा सकता है।

दूसरा चरण: सुनिश्चित करें, हेडर और ट्रेलर हमेशा सेट होते हैं।

CreateDataFileInterface
  + OpenFile(filename : string, header: string, trailer : string) : DataFileInterface

DataFileInterface
  + WriteDataLine(data : string) : void
  + Close() : void

अब आपको a DataFileInterface: फ़ाइल नाम, हेडर और ट्रेलर प्राप्त करने के लिए सभी आवश्यक मापदंडों को पूरा करना होगा । यदि ट्रेलर स्ट्रिंग सभी पंक्तियों के लिखे जाने तक उपलब्ध नहीं है, तो आप इस पैरामीटर को Close()(संभवतः विधि का नाम बदलकर WriteTrailerAndClose()) भी स्थानांतरित कर सकते हैं, ताकि कम से कम फ़ाइल ट्रेलर स्ट्रिंग के बिना समाप्त न हो सके।


टिप्पणी का जवाब देने के लिए:

मुझे इंटरफ़ेस को अलग करना पसंद है। लेकिन मुझे लगता है कि आपका सुझाव प्रवर्तन के बारे में है (उदाहरण के लिए WriteTrailerAndClose ()) SRP के उल्लंघन पर फैसला कर रहा है। (यह एक ऐसी चीज है जिसे मैंने कई अवसरों पर संघर्ष किया है, लेकिन आपका सुझाव एक संभावित उदाहरण है।) आप कैसे प्रतिक्रिया देंगे?

सच। मैं अपनी बात मनवाने के लिए उदाहरण पर अधिक ध्यान केंद्रित नहीं करना चाहता था, लेकिन यह एक अच्छा सवाल है। इस मामले में मुझे लगता है कि मैं इसे कॉल करूंगा Finalize(trailer)और तर्क दूंगा कि यह बहुत ज्यादा नहीं है। ट्रेलर लिखना और समापन केवल कार्यान्वयन विवरण हैं। लेकिन अगर आप असहमत हैं या एक समान स्थिति है जहां यह अलग है, तो यहां एक संभावित समाधान है:

CreateDataFileInterface
  + OpenFile(filename : string, header : string) : IncompleteDataFileInterface

IncompleteDataFileInterface
  + WriteDataLine(data : string) : void
  + FinalizeWithTrailer(trailer : string) : CompleteDataFileInterface

CompleteDataFileInterface
  + Close()

मैं वास्तव में इसे इस उदाहरण के लिए नहीं करूंगा, लेकिन यह दिखाता है कि तकनीक के माध्यम से कैसे आगे बढ़ें।

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


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

ओह, तब मैंने आपको गलत समझा, मुझे लगा कि यह उपयोगकर्ता के इरादे का वर्णन कर रहा है, कार्यान्वयन का नहीं।
फैबियन शेंगलर

मुझे इंटरफ़ेस को अलग करना पसंद है। लेकिन मैं यह सोचने में इच्छुक हूं कि प्रवर्तन के बारे में आपका सुझाव (उदाहरण WriteTrailerAndClose()) SRP के उल्लंघन पर है। (यह एक ऐसी चीज है जिसे मैंने कई अवसरों पर संघर्ष किया है, लेकिन आपका सुझाव एक संभावित उदाहरण है।) आप कैसे प्रतिक्रिया देंगे?
kmote

1
@kmote का जवाब एक टिप्पणी के लिए बहुत लंबा था, मेरा अपडेट देखें
फैबियन शेंगलर

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