- API resource naming और modeling से जुड़े निर्णय, API डिज़ाइन का सबसे कठिन और सबसे महत्वपूर्ण हिस्सा हैं। Resources, यूज़र के मन में इस बात का mental model बनाते हैं कि product कैसे काम करता है और उसकी capabilities क्या हैं।
- Increase टीम API डिज़ाइन को दिशा देने के लिए "कोई abstraction नहीं" सिद्धांत का उपयोग करती है।
Stripe का API डिज़ाइन दृष्टिकोण
- टीम के कई सदस्य पहले Stripe में काम कर चुके थे, इसलिए उन्होंने Stripe के सफल API डिज़ाइन मूल्यों पर विचार किया।
- Stripe जटिल domain की core functionality को ऐसे abstractions में बदलने में बहुत सक्षम है जिन्हें यूज़र आसानी से समझ और उपयोग कर सकें। (उदाहरण: Visa और Mastercard के अंतर को abstract करने वाला PaymentIntent)
- Stripe के ज़्यादातर यूज़र ऐसे शुरुआती startup होते हैं जो payment से असंबंधित products बना रहे होते हैं, इसलिए उन्हें credit card की बारीकियों को जानने की ज़रूरत नहीं होती। वे Stripe को जल्दी integrate करके अपने product development पर ध्यान देना चाहते हैं।
Increase के यूज़र और API डिज़ाइन सिद्धांत
- इसके विपरीत, Increase के यूज़र payment network के बारे में गहरी जानकारी रखते हैं, और Increase को चुनने का कारण ही direct network connectivity और integration की गहराई है।
- वे यह ठीक-ठीक जानना चाहते हैं कि FedACH window कब बंद होती है और transfer किस समय होता है, और वे समझते हैं कि ACH transfer में अलग-अलग SEC code सेटिंग्स return timing को प्रभावित कर सकती हैं।
- इन networks की मूलभूत जटिलता को छिपाने की कोशिश, यूज़र की ज़िंदगी आसान नहीं बनाती; उल्टा उन्हें परेशान करती है।
- शुरुआती यूज़र्स के साथ हुई बातचीत के ज़रिए "कोई abstraction नहीं" सिद्धांत निकाला गया और इसे API डिज़ाइन में लागू किया गया।
"कोई abstraction नहीं" सिद्धांत का API डिज़ाइन पर प्रभाव
- वास्तव में इस्तेमाल होने वाली terminology का उपयोग: API resources और properties के लिए अपने नाम गढ़ने के बजाय underlying network की vocabulary का उपयोग किया गया। (उदाहरण: ACH transfer parameters में Nacha specification के field names का उपयोग)
- अपरिवर्तनीयता: वास्तविक events को model बनाकर अधिक API resources को immutable बनाया गया। Immutable resource clusters को state machine "lifecycle objects" के रूप में समूहित करना प्रभावी रहा। (उदाहरण:
ach_transfer object का status field और transfer lifecycle के अनुसार बनने वाले कुछ immutable child objects)
- use case के अनुसार resources को अलग करना: जब resource instance के आधार पर यूज़र द्वारा किए जा सकने वाले actions का सेट बहुत अलग हो, तो उसे कई resources में विभाजित किया गया। (उदाहरण: outgoing ACH transfer और incoming ACH transfer को अलग resources में बाँटना)
इंजीनियरिंग टीम द्वारा इस दृष्टिकोण का पालन
- इंजीनियरिंग टीम ने इस दृष्टिकोण का पालन करने का संकल्प लिया।
- कई वर्षों तक जटिल API डिज़ाइन करते समय लगातार छोटे-छोटे incremental निर्णय लेने पड़ते हैं; ऐसे में पहले से मूल सिद्धांतों का पालन करने का संकल्प, इन निर्णयों का cognitive load कम कर देता है।
- उदाहरण के लिए, Federal Reserve को remittance भेजते समय आवश्यक Input Message Accountability Data field के मामले में, अधिक abstraction वाले API में इस field का कोई "user-friendly" नाम क्या होना चाहिए, इस पर सोचना पड़ता। लेकिन Increase में engineer बस field का नाम
input_message_accountability_data रखकर आगे बढ़ जाता है।
GN⁺ की राय
- API में abstraction का स्तर, उस product domain के बारे में developer के अनुभव स्तर और integration में लगाने वाली ऊर्जा आदि के अनुसार बदल सकता है। इसलिए API डिज़ाइन करते समय उसे integrate करने वाले developers के लिए उपयुक्त abstraction स्तर पर विचार करना महत्वपूर्ण है।
- यदि आप उच्च abstraction स्तर वाला API बना रहे हैं, तो नई functionality जोड़ने से पहले बहुत सावधानी से सोचना चाहिए। वहीं यदि आप निम्न abstraction स्तर वाला API बना रहे हैं, तो उस सिद्धांत पर टिके रहना चाहिए और abstraction जोड़ने के प्रलोभन का विरोध करना चाहिए।
- underlying network या protocol की terminology को ज्यों का त्यों उपयोग करना developers को underlying system समझने में मदद कर सकता है, लेकिन दूसरी ओर पहली बार आने वाले developers के लिए यह प्रवेश बाधा भी बन सकता है। इसलिए comments और documentation को अच्छी तरह तैयार रखना महत्वपूर्ण लगता है।
- API डिज़ाइन में immutable objects का उपयोग data consistency बनाए रखने और side-effects को रोकने में प्रभावी हो सकता है। लेकिन यदि data update करने की आवश्यकता हो, तो यह असुविधाजनक भी हो सकता है, इसलिए trade-off पर सावधानी से विचार करना चाहिए।
- use case के अनुसार resources को अलग करना API की complexity बढ़ा सकता है, लेकिन लंबी अवधि में predictability बढ़ा सकता है। हालांकि यदि इसे बहुत अधिक सूक्ष्म बना दिया जाए तो usability घट सकती है, इसलिए सही स्तर खोजना महत्वपूर्ण है।
1 टिप्पणियां
Hacker News राय
low-level abstraction वाले API और high-level abstraction वाले API, दोनों उपलब्ध कराना अच्छा है
Increase ने अलग approach क्यों चुना, इसे समझाने वाला हिस्सा अच्छा लगा
Stripe की असली क्षमता यह है कि वह अपने customers को समझता है और उन्हें उनकी चाही हुई simplicity देता है
यह Domain-Driven Design के "Ubiquitous Language" design pattern जैसा है, जिसमें implementation में वही terms इस्तेमाल किए जाते हैं जो domain experts वास्तव में इस्तेमाल करते हैं
ऐसी भाषा इस्तेमाल करनी चाहिए जिसे domain expert समझ सके
अगर POSIX जैसी abstraction न हो, तो application को हर supported file system के लिए adapter लिखना पड़ेगा
कहा गया है कि API structure का कुछ हिस्सा externally controlled specification के आधार पर 1:1 बनाया जाता है
payment API में एक चीज़ जिसे साफ़-सुथरे तरीके से model करना मुश्किल है, वह यह है कि payment schemes, payment return के समय payer और payee की भूमिकाओं को अलग-अलग तरीके से दिखाती हैं