क्या किसी को हमेशा पता होना चाहिए कि एक एपीआई कोड को देखकर क्या कर रहा है?


20

हाल ही में मैं अपना खुद का एपीआई विकसित कर रहा हूं और इसके साथ ही एपीआई डिजाइन में निवेशित रुचि मुझे गहरी दिलचस्पी है कि मैं अपने एपीआई डिजाइन को कैसे सुधार सकता हूं।

एक पहलू जो कुछ बार सामने आया है, वह है (मेरे एपीआई के उपयोगकर्ताओं द्वारा नहीं, लेकिन विषय के बारे में मेरी चर्चा में): किसी को एपीआई को कॉल करने वाले कोड को देखकर पता होना चाहिए कि वह क्या कर रहा है

उदाहरण के लिए GitHub पर प्रवचन रिपो के लिए इस चर्चा को देखें , यह कुछ इस तरह है:

foo.update_pinned(true, true);

बस कोड को देखकर (पैरामीटर नाम, प्रलेखन आदि को जाने बिना) कोई यह अनुमान नहीं लगा सकता है कि यह क्या करने जा रहा है - 2 तर्क का क्या मतलब है? सुझाए गए सुधार में कुछ ऐसा है:

foo.pin()
foo.unpin()
foo.pin_globally()

और इससे चीजें साफ हो जाती हैं (दूसरा तर्क यह था कि विश्व स्तर पर पिन करना है, मैं अनुमान लगा रहा हूं), और मैं इस मामले में सहमत हूं कि बाद में निश्चित रूप से सुधार होगा।

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

उदाहरण के लिए, मैं SetVisibility(bool, string, bool)एक फाल्कनपेयर पर एक विधि का पर्दाफाश करता हूं और मैं स्वीकार करता हूं कि लाइन को देख रहा हूं:

falconPeer.SetVisibility(true, "aerw3", true);

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


13
यही कारण है कि कुछ भाषाओं ने मापदंडों का नाम दिया है (कभी-कभी नामांकित पैरामीटर भी लागू किए जाते हैं )। उदाहरण के लिए आप एक सरल updateविधि में बहुत सारी सेटिंग्स को समूहित कर सकते हैं foo.update(pinned=true, globally=true):। या: foo.update_pinned(true, globally=true)। तो, आपके प्रश्न का उत्तर भी भाषा की विशेषताओं को ध्यान में रखना चाहिए, क्योंकि भाषा X के लिए एक अच्छा एपीआई भाषा Y और उपाध्यक्ष के लिए अच्छा नहीं हो सकता है।
बकुरीउ

सहमति - लेट्स का उपयोग कर बंद बूलियन्स :)
Ven


@Bakuriu यहां तक ​​कि सी में दुश्मनी है, भले ही वे भेस में पूर्णांक हैं। मुझे नहीं लगता कि कोई वास्तविक दुनिया की भाषा है जहां बुलियन अच्छे एपीआई डिजाइन हैं।
डोभाल

1
@ डोभाल मुझे वह नहीं मिला जो आप कहने की कोशिश कर रहे हैं। मैंने उस स्थिति में बूलियनों का उपयोग केवल इसलिए किया क्योंकि ओपी ने उनका उपयोग किया था, लेकिन मेरी बात पूरी तरह से पारित मूल्य से असंबंधित है। उदाहरण के लिए: के setSize(10, 20)रूप में setSize(width=10, height=20)या के रूप में पठनीय नहीं है random(distribution='gaussian', mean=0.5, deviation=1)। लागू किए गए नामित मापदंडों वाली भाषाओं में, बूलियां वास्तव में उसी तरह की जानकारी दे सकती हैं, जैसे कि एनम / नामांकित स्थिरांक का उपयोग करना, इसलिए वे एपीआई में अच्छे हो सकते हैं।
बकुरीउ

जवाबों:


27

इसे तीन विधि कॉलों में विभाजित करने की आपकी इच्छा पूरी तरह से समझ में आने वाली है, लेकिन आपके पास बूलियन मापदंडों के अलावा अन्य विकल्प नहीं हैं।

आप enums का उपयोग कर सकते हैं:

