एक वाक्य में
GraphQL formatting एक कला है जिसमें queries, mutations, और schemas पर एक जैसे स्टाइल नियम लागू किए जाते हैं, जिससे ब्रेसिज़ और फ़ील्ड्स का जंजाल एक पढ़ने लायक, maintainable मास्टरपीस में बदल जाता है।
यह क्या समस्या हल करता है
पुराने ज़माने में, अगर आपको अपने नए कूल वेब ऐप के लिए सर्वर से डेटा चाहिए होता था, तो आप शायद REST API का इस्तेमाल करते थे। आप यूज़र डेटा के लिए /users/123 जैसे endpoint से पूछते थे, और उनकी पोस्ट्स के लिए /users/123/posts से। समस्या? आपको ज़रूरत से ज़्यादा यूज़र डेटा मिल सकता था (over-fetching), या आपको वह सारा डेटा पाने के लिए कई चक्कर लगाने पड़ते थे जिसकी आपको वास्तव में ज़रूरत थी (under-fetching)।
फिर आया GraphQL, जो Facebook द्वारा विकसित APIs के लिए एक query language है। इसने खेल ही पलट दिया। सर्वर यह तय करे कि क्या डेटा भेजना है, इसके बजाय client ठीक वही मांगता है जिसकी उसे ज़रूरत है, और वह भी एक ही request में। यह ऐसा है जैसे एक फिक्स्ड मेन्यू के बजाय अपनी पसंद की चीज़ें ऑर्डर करना।
# मुझे बस यूज़र 42 का नाम और उसकी पहली 3 पोस्ट्स के टाइटल दे दो
query GetUserNameAndPosts {
user(id: "42") {
name
posts(first: 3) {
title
}
}
}
यह एक क्रांति थी। लेकिन इसने एक नई, छोटे पैमाने की समस्या को जन्म दिया। GraphQL queries, अपने नेस्टेड कर्ली ब्रेसिज़ के साथ, जटिल हो सकती हैं। बहुत जटिल। बिना किसी नियम के, एक डेवलपर द्वारा लिखी गई query टेक्स्ट की एक ही, न पढ़ी जा सकने वाली लाइन की तरह दिख सकती है। दूसरा डेवलपर वही query पूरी तरह से अलग इंडेंटेशन स्टाइल के साथ लिख सकता है।
जब आप सुबह के 2 बजे किसी समस्या को debug करने की कोशिश कर रहे हों या कोई नया टीम सदस्य आपकी API की संरचना को समझने की कोशिश कर रहा हो, तो यह असंगतता एक दुःस्वप्न है। Code भी एक तरह का कम्युनिकेशन है, और unformatted GraphQL बिना पैराग्राफ, विराम चिह्न, या एक जैसे फ़ॉन्ट वाली किताब पढ़ने जैसा है। Formatting एक साझा व्याकरण लागू करती है, जिससे code का इरादा हर उस इंसान को तुरंत स्पष्ट हो जाता है जो उसे पढ़ता है।
यह अंदर से कैसे काम करता है
एक GraphQL formatter सिर्फ़ एक फैंसी फाइंड-एंड-रिप्लेस नहीं कर रहा है। यह एक परिष्कृत प्रक्रिया है जिसमें code की संरचना को समझना, नियमों का एक सेट लागू करना, और फिर code को स्क्रैच से एक सुंदर, अनुमानित तरीके से फिर से बनाना शामिल है।
Parsing: टेक्स्ट से ट्री तक
सबसे पहले, formatter को GraphQL code के रॉ स्ट्रिंग को पढ़ना होता है और यह समझना होता है कि यह क्या है। यह सिर्फ { को देखकर एक नई लाइन नहीं जोड़ सकता। इसे यह जानने की ज़रूरत है कि क्या वह ब्रेस एक query, एक type definition, या एक input object खोल रहा है।
इस प्रक्रिया को parsing कहा जाता है। Formatter इनपुट को tokenize करता है (इसे query, user, (, id, :, "42", ) जैसे सार्थक हिस्सों में तोड़ता है) और फिर एक Abstract Syntax Tree (AST) बनाता है। AST एक पेड़ जैसी डेटा संरचना है जो code के व्याकरणिक ढांचे का प्रतिनिधित्व करती है।
एक सरल query के लिए:
query { user { name } }
AST कुछ इस तरह दिख सकता है (एक सरलीकृत, वैचारिक तरीके से):
- Document
- Definition (OperationDefinition, type: query)
- SelectionSet
- Selection (Field)
- name: "user"
- SelectionSet
- Selection (Field)
- name: "name"
टेक्स्ट अब सिर्फ़ टेक्स्ट नहीं है; यह एक संरचित ऑब्जेक्ट है जिसे प्रोग्राम समझदारी से हेरफेर कर सकता है।
स्टाइल के नियम
एक बार जब formatter के पास AST आ जाता है, तो वह ट्री के माध्यम से चल सकता है और अपने स्टाइल नियमों को लागू कर सकता है। ये नियम formatting का दिल हैं और अक्सर (ज्यादातर व्यर्थ) डेवलपर बहसों का विषय होते हैं। सामान्य नियमों में शामिल हैं:
- इंडेंटेशन: नेस्टिंग के प्रत्येक स्तर के लिए कितने स्पेस (या टैब्स, अगर आप इन्हें इस्तेमाल करने का गुनाह करते हैं तो) का उपयोग करना है। लगभग सार्वभौमिक मानक 2 स्पेस है।
- लाइन ब्रेक्स: चीज़ों को नई लाइन पर कब रखना है। क्या एक ओपनिंग ब्रेस
{को फ़ील्ड नाम के साथ उसी लाइन पर होना चाहिए या एक नई लाइन पर? (अधिकांश formatters इसे उसी लाइन पर रखते हैं।) - स्पेसिंग: कोलन जैसे ऑपरेटरों के आसपास और कोष्ठक के भीतर लगातार स्पेस सुनिश्चित करना।
- फ़ील्ड सॉर्टिंग: बड़े schemas के लिए, कुछ formatters फ़ील्ड्स को वर्णानुक्रम में भी सॉर्ट कर सकते हैं ताकि उन्हें ढूंढना आसान हो सके।
Prettier जैसे टूल "opinionated" होने के लिए प्रसिद्ध हो गए हैं—वे आपके लिए ये विकल्प चुनते हैं, ताकि आपको उनके बारे में बहस न करनी पड़े। लक्ष्य एक "परफेक्ट" स्टाइल ढूंढना नहीं है, बल्कि एक स्टाइल चुनना और उसे लगातार लागू करना है।
Pretty-Printing: ट्री से वापस टेक्स्ट तक
नियमों को लागू करने के बाद, formatter का अंतिम काम संशोधित AST को लेना और इसे वापस टेक्स्ट की एक स्ट्रिंग में बदलना है। इस प्रक्रिया को pretty-printing कहा जाता है। Formatter ट्री को पार करता है, और प्रत्येक नोड (जैसे Field या SelectionSet) पर, यह संबंधित टेक्स्ट को प्रिंट करता है, नियमों के अनुसार सही इंडेंटेशन और लाइन ब्रेक जोड़ता है।
परिणाम एक खूबसूरती से format किया गया GraphQL स्ट्रिंग होता है।
एक संबंधित अवधारणा minification या compacting है। यह pretty-printing का उल्टा है। यह भी code को एक AST में parse करता है, लेकिन फिर इसे सभी वैकल्पिक व्हाइटस्पेस हटाकर वापस प्रिंट करता है। यह एक सिंगल-लाइन, कॉम्पैक्ट स्ट्रिंग बनाता है जो इंसानों के लिए अपठनीय है लेकिन नेटवर्क पर भेजने के लिए एकदम सही है, क्योंकि यह कुछ कीमती बाइट्स बचाता है।
असल दुनिया की कहानियाँ
आधी रात के Debugging सेशन का किस्सा
जैस्मिन, एक बैकएंड इंजीनियर, ऑन-कॉल थी। सुबह 1:30 बजे, एक अलर्ट आया: एक महत्वपूर्ण GraphQL mutation प्रोडक्शन में फेल हो रहा था। एकमात्र सुराग एक लॉग एंट्री थी जिसमें client द्वारा भेजी गई सटीक query थी - एक 3000-कैरेक्टर की सिंगल लाइन, जो एक minified JavaScript बंडल से कॉपी-पेस्ट की गई थी। वह टेक्स्ट की उस दीवार को घूरती रही, ...customer{address{..., जिसमें वह गलत हिस्से को खोजने की कोशिश कर रही थी। उसकी आँखें धुँधला गईं। निराश होकर, उसने पूरी स्ट्रिंग को एक GraphQL formatter में डाल दिया। तुरंत, query एक 70-लाइन, पूरी तरह से इंडेंट की गई संरचना में खिल गई। और वहाँ यह था, लाइन 47 पर दिन के उजाले की तरह साफ़: एक महत्वपूर्ण फ़ील्ड नाम में एक टाइपो, address के बजाय adress। समाधान मामूली था, लेकिन वह समस्या को तब तक देख भी नहीं सकती थी जब तक कि उसे format नहीं किया गया।
सबक: पठनीयता (Readability) ही debug करने की क्षमता का पहला और सबसे महत्वपूर्ण कदम है। एक formatter टेक्स्ट के एक अभेद्य ढेर को कुछ ऐसा बना देता है जिसे एक इंसान वास्तव में समझ सकता है।
वो Pull Request जो Merge होकर ही नहीं दे रहा था
एक छोटी टीम GraphQL के साथ एक नया ई-कॉमर्स बैकएंड बना रही थी। दो डेवलपर, लियाम और ओलिविया, एक फीचर पर काम कर रहे थे। लियाम ने अपने एडिटर को 4-स्पेस इंडेंटेशन का उपयोग करने के लिए कॉन्फ़िगर किया। ओलिविया, जो 2-स्पेस इंडेंट की प्रशंसक थी, का सेटअप अलग था। जब लियाम ने अपना pull request सबमिट किया, तो ओलिविया ने उसकी समीक्षा की, कुछ तार्किक बदलाव किए, और अपना commit पुश कर दिया। परिणामी "diff" लाल और हरे रंग का समुद्र था। लगभग हर लाइन को बदला हुआ चिह्नित किया गया था, सिर्फ इसलिए क्योंकि उनके एडिटर व्हाइटस्पेस पर लड़ रहे थे। वास्तविक, सार्थक परिवर्तन पूरी तरह से शोर में खो गए थे। टेक लीड को इस गड़बड़ी को सुलझाने में एक घंटा लगाना पड़ा। अगले दिन, उसने उनके pre-commit हुक में एक स्वचालित GraphQL formatter जोड़ा। अब, commit होने से पहले ही सारा code एक ही मानक के अनुसार format हो जाता है।
सबक: स्वचालित formatting स्टाइल की बहसों को खत्म करती है और वर्ज़न कंट्रोल हिस्ट्री को साफ़ रखती है, जिससे समीक्षाएँ उस चीज़ पर केंद्रित होती हैं जो मायने रखती है: लॉजिक।
वो Schema जो स्पेगेटी जैसा दिखता था
एक स्टार्टअप का GraphQL schema तीन वर्षों में व्यवस्थित रूप से बढ़ा था। Types को जहाँ भी फिट बैठता था, जोड़ दिया गया था, फ़ील्ड्स किसी विशेष क्रम में नहीं थे, और कमेंट्स छिटपुट थे। एक नए कर्मचारी के लिए, API के डेटा मॉडल को समझने की कोशिश करना पुराने केबलों से भरे दराज को सुलझाने जैसा था। उन्होंने एक प्रयोग करने का फैसला किया: उन्होंने पूरी schema.graphql फ़ाइल को एक formatter में डाल दिया। टूल ने न केवल सब कुछ सही ढंग से इंडेंट किया, बल्कि प्रत्येक type के भीतर सभी फ़ील्ड्स को वर्णानुक्रम में सॉर्ट भी कर दिया। अचानक, id हमेशा पहला फ़ील्ड था। Deprecated फ़ील्ड्स एक साथ समूहित हो गए। पूरी संरचना फोकस में आ गई। यह सिर्फ़ सुंदर नहीं था; यह अब दस्तावेज़ीकरण का एक उपयोगी टुकड़ा था।
सबक: एक अच्छी तरह से format किया गया schema जीवित दस्तावेज़ के रूप में काम करता है। यह आपकी API की संरचना और इरादे को प्रकट करता है, जिससे यह सभी के लिए अधिक सुलभ हो जाता है।
आम गलतियाँ और जाल
- स्टाइल पर बहस करना। सबसे बड़ा जाल है टैब्स बनाम स्पेस या ब्रेस कहाँ जाना चाहिए, इस पर घंटों बर्बाद करना। formatting का मूल्य एकरूपता है। Prettier जैसा एक लोकप्रिय, opinionated टूल चुनें, उसे इस्तेमाल करने पर सहमत हों, और आगे बढ़ें।
- commit करने से पहले format करना भूल जाना। अगर formatting एक मैन्युअल प्रक्रिया है, तो लोग भूल जाएंगे। इससे वे गंदे diffs बनते हैं जिनसे आप बचने की कोशिश कर रहे थे। formatting को एक pre-commit हुक (Husky और lint-staged जैसे टूल का उपयोग करके) में एकीकृत करें ताकि यह स्वचालित और सहज हो जाए।
- formatting को linting के साथ भ्रमित करना। एक formatter आपके code को सुसंगत बनाता है। एक linter (जैसे
eslint-plugin-graphql) आपके code को संभावित बग्स या खराब प्रथाओं के लिए जाँचता है, जैसे कि एक deprecated फ़ील्ड का उपयोग करना या एक अकुशल query लिखना। आपको दोनों की ज़रूरत है। एक formatter रसोई साफ़ करता है; एक linter यह जाँचता है कि कहीं आपने स्टोव तो चालू नहीं छोड़ दिया। - जेनरेट किए गए code को format करना। कुछ वर्कफ़्लो किसी अन्य स्रोत (जैसे डेटाबेस स्कीमा या किसी भिन्न प्रोग्रामिंग भाषा) से GraphQL स्कीमा फ़ाइलें या query जेनरेट करते हैं। आउटपुट को format करना अक्सर समय की बर्बादी होती है, क्योंकि अगली बार code जेनरेट होने पर आपके परिवर्तन ओवरराइट हो जाएंगे। इसके बजाय स्रोत को format करें।
- प्रोडक्शन में सुंदर queries भेजना। जबकि विकास के लिए सुंदर इंडेंटेशन बहुत अच्छा है, यह नेटवर्क पर बाइट्स की बर्बादी है। आपकी बिल्ड प्रक्रिया को आपके client एप्लिकेशन से सर्वर पर भेजे जाने से पहले GraphQL queries को minify करना चाहिए।
यह आपके रडार पर क्यों होना चाहिए
आपको GraphQL formatting के बारे में उसी क्षण सोचना शुरू कर देना चाहिए जब किसी प्रोजेक्ट में एक से अधिक व्यक्ति शामिल हों, या जब आपकी queries एक सिंगल नेस्टेड फ़ील्ड से अधिक जटिल हो जाएं।
यह पेशेवर सॉफ्टवेयर विकास के लिए एक मूलभूत उपकरण है जो GraphQL पर पूरी तरह से लागू होता है। यह सिर्फ़ चीजों को "सुंदर" बनाने के लिए नहीं है। यह इन चीज़ों के बारे में है:
- स्पष्टता (Clarity): code को पढ़ने और समझने में आसान बनाना।
- रखरखाव (Maintainability): code को बदलने और debug करने में आसान बनाना।
- सहयोग (Collaboration): शैलीगत विकल्पों को स्वचालित करके टीम के सदस्यों के बीच घर्षण को कम करना।
अगर आप कभी भी अपने आप को किसी लॉग फ़ाइल में एक minified GraphQL query को घूरते हुए पाते हैं, या किसी टीम के साथी के साथ इंडेंटेशन के बारे में बहस करते हुए पाते हैं, तो यह एक संकेत है कि आपको अपने जीवन में एक स्वचालित formatter की ज़रूरत है।
और गहराई में जाएं
- GraphQL Specification - GraphQL भाषा के लिए आधिकारिक, प्रामाणिक स्रोत।
- Prettier: GraphQL - GraphQL के लिए सबसे लोकप्रिय कोड formatter के समर्थन के लिए डॉक्स।
- Exploring GraphQL APIs with Abstract Syntax Trees - AST की शक्ति पर Apollo का एक बेहतरीन पोस्ट।
- GraphQL on Wikipedia - एक उच्च-स्तरीय अवलोकन और इतिहास के लिए।
- ESLint Plugin for GraphQL - linting में एक गहरी डुबकी, जो formatting का शक्तिशाली साथी है।