एक वाक्य में
इंडेंटेशन कोड की लाइनों को विज़ुअली ग्रुप करने के लिए व्हाइटस्पेस का उपयोग करता है, जिससे प्रोग्राम की लॉजिकल संरचना इंसान की आंखों के लिए स्पष्ट हो जाती है।
यह किस समस्या को हल करता है
बिना पैराग्राफ, बिना चैप्टर, और डायलॉग के लिए बिना इंडेंटेशन वाले एक उपन्यास को पढ़ने की कल्पना करें। यह टेक्स्ट की एक अभेद्य दीवार होगी। आप अपनी जगह खो देंगे, बातचीत को समझने में संघर्ष करेंगे, और जल्दी ही हार मान लेंगे।
शुरुआती कोड अक्सर ऐसा ही होता था। पंच कार्ड के युग में, जगह बहुत कीमती थी, और ध्यान मशीन को निर्देश समझाने पर था, न कि उस अगले इंसान पर जिसे इसे मेंटेन करना था। कई शुरुआती भाषाओं के लिए, व्हाइटस्पेस को या तो कंप्यूटर द्वारा अनदेखा कर दिया जाता था या इसके बहुत कठोर, कॉलम-आधारित नियम होते थे (हाँ, FORTRAN, तुम्हारी ही बात हो रही है)।
जैसे-जैसे प्रोग्रामिंग एक विशिष्ट अकादमिक क्षेत्र से एक वैश्विक उद्योग में विकसित हुई, एक बहुत बड़ी समस्या सामने आई: कोड लिखे जाने से कहीं ज़्यादा बार पढ़ा जाता है। कोड की एक लाइन शायद एक बार लिखी जाती हो, लेकिन टीम के सदस्यों, भविष्य के डेवलपर्स (जिसमें आपका भविष्य का स्व भी शामिल है!), और डीबगर्स द्वारा सैकड़ों बार पढ़ी जा सकती है।
एक सुसंगत विज़ुअल संरचना के बिना कोड मानसिक रूप से थका देने वाला होता है। आपको यह पता लगाने के लिए हर लाइन को मानसिक रूप से पार्स करना पड़ता है कि यह किस if स्टेटमेंट से संबंधित है, एक फ़ंक्शन कहाँ समाप्त होता है, या एक लूप के अंदर क्या है। यह मानसिक ओवरहेड प्रोडक्टिविटी पर एक सीधा टैक्स है और बग्स के लिए एक प्रजनन भूमि है। एक गलत जगह पर लगा हुआ कर्ली ब्रेस, जो बिना इंडेंट किए टेक्स्ट के समुद्र में अदृश्य हो, एक टीम के डीबगिंग में कई दिन बर्बाद कर सकता है।
इससे कोड स्टाइल के "धर्मयुद्ध" शुरू हुए: टैब्स बनाम स्पेस, दो स्पेस बनाम चार, ओपनिंग ब्रेस कहाँ रखें। टीमें कोड रिव्यू में लॉजिक से ज़्यादा फॉर्मेटिंग पर बहस करने में समय बिताती थीं।
स्वचालित कोड इंडेंटेशन और फॉर्मेटिंग इस समस्या को पूरी तरह से हल करते हैं। वे एक अथक, निष्पक्ष स्टाइल गाइड लागू करने वाले की तरह काम करते हैं, जो एक गंदे, असंगत लिखावट को एक साफ, सार्वभौमिक रूप से समझे जाने वाले ढांचे में बदल देते हैं। यह डेवलपर्स की दिमागी शक्ति को उन चीज़ों पर ध्यान केंद्रित करने के लिए मुक्त करता है जो वास्तव में मायने रखती हैं: समस्याओं को हल करना।
अंदर की कहानी: यह कैसे काम करता है
आप सोच सकते हैं कि एक इंडेंटर बस एक ओपनिंग ब्रैकेट { को देखता है और अगली लाइन में कुछ स्पेस जोड़ देता है। हालांकि यह मूल विचार है, एक वास्तविक, भाषा-जागरूक इंडेंटर इससे कहीं ज़्यादा परिष्कृत चीज़ है। यह केवल कैरेक्टर्स को नहीं देखता; यह कोड के व्याकरण को समझता है। इस प्रक्रिया में आम तौर पर दो प्रमुख चरण शामिल होते हैं: कोड को एक संरचनात्मक प्रतिनिधित्व में पार्स करना और फिर उस संरचना को वापस टेक्स्ट में "प्रिटी-प्रिंट" करना।
चरण 1: पार्सिंग और एब्सट्रैक्ट सिंटैक्स ट्री (AST)
कोड को फॉर्मेट करने से पहले, टूल को उसे समझना होता है। यह सिर्फ अनुमान नहीं लगा सकता। यह स्रोत कोड को एब्सट्रैक्ट सिंटैक्स ट्री (AST) नामक डेटा संरचना में पार्स करके किया जाता है। इसे एक तैयार इमारत से एक विस्तृत ब्लूप्रिंट बनाने जैसा समझें।
लेक्सिंग (या टोकनाइजिंग): रॉ टेक्स्ट को स्कैन किया जाता है और "टोकन" के एक क्रम में तोड़ा जाता है। एक टोकन कोड की सबसे छोटी सार्थक इकाई है, जैसे कि एक कीवर्ड (
const), एक आइडेंटिफायर (myVar), एक विराम चिह्न ({), या एक लिटरल वैल्यू (123)।जावास्क्रिप्ट की एक सरल लाइन जैसे
const x = 10;के लिए, टोकन कुछ इस तरह दिख सकते हैं:[KEYWORD:"const"] [IDENTIFIER:"x"] [OPERATOR:"="] [NUMBER:"10"] [PUNCTUATION:";"]पार्सिंग: टोकन की स्ट्रीम को फिर एक पार्सर को दिया जाता है। पार्सर भाषा के व्याकरण के नियमों का उपयोग करके इन टोकन को एक ट्री संरचना में इकट्ठा करता है जो कोड के लॉजिकल पदानुक्रम का प्रतिनिधित्व करता है।
हमारे सरल उदाहरण के लिए, AST कुछ इस तरह दिख सकता है (एक सरलीकृत JSON-जैसे दृश्य में):
{ "type": "VariableDeclaration", "kind": "const", "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "x" }, "init": { "type": "Literal", "value": 10 } } ] }
अब टूल अस्पष्ट टेक्स्ट से नहीं निपट रहा है। यह निश्चित रूप से जानता है कि उसके पास एक "वेरिएबल डिक्लेरेशन" है जिसमें "x" नाम का एक वेरिएबल है जिसे 10 के मान से इनिशियलाइज़ किया गया है।
चरण 2: ट्री को प्रिटी-प्रिंट करना
AST हाथ में होने के साथ, फॉर्मैटर अब इस संरचित ट्री के माध्यम से चल सकता है और इसे पूरी तरह से स्वरूपित टेक्स्ट के रूप में प्रिंट कर सकता है। इस प्रक्रिया को अक्सर "प्रिटी-प्रिंटिंग" कहा जाता है।
प्रिंटर AST में जिस प्रकार के नोड पर जा रहा है, उसके आधार पर नियमों के एक सेट का पालन करता है।
- जब यह "ब्लॉक स्टेटमेंट" नोड में प्रवेश करता है (जैसे,
if,for, याfunctionकी बॉडी), तो यह जानता है कि इंडेंटेशन स्तर बढ़ाना है। - जब यह उस नोड को छोड़ता है, तो यह इंडेंटेशन स्तर घटाता है।
- यह जानता है कि लाइन ब्रेक कहाँ उपयुक्त हैं (जैसे, एक सेमीकोलन
;या एक क्लोजिंग ब्रेस}के बाद)। - यह सुसंगत स्पेसिंग लागू करता है (जैसे, हमेशा
+या=जैसे ऑपरेटरों के आसपास एक स्पेस डालना)।
Prettier जैसे आधुनिक फॉर्मैटर और भी उन्नत तकनीक का उपयोग करते हैं। सीधे प्रिंट करने के बजाय, वे AST को "डॉक्यूमेंट कमांड्स" के एक मध्यवर्ती प्रतिनिधित्व (IR) में बदलते हैं। ये कमांड अधिक अमूर्त होते हैं, जैसे group, indent, softline (एक लाइन ब्रेक जो केवल तभी उपयोग किया जाता है जब कोड एक लाइन में फिट नहीं होता है), और hardline।
प्रिटी-प्रिंटर फिर इन कमांड्स के क्रम को लेता है और उन्हें लेआउट करने का "सबसे अच्छा" तरीका खोजने के लिए एक चतुर एल्गोरिथ्म का उपयोग करता है, जो एक अधिकतम लाइन लंबाई का सम्मान करने की कोशिश करता है। इस तरह फॉर्मैटर स्वचालित रूप से कोड की लंबी लाइनों को एक बुद्धिमान तरीके से रैप कर सकते हैं जो अभी भी पठनीयता को बनाए रखता है।
चरण 3: कॉन्फ़िगरेशन
प्रिटी-प्रिंटर शून्य में काम नहीं कर रहा है। यह कॉन्फ़िगर करने योग्य नियमों के एक सेट का पालन करता है। ये वे सेटिंग्स हैं जो टैब्स-बनाम-स्पेस युद्ध को एक बार और सभी के लिए समाप्त कर देती हैं। एक कॉन्फ़िगरेशन फ़ाइल (जैसे .prettierrc या .editorconfig) प्रिंटर को बताती है:
- इंडेंट स्टाइल:
tabsयाspaces - इंडेंट विड्थ:
2,4, आदि। - अधिकतम लाइन लंबाई:
80,100,120, आदि। - कोट स्टाइल:
singleयाdouble - और दर्जनों अन्य भाषा-विशिष्ट नियम।
टूल इन नियमों को नियतात्मक रूप से लागू करता है। एक ही कोड और एक ही कॉन्फ़िगरेशन दिए जाने पर, यह हमेशा बिल्कुल वैसा ही आउटपुट उत्पन्न करेगा।
असल दुनिया की कहानियाँ
आधी रात की बग हंट
एक डेवलपर, मान लीजिए उसका नाम सारा है, देर रात के डीबगिंग सेशन में गहरे डूबी हुई थी। प्रोडक्शन में एक महत्वपूर्ण फीचर फेल हो रहा था, और लॉग्स कोड के एक विशिष्ट ब्लॉक की ओर इशारा कर रहे थे। वह एक घंटे से ज़्यादा समय तक उस फ़ंक्शन को घूरती रही। लॉजिक सही लग रहा था। एक if/else ब्लॉक के अंदर एक महत्वपूर्ण क्लीनअप कोड चलना चाहिए था। लेकिन उसके डीबगिंग ट्रेस से पता चला कि यह कभी एक्सेक्यूट नहीं हो रहा था। निराश होकर, उसने अनजाने में अपने एडिटर में "फॉर्मेट डॉक्यूमेंट" शॉर्टकट दबाया।
कोड तुरंत बदल गया। "क्लीनअप" ब्लॉक, जिसे वह else के अंदर समझ रही थी, एक लेवल बाईं ओर खिसक गया। ऊपर के ब्लॉक से एक गलत जगह पर लगा हुआ क्लोजिंग कर्ली ब्रेस } ने if/else स्टेटमेंट को समय से पहले समाप्त कर दिया था। दोषपूर्ण इंडेंटेशन ने कोड को सही दिखने पर मजबूर कर दिया था जबकि एक घातक लॉजिक त्रुटि छिपी हुई थी। संरचना को विज़ुअली स्पष्ट किए जाने के साथ, बग 30 सेकंड में ठीक हो गया।
सबक: सही इंडेंटेशन सिर्फ दिखने के लिए नहीं है; यह एक शक्तिशाली डीबगिंग टूल है जो विज़ुअल संरचना को लॉजिकल संरचना के साथ संरेखित करता है।
हजार बदलावों वाला पुल रिक्वेस्ट
एक नया इंटर्न, बेन, अपना पहला योगदान करने के लिए उत्साहित था। काम सरल था: एक कॉन्फ़िगरेशन फ़ाइल में एक सिंगल वेरिएबल बदलना। उसने बदलाव किया और अपना पुल रिक्वेस्ट (PR) सबमिट किया। जब सीनियर डेवलपर ने इसे खोला, तो वह कराह उठा। PR में 200 से अधिक लाइनें बदली हुई दिख रही थीं, भले ही फ़ाइल केवल 200 लाइन की थी। बेन का कोड एडिटर टैब्स का उपयोग करने के लिए कॉन्फ़िगर किया गया था, लेकिन प्रोजेक्ट का मानक दो स्पेस था। उसके एडिटर ने "मददगार" तरीके से पूरी फ़ाइल को फिर से फॉर्मेट कर दिया था। इस शोर में दबे हुए, सीनियर डेवलपर को वह एक-लाइन का बदलाव नहीं मिल रहा था जिसकी उसे समीक्षा करनी थी। उसे PR को अस्वीकार करना पड़ा और बेन से फॉर्मेटिंग को ठीक करके फिर से सबमिट करने के लिए कहना पड़ा।
सबक: एक टीम सेटिंग में, असंगत फॉर्मेटिंग शोर पैदा करती है और समय बर्बाद करती है। कुशल सहयोग के लिए एक साझा, स्वचालित फॉर्मेटिंग रणनीति अनिवार्य है।
PHP मोनोलिथ की खुदाई
एक छोटी टीम को 15 साल पुराने PHP एप्लिकेशन को आधुनिक बनाने के लिए काम पर रखा गया था। जब उन्होंने कोडबेस खोला, तो वे डर से पीछे हट गए। यह एक डिजिटल पुरातात्विक खुदाई स्थल था। दशकों के विभिन्न डेवलपर्स, एडिटर्स, और स्टाइल प्राथमिकताओं ने फॉर्मेटिंग का एक फ्रेंकस्टीन का राक्षस बना दिया था। कुछ फाइलें टैब्स का उपयोग करती थीं, कुछ दो स्पेस, कुछ चार, कुछ आठ। फ़ंक्शन ब्रेसिज़ हर जगह थे। इसे पढ़ना लगभग असंभव था। पहला काम, नई कोड की एक भी लाइन लिखने से पहले, पूरे प्रोजेक्ट पर एक कोड फॉर्मैटर चलाना था। इसे कॉन्फ़िगर करने और चलाने में कुछ घंटे लगे, लेकिन परिणाम परिवर्तनकारी था। कोड, हालांकि अभी भी पुराना और जटिल था, अचानक एक समान और पठनीय हो गया। वे अंततः अंतर्निहित संरचना को देख सकते थे, पैटर्न की पहचान कर सकते थे, और इसे सुरक्षित रूप से रीफैक्टर करने का काम शुरू कर सकते थे।
सबक: एक लिगेसी कोडबेस को काबू में करने में फॉर्मेटिंग पहला और सबसे महत्वपूर्ण कदम है। यह अराजकता में व्यवस्था लाती है और भविष्य के काम को संभव बनाती है।
आम गलतियाँ और जाल
- फॉर्मैटर के आउटपुट को मैन्युअल रूप से 'ठीक' करना। एक ऑटो-फॉर्मैटर का उद्देश्य स्टाइल के लिए सच्चाई का एक एकल, वस्तुनिष्ठ स्रोत होना है। यदि आप वापस जाकर उसके आउटपुट को मैन्युअल रूप से बदलते हैं क्योंकि आपको यह पसंद नहीं है कि उसने लाइन ब्रेक कहाँ रखा है, तो आप असंगति को फिर से पेश कर रहे हैं और पूरे उद्देश्य को विफल कर रहे हैं। टूल पर भरोसा करना सीखें।
- कोड पर एक सामान्य टेक्स्ट इंडेंटर का उपयोग करना। Python और YAML जैसी भाषाएँ "व्हाइटस्पेस-संवेदनशील" हैं, जिसका अर्थ है कि इंडेंटेशन लॉजिक को प्रभावित करता है। एक साधारण टूल का उपयोग करना जो केवल कुछ कैरेक्टर्स के बाद टैब जोड़ता है, आपके कोड को तोड़ सकता है और तोड़ेगा। हमेशा एक ऐसे फॉर्मैटर का उपयोग करें जो विशेष रूप से उस भाषा के लिए डिज़ाइन किया गया हो जिसे आप लिख रहे हैं।
- एक ही कमिट में फॉर्मेटिंग परिवर्तनों को लॉजिक परिवर्तनों के साथ मिलाना। जैसा कि PR कहानी में देखा गया है, यह कोड रिव्यू को दर्दनाक बना देता है। यदि आप किसी फ़ाइल को फॉर्मेट कर रहे हैं, तो केवल फॉर्मेटिंग परिवर्तनों को एक स्पष्ट संदेश के साथ कमिट करें जैसे "chore: format file X"। फिर, अपने कार्यात्मक परिवर्तनों को एक अलग कमिट में करें।
- कॉन्फ़िगरेशन साझा करना भूल जाना। यदि एक टीम के प्रत्येक डेवलपर के पास फॉर्मैटर के लिए थोड़ा अलग कॉन्फ़िगरेशन है, तो आप लगातार बदलाव की स्थिति में रहेंगे, जिसमें फाइलें वर्ज़न कंट्रोल में आगे-पीछे बदलती रहेंगी। कॉन्फ़िगरेशन फ़ाइल (जैसे,
.editorconfig) को प्रोजेक्ट की रिपॉजिटरी में कमिट किया जाना चाहिए ताकि हर कोई ठीक उन्हीं नियमों का उपयोग करे।
यह आपके रडार पर क्यों होना चाहिए
आपको कोड इंडेंटेशन और फॉर्मेटिंग के बारे में लगातार सोचना चाहिए, इस हद तक कि यह एक स्वचालित आदत बन जाए।
- जब आप एक प्रोजेक्ट शुरू करते हैं:
git initके बाद आपको सबसे पहला काम अपने ऑटो-फॉर्मैटर और उसके कॉन्फ़िगरेशन को सेट करना चाहिए। जैसा आप आगे बढ़ना चाहते हैं, वैसी ही शुरुआत करें। - जब आप एक प्रोजेक्ट में शामिल होते हैं: प्रोजेक्ट की स्टाइल गाइड और फॉर्मैटर कॉन्फ़िगरेशन खोजें। अपने एडिटर को तुरंत इसका पालन करने के लिए सेट करें। वह व्यक्ति न बनें जो कोडबेस की साफ-सुथरी शैली को बिगाड़ता है।
- जब आप किसी बग पर अटके हों: समस्या नहीं दिख रही है? फॉर्मैटर चलाएँ। आप आश्चर्यचकित हो सकते हैं कि विज़ुअल स्पष्टता आपके टूटे हुए लॉजिक के बारे में क्या révél करती है।
- जब आप कोड कमिट करने वाले हों: कई टीमें "प्री-कमिट हुक" सेट करती हैं—स्वचालित स्क्रिप्ट जो आपके कमिट करने से पहले चलती हैं। सबसे आम हुक में से एक स्वचालित रूप से आपके द्वारा बदली गई सभी फाइलों को फॉर्मेट करता है। यह गारंटी देता है कि कोई भी बिना फॉर्मेट किया हुआ कोड कभी भी रिपॉजिटरी में नहीं आता है।
अंततः, स्वचालित फॉर्मेटिंग को अपनाना व्यावसायिकता के बारे में है। यह आपके टीम के साथियों और आपके भविष्य के स्व के प्रति सम्मान दिखाता है। यह एक सरल, शक्तिशाली अभ्यास है जो किसी भी सॉफ्टवेयर प्रोजेक्ट की गुणवत्ता और रखरखाव को बढ़ाता है।
और गहराई में जाएं
- Prettier: How it Works - सबसे लोकप्रिय फॉर्मेटर्स में से एक द्वारा उपयोग किए जाने वाले उन्नत प्रिटी-प्रिंटिंग एल्गोरिथ्म का एक सुलभ स्पष्टीकरण।
- EditorConfig - कॉन्फ़िगरेशन फ़ाइल मानक के लिए आधिकारिक साइट जो विभिन्न एडिटर्स और IDEs में सुसंगत कोडिंग शैलियों को बनाए रखने में मदद करती है।
- Wikipedia: Indentation style - विभिन्न स्टाइल और ब्रेस प्लेसमेंट और व्हाइटस्पेस पर हुए "धर्मयुद्ध" के इतिहास का एक व्यापक अवलोकन।
- A prettier printer - फिलिप वाडलर द्वारा लिखा गया मूल अकादमिक पेपर जिसने Prettier जैसे आधुनिक फॉर्मेटर्स की नींव रखी। यह घना लेकिन मौलिक है।
- Google JavaScript Style Guide - एक प्रमुख टेक कंपनी की एक व्यापक स्टाइल गाइड का एक उदाहरण, जिसमें फॉर्मेटिंग पर विशिष्ट नियम हैं।