falconPeer.SetVisibility(JoinRequestOptions.Accept, "aerw3", DiscoveryRequestOptions.Reply);

या यहां तक ​​कि एक झंडे एनम (यदि आपकी भाषा इसका समर्थन करती है):

falconPeer.SetVisibility(VisibilityOptions.AcceptJoinRequests | VisibilityOptions.ReplyToDiscoveryRequests, "aerw3");

या आप एक पैरामीटर ऑब्जेक्ट का उपयोग कर सकते हैं :

var options = new VisibilityOptions();
options.AcceptJoinRequests = true;
options.ReplyToDiscoveryRequest = true;
options.Password="aerw3";
falconPeer.SetVisibility(options);

पैरामीटर ऑब्जेक्ट पैटर्न आपको कुछ अन्य लाभ प्रदान करता है जो आपको सहायक लग सकते हैं। यह चारों ओर से गुजरता है और मापदंडों के एक सेट को अनुक्रमित करना आसान बनाता है, और आप आसानी से अनिर्दिष्ट मापदंडों को "डिफ़ॉल्ट" मान दे सकते हैं।

या आप बस बूलियन मापदंडों का उपयोग कर सकते हैं। Microsoft .NET फ्रेमवर्क एपीआई के साथ हर समय ऐसा करने लगता है, इसलिए आप सिर्फ यह कह सकते हैं कि "यदि यह उनके लिए पर्याप्त है, तो यह मेरे लिए काफी अच्छा है"।


पैरामीटर ऑब्जेक्ट पैटर्न में अभी भी एक समस्या है जिसे ओपी ने कहा है: " इसे 3 विधि कॉलों में विभाजित करने से एपीआई का एक उपयोगकर्ता" दृश्यता "का एक पहलू निर्धारित कर सकता है जो दूसरों को सेट करना भूल सकता है
लोड

सच है, लेकिन मुझे लगता है कि यह स्थिति को बेहतर बनाता है (यदि सही नहीं)। यदि उपयोगकर्ता को विजिबिलिटी ऑबजेक्शन ऑब्जेक्ट में झटपट और पास करने के लिए मजबूर किया जाता है, तो यह (किसी भी भाग्य के साथ) उन्हें याद दिला सकता है कि विजिबिलिटी ऑउंस ऑब्जेक्ट पर अन्य गुण हैं जो वे सेट करना चाहते हैं। तीन विधि कॉल दृष्टिकोण के साथ, सभी उन्हें याद दिलाने के लिए मिल गए हैं कि वे उन तरीकों पर टिप्पणी कर रहे हैं जो वे बुला रहे हैं।
बेनएम

6

जाहिर है, नियम में हमेशा अपवाद होते हैं, लेकिन जैसा कि आपने खुद को अच्छी तरह से समझाया है, पढ़ने योग्य एपीआई होने में कुछ फायदे हैं। बूलियन तर्क विशेष रूप से परेशान हैं, क्योंकि 1) वे एक आशय प्रकट नहीं करते हैं और 2) वे इसका मतलब है कि आप एक फ़ंक्शन कहते हैं, जहां आपको वास्तव में दो होने चाहिए, क्योंकि बूलियन ध्वज के आधार पर अलग-अलग चीजें होने वाली हैं।

मुख्य प्रश्न यह है: आप अपने एपीआई को और अधिक पठनीय बनाने के लिए कितना प्रयास करना चाहते हैं? जितना अधिक बाहर का सामना करना पड़ता है, उतना ही प्रयास आसानी से उचित हो सकता है। यदि यह एक एपीआई है जो केवल एक अन्य इकाई द्वारा उपयोग किया जाता है, तो यह सौदा का उतना बड़ा नहीं है। यदि आप एक REST API के बारे में बात कर रहे हैं, जहाँ आप पूरी दुनिया को इस पर हारने देने की योजना बना रहे हैं, तो आप इसे और अधिक समझने के लिए कुछ और प्रयास कर सकते हैं।

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

Visibility visibility = Visibility.builder()
  .acceptJoinRequests()
  .withPassword("aerw3")
  .replyToDiscoveryRequests()
  .build();
falconPeer.setVisibility(visibility);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.