शनिवारची दुपार. तुम्ही कॉफी घेऊन बसला आहात, एखादे नवीन फीचर पूर्ण करण्याचा किंवा तुमच्या साईड प्रोजेक्टवर काम करण्याचा पूर्ण इरादा आहे. दहा मिनिटांतच सर्व काही थांबते. लॉजिक खूप क्लिष्ट आहे म्हणून नाही. तुम्हाला फ्रेमवर्क समजत नाही म्हणूनही नाही. प्रगती फक्त एका उघड्या राहिलेल्या टॅगमुळे (tag) थांबते.
या वीकेंडच्या आव्हानामध्ये (challenge) नेमके हेच घडले. एक Liquid सिंटॅक्स एरर (syntax error). टॅग योग्यरित्या बंद केला नव्हता. पार्सरने (parser) फाईल वाचली, जिथे क्लोजिंग सिक्वेन्सची अपेक्षा होती तिथे पोहोचला आणि तिथे काहीच आढळले नाही. अगदी तसे, बिल्ड फेल झाले. हा असा प्रकारचा बग आहे जो अनुभवी डेव्हलपर्सनाही नम्र करतो आणि नवशिक्यांना आत्मविश्वासाच्या संकटात टाकू शकतो, जरी एकदा तो समजला की दुरुस्त करण्यासाठी फक्त काही सेकंद लागतात.
अंतर्गत नेमके काय चुकले?
Liquid ही Shopify ने तयार केलेली एक टेम्पलेटिंग लँग्वेज आहे, जी ई-कॉमर्स स्टोअरफ्रंटपासून ते GitHub Pages वरील Jekyll-आधारित ब्लॉग्सपर्यंत सर्व काही चालवते. ती दोन मुख्य सिंटॅक्स पॅटर्नवर अवलंबून आहे. {{ page.title }} प्रमाणे डबल कर्ली ब्रेसेस (curly braces) आउटपुट हाताळतात. {% if user %} किंवा {% for item in list %} प्रमाणे कर्ली ब्रॅकेटमधील टक्केवारी चिन्हे (percent signs) लॉजिक आणि फ्लो कंट्रोल हाताळतात.
प्रत्येक ओपनिंग टॅगला जोडीदार हवा असतो. {% if %} साठी {% endif %} आवश्यक आहे. {% for %} लूपसाठी {% endfor %} आवश्यक आहे. कॅप्चर ब्लॉकसाठी {% endcapture %} आवश्यक आहे. हे केवळ सूचना नाहीत. Liquid इंजिन तुमचे टेम्पलेट क्रमाने वाचते. जेव्हा त्याला एखादे ओपनिंग कन्स्ट्रक्ट (opening construct) आढळते, तेव्हा ते त्याच्या अंतर्गत स्टॅकवर (internal stack) एक फ्रेम पुश करते आणि प्रतीक्षा करते. जर फाईल संपली, किंवा अपेक्षित टॅग येण्यापूर्वीच दुसरा एखादा मोठा ब्लॉक बंद झाला, तर इंजिन एरर देते. संदेश अनेकदा स्पष्ट असतो: tag was not closed correctly. सिस्टीमला क्लोजिंग सिक्वेन्सची अपेक्षा होती. कधीकधी तुम्हाला लाईन नंबर मिळतो. कधीकधी तो लाईन नंबर चुकीच्या ठिकाणी दर्शवतो कारण पार्सरला जोडीदार टॅग गहाळ आहे हे तेव्हाच समजते जेव्हा तो त्याच्या खालील सर्व गोष्टी वाचून पूर्ण करतो.
एक ठोस उदाहरण घेऊया. तुम्ही असे काहीतरी लिहू शकता:
{% for product in collections.all.products %}
<div class="card">
<h2>{{ product.title }}</h2>
{% if product.available %}
<span>In stock</span>
{% endif %}
</div>
{% endfor %}
तिन्ही टॅग्स बंद आहेत. आता कल्पना करा की तुम्ही वेगाने काम करत आहात, डॉक्युमेंटेशनमधून स्निपेट्स (snippets) कॉपी-पेस्ट करत आहात आणि चुकून शेवटचा r राहून गेला आहे:
{% for product in collections.all.products %}
<div class="card">
<h2>{{ product.title }}</h2>
{% if product.available %}
<span>In stock</span>
</div>
{% endfo %}
किंवा कदाचित तुम्ही {% endfor %} पूर्णपणे विसरला असाल कारण तो HTML च्या मोठ्या भागाच्या खाली आहे. इंजिनला {% for % दिसते, लूप रजिस्टर होते, पण जोडीदार कधीच सापडत नाही. Shopify च्या संदर्भात, याचा अर्थ संपूर्ण थीम कंपाईल होण्यास अपयशी ठरते. Jekyll मध्ये, GitHub Pages तुम्हाला बिल्ड फेल्युअरचा ईमेल पाठवते. लोकल डेव्हलपमेंटमध्ये एक गुंतागुंतीचा स्टॅक ट्रेस (stack trace) दिसू शकतो. एक विसरलेला टॅग संपूर्ण पाइपलाइन थांबवू शकतो.
लहान चुकांचा त्रास
या चुका अत्यंत त्रासदायक असतात कारण चुकांच्या आकारानुसार त्यांचे परिणाम वाढत नाहीत. तुम्ही डेटाबेसची रचना चुकीची केली नाही. तुम्ही चुकीचा अल्गोरिदम निवडला नाही. तुम्ही फक्त एक अक्षर विसरलात. लहान चुकांमुळे मोठे बग्स निर्माण होतात. तो गहाळ झालेला {% endif %} फक्त एक ओळ तोडत नाही. त्याचा परिणाम साखळीप्रमाणे (cascade) पसरतो. पार्सर आता कंडिशनल (conditional) कुठे संपते याबद्दल गोंधळलेला असतो, ज्यामुळे त्याच्या खालील प्रत्येक ओळ चुकीची (malformed) वाटू शकते. जे टेम्पलेट वीस ओळींचे दिसते, ते अचानक साठो ओळींचा एरर आउटपुट जनरेट करू लागते, ज्यातील बहुतेक माहिती दिशाभूल करणारी असते.
जेव्हा तुम्ही एक अक्षर विसरता तेव्हा तुम्हाला या चुकांचा सामना करावा लागतो, आणि तुमचा मेंदू या वास्तवासाठी कधीच तयार नसतो. मानवी मेंदू पॅटर्न रिकग्निशनद्वारे (pattern recognition) कोड वाचतो. आपल्याला त्यामागचा हेतू समजतो. आपल्याला if आणि त्याशी जुळणारे लॉजिक दिसते आणि आपण सीमा (boundary) ओळखतो. संगणक असे अनुमान लावत नाही. तो प्रत्येक अक्षर वरून खाली, क्रमाने वाचतो आणि संदिग्धतेसाठी (ambiguity) त्याला शून्य सहनशीलता असते. जेव्हा तो जोडीदार टॅगची प्रतीक्षा करत फाईलच्या शेवटी पोहोचतो, तेव्हा तो हार मानतो. तुमचे काम अशा प्रकारचे डेव्हलपर बनणे आहे जे केवळ ती त्रुटी शोधण्यासाठी पुरेसा वेळ पार्सरसारखा विचार करू शकतील.
हे फक्त Liquid पुरते मर्यादित नाही. Python मधील न बंद झालेले कंसाचे (parenthesis) चिन्ह, Markdown मधील गहाळ झालेला बॅकटिक (backtick), JavaScript मधील विसरलेला ब्रॅकेट, किंवा HTML मधील अर्धवट राहिलेला अँगल ब्रॅकेट (angle bracket). वीकेंड चॅलेंजमध्ये Liquid चा वापर शिकवण्यासाठी केला गेला, परंतु त्यातील मूळ धडा तुम्ही वापरत असलेल्या प्रत्येक भाषेत लागू होतो. सिंटॅक्स म्हणजे व्याकरण आहे, आणि व्याकरण अत्यंत कडक असते.
त्यांना कसे शोधायचे
जेव्हा तुम्ही अशा अडचणीत येता, तेव्हा पहिली प्रतिक्रिया संपूर्ण फाईल घाबरून वाचण्याची असते. तसे करू नका. घाबरून वाचल्यामुळे तुमचा मेंदू चुकीचे अक्षर आपोआप दुरुस्त करतो (autocorrects), ज्यामुळे तुम्ही नेमके तेच अक्षर दुर्लक्षित करता जे चुकले आहे. त्याऐवजी, पद्धतशीरपणे (systematically) काम करा.
तुमच्या टॅग्सना स्पष्टपणे जुळवून घ्या. फाईल तपासा आणि प्रत्येक ओपनिंग टॅग मोठ्याने किंवा कागदावर लिहून नाव द्या. for साठी endfor आवश्यक आहे. if साठी endif आवश्यक आहे. unless साठी endunless आवश्यक आहे. capture साठी endcapture आवश्यक आहे. जर तुम्ही ब्लॉक्स नेस्ट (nest) करत असाल, तर मनातल्या मनात एक काउंटर वाढवत जा. जेव्हा मी for च्या आत if उघडतो, तेव्हा फाईल संपण्यापूर्वी मला दोन जबाबदाऱ्या पूर्ण कराव्या लागतात.
तुमच्या एडिटरचा वापर करा. जर तुम्ही नियमितपणे Liquid वर काम करत असाल, तर व्याकरण ओळखणारा 'syntax highlighter' इंस्टॉल करा. Visual Studio Code मध्ये असे एक्स्टेंशन्स आहेत जे Liquid टॅग्सना डिम (dim) करतील किंवा कलर-कोड करतील. जेव्हा एखादा क्लोजिंग टॅग चुकीचा असतो, तेव्हा कलर पॅटर्न बदलतो. काही linters तुम्ही कंपाईल करण्यापूर्वीच न मिटलेले ब्लॉक्स पकडू शकतात. Vim किंवा Neovim मध्ये, vim-liquid सारखे प्लगइन वापरण्याचा विचार करा किंवा मॅचिंग टॅग्स हायलाइट करण्यासाठी Tree-sitter कॉन्फिगर करा. ही साधने विचार करण्याची गरज संपवत नाहीत, परंतु ती विसंगती (mismatch) दृश्यमान करतात.
तुमच्या टेम्पलेटमध्ये 'binary search' करा. जर एरर मेसेज लाईन २०० कडे निर्देश करत असेल पण तिथे काहीही चुकीचे दिसत नसेल, तर खरा दोष बहुधा त्याच्या वरच्या भागात असू शकतो. टेम्पलेटचा खालचा अर्धा भाग कमेंट (comment out) करा. ते बिल्ड होते का? जर हो, तर एरर कमेंट केलेल्या भागात आहे. त्यातील अर्धा भाग अनकमेंट (uncomment) करा. तो खराब झालेला ब्लॉक शोधेपर्यंत ही प्रक्रिया पुन्हा करा. हे संथ वाटू शकते, परंतु तुमचा ताण वाढत असताना तेच दोनशे ओळी सहा वेळा वाचण्यापेक्षा हे अधिक जलद आहे.
तुमचे includes तपासा. Liquid {% include %} किंवा {% render %} द्वारे मॉड्युलर फ्रॅग्मेंट्सना सपोर्ट करते. न मिटलेला टॅग कदाचित मुख्य फाईलमध्ये नसेल. तो एखाद्या स्निपेटमध्ये (snippet) असू शकतो जो मूळ टेम्पलेटमधून घेतला जातो. येथेच व्हर्जन कंट्रोल (version control) तुमचे मानसिक आरोग्य वाचवते. 'diff' रन करा. शेवटच्या यशस्वी बिल्डपासून काय बदलले आहे ते पहा. अनेकदा उत्तर लाल आणि हिरव्या रंगात स्पष्टपणे दिसते.
इंडेंटेशन (Indentation) म्हणजे डॉक्युमेंटेशन आहे. जर तुमचा {% if %} कॉलम शून्य पासून सुरू होत असेल आणि त्याचा संबंधित {% endif %} एखाद्या नेस्टेड स्ट्रक्चरमध्ये इंडेंट केलेला असेल, तर व्हिज्युअल अलाइनमेंट तुम्हाला विसंगती लक्षात घेण्यास मदत करते. जर तुमचे HTML आणि Liquid टॅग्स एकाच इंडेंटेशन स्कीमचा वापर करत असतील, तर चुकीच्या खोलीवर (depth) असलेला जोडीदार तुमच्या नजरेत येईल.
खरे अभ्यासक्रम (The Real Curriculum)
वीकेंड चॅलेंजेस महत्त्वाचे आहेत कारण ते तुम्ही प्रत्यक्षात काम करत असलेल्या परिस्थितीची हुबेहूब प्रतिकृती तयार करतात. कोणताही मॅनेजर पाहत नाहीये. कोणतीही डेडलाईन दबाव आणत नाहीये. तुम्ही कौशल्यासाठी किंवा मनोरंजनासाठी कोडिंग करत असता आणि अचानक एक सूक्ष्म त्रुटी तुम्हाला थांबवते. तो क्षणच खरा धडा आहे. तुम्ही डीबगिंगबद्दल वाचून डीबगिंग शिकत नाही. जेव्हा तुम्हाला बाहेर फिरायला जायचे असते, तेव्हा एखादा खराब झालेला बिल्ड समोर पाहून आणि एरर मेसेजला टीका म्हणून न घेता डेटा म्हणून स्वीकारण्यास स्वतःला भाग पाडून तुम्ही डीबगिंग शिकता.
या त्रुटी सुधारण्यास शिका कारण त्या कधीही पूर्णपणे संपत नाहीत. करिअरमध्ये दहा वर्षे पूर्ण झाली तरी, शुक्रवारी रात्रीच्या डिप्लॉयमेंट दरम्यान तुम्ही क्लोजिंग टॅग विसरू शकता. ज्युनियर आणि सीनियर डेव्हलपरमधील फरक चुकांचा अभाव नसून, ते रिकव्हरीच्या वेगावर अवलंबून असतो. सीनियर सिंटॅक्स एरर पाहतो, पॅटर्न ओळखतो, स्पष्ट संशयित गोष्टी तपासतो आणि पुढे जातो. ज्युनियरला वाटते की संपूर्ण टूलचेनच खराब झाली आहे. पुनरावृत्तीमुळे तो रिफ्लेक्स (reflex) तयार होतो.
कम्युनिटीचा पैलू या प्रक्रियेला वेग देतो. जेव्हा अनेक लोक वीकेंडमध्ये एकाच खराब टेम्पलेटवर काम करतात, तेव्हा असे पॅटर्न समोर येतात जे कोणताही एक डेव्हलपर एकट्याने पाहू शकत नाही. कोणीतरी लक्षात आणून देतो की एरर फक्त नेस्टेड for लूपमध्येच येते. कोणीतरी असा शेल स्क्रिप्ट शेअर करतो जो सामान्य Liquid टॅग विसंगती शोधण्यासाठी 'grep' करतो. ज्ञान साठवून ठेवण्यापेक्षा ते एकमेकांसोबत शेअर केल्यावर ते अधिक वाढते. तुम्ही या विशिष्ट चॅलेंजचे पूर्ण तपशील वाचू शकता आणि इतरांनी ते कसे हाताळले ते पाहू शकता या Dev.to पोस्टवर. जर तुम्हाला समान समस्यांवर काम करणाऱ्या लोकांशी चर्चा करायची असेल, तर टेलिग्रामवर एक पर्यायी लर्निंग कम्युनिटी आहे जिथे या चर्चा वीकेंडनंतरही सुरू राहतात.
मुख्य निष्कर्ष (The Takeaway)
सिंटॅक्स एरर्सना तुमच्या खऱ्या कामातील अडथळा समजू नका. ते कामाचाच एक मूलभूत भाग आहेत. या वीकेंडचा बिल्ड मोडणारा Liquid टॅग हा केवळ टेम्पलेट इंजिनबद्दल नव्हता. जेव्हा तुमचे मेंदू अंदाज लावू इच्छित असतो, तेव्हा अचूकतेने वाचण्याचे प्रशिक्षण स्वतःला देण्याबद्दल होता. गेल्या आठवड्यात तुम्ही लिहिलेली फाईल उघडा. तुम्ही उघडलेल्या टॅग्सचा शोध घ्या. प्रत्येक टॅग योग्यरित्या बंद केला आहे याची खात्री करा. तुमचे लूप्स बंद करा. तुमच्या कंडिशनल्सना (conditionals) पूर्ण करा. आणि मग पुन्हा एकदा, प्रत्येक अचूक कॅरेक्टरसह बिल्डिंगकडे वळा.
