“Why Not” टिप्पणियाँ क्यों ज़रूरी हैं
(buttondown.com)- टिप्पणियाँ identifiers की तुलना में अधिक अभिव्यंजक मानवीय भाषा का उपयोग कर सकती हैं, इसलिए वे कोड में मौजूद न होने वाले विकल्पों और छोड़े गए alternatives को दर्ज करने के लिए उपयुक्त हैं
- “comment the why, not the what” को इस तरह समझा जा सकता है कि अधिकतम जानकारी identifiers में डाली जाए, लेकिन हाल में कारण तक को लंबे function names या test names में ले जाने की प्रवृत्ति बढ़ी है
Logic for Programmersके epub build में 16 mathematical symbols को हर string पर क्रमशः replace करने वाला धीमा implementation इस्तेमाल किया गया, लेकिन अभी mathematical strings सिर्फ 25 हैं इसलिए यह काफी तेज़ है- ऐसी टिप्पणियाँ बाद में, जब mathematical strings सैकड़ों तक बढ़ जाएँ और build bottleneck बन जाए, तब यह बताती हैं कि कहाँ सुधार करना है, और यह भी दर्ज करती हैं कि धीमा कोड एक सचेत trade-off था
- function names या tests कोड के वास्तव में किए जाने वाले काम से जुड़े होते हैं, इसलिए चुने न गए alternatives और न किए जाने वाले काम जैसी नकारात्मक जानकारी को self-documenting रूप में उनमें रखना कठिन है
ऐसी जानकारी जिसे टिप्पणियाँ कोड से आसान तरीके से समेट सकती हैं
- कोड एक structured machine language है, जबकि टिप्पणियाँ अभिव्यंजक मानवीय भाषा में लिखी जाती हैं
- “comment the why, not the what” का अर्थ यह निकाला जा सकता है कि जितनी संभव हो उतनी जानकारी identifiers में रखी जाए
- identifiers कोड के भीतर शामिल एक सीमित मानवीय भाषा के अधिक करीब होते हैं, और वे हर “what” को नहीं समेट सकते, लेकिन कई मामलों में काफी कुछ समेट सकते हैं
- हाल के दिनों में यह मत बढ़ा है कि “why” भी टिप्पणी के बजाय लंबे function names या test case names में डाला जा सकता है
- self-documenting codebase आम तौर पर अधिक identifiers जोड़कर documentation बढ़ाते हैं
- एक अपवाद के रूप में, ऐसा उदाहरण मिलता है जहाँ टिप्पणियों को logging में बदलकर कोड को अधिक self-documenting बनाया जाता है
“Why Not” टिप्पणियाँ क्या संभालती हैं
- वह जानकारी जिसे कोड में व्यक्त करना कठिन है, वह है नकारात्मक जानकारी
- नकारात्मक जानकारी इस बात पर ध्यान खींचती है कि system में क्या नहीं है, या कोई खास alternative क्यों नहीं चुना गया
- “why not” कोड क्या करता है यह बताने के बजाय, यह दर्ज करता है कि कोड कौन-से विकल्प नहीं अपनाता और क्यों
epub में mathematical symbol replacement का उदाहरण
Logic for Programmersके epub build में तकनीकी कारणों से\\forallजैसी mathematical notation∀जैसे symbols में convert नहीं हो रही थी- इसे ठीक करने के लिए mathematical strings के भीतर tokens को सीधे उनके Unicode equivalent symbols से बदलने वाली script लिखी गई
- सबसे आसान implementation यह था कि ज़रूरी 16 mathematical symbols में से हर एक के लिए
string = string.replace(old, new)call किया जाए - यह तरीका हर string को 16 बार traverse करता है, इसलिए inefficient है, लेकिन एक ही traversal में सभी 16 replacements करने का तरीका अधिक complex है
- छोड़ी गई टिप्पणी का सार यह था:
- हर string को 16 बार traverse किया जाता है
- अभी किताब में mathematical strings सिर्फ 25 हैं और उनमें से अधिकांश 5 characters से छोटे हैं
- इसलिए यह अब भी काफी तेज़ है
- यह टिप्पणी सिर्फ “धीमा कोड क्यों लिखा गया” नहीं, बल्कि “तेज़ कोड क्यों नहीं लिखा गया” भी समझाती है
भविष्य के पाठक के लिए संकेत-पट्ट
- धीमा कोड अभी समस्या न पैदा करे, फिर भी बाद में समस्या बन सकता है
- अगर
Logic for Programmersके भविष्य के versions में mathematical strings सैकड़ों तक बढ़ जाएँ, तो वह build step पूरे build का bottleneck बन सकता है - अभी संकेत छोड़ देने से बाद में तुरंत पता चल सकता है कि किस हिस्से को ठीक करना है
- भले ही कोड लगातार बिना समस्या काम करता रहे, टिप्पणी यह तथ्य सुरक्षित रखती है कि लेखक trade-off से अवगत था
- 2 साल बाद
epub_math_fixer.pyफिर से खोलने पर यह दोबारा जाँचने की ज़रूरत कम हो जाती है कि धीमा कोड अनुभवहीनता, समय की कमी, या गलती की वजह से था या नहीं - नकारात्मक टिप्पणी यह जानकारी छोड़ती है कि धीमे implementation के बारे में जानकारी थी, alternatives पर विचार किया गया था, और optimize न करने का निर्णय लिया गया था
function names और tests से इसे बदलना कठिन क्यों है
RunFewerTimesSlowerAndSimplerAlgorithmAfterConsideringTradeOffsजैसा function name बहुत लंबा है, और वास्तविक trade-off को पर्याप्त रूप से समझा भी नहीं पाता- बाद में कोड optimize करने पर उस नाम को कई जगह बदलना पड़ सकता है
- इससे भी बड़ी समस्या यह है कि ऐसा नाम function वास्तव में क्या करता है यह नहीं बताता, इसलिए self-documentation को उल्टा कमज़ोर कर देता है
- function names और variable names जैसे identifiers जानकारी का सिर्फ एक clause समेट सकते हैं
- एक ही identifier में “function क्या करता है” और “function कौन-सा trade-off स्वीकार करता है” दोनों को साथ रखना कठिन है
tests में भी नकारात्मक जानकारी दर्ज करना मुश्किल है
- किताब में mathematical blocks को grep करके अगर उनकी संख्या 80 से ऊपर जाए तो fail होने वाला test बनाया जा सकता है
- लेकिन ऐसा test
EpubMathFixerको सीधे test नहीं करता - function के भीतर ऐसा कोई point नहीं है जहाँ वह test hook कर सके
- self-documentation लिखे गए कोड के साथ जुड़कर यह समझाती है कि कोड क्या करता है
- नकारात्मक जानकारी उस काम से संबंधित होती है जो कोड नहीं करता, इसलिए यह self-documenting तरीके से मूल रूप से मेल नहीं खाती
एक बड़ा सवाल
- “why not” टिप्पणियों को counterfactual का एक उदाहरण माना जा सकता है
- यह सवाल बना रहता है कि क्या मानवीय संचार के abstract तत्व सामान्य रूप से self-documenting हो सकते हैं
- metaphor, uncertainty, ethical claims जैसी जानकारी भी self-documenting हो सकती है या नहीं, यह अब भी एक खुला प्रश्न है
1 टिप्पणियां
Hacker News की रायें
कुछ साल पहले Twitter पर देखा हुआ एक मज़ाक याद आता है: “जूनियर इंजीनियर ऐसे comments लिखते हैं जो बताते हैं कि code क्या करता है, मिड-लेवल इंजीनियर ऐसे comments लिखते हैं जो बताते हैं कि code ऐसा क्यों करता है, और सीनियर इंजीनियर ऐसे comments लिखते हैं जो बताते हैं कि code किसी और तरीके से क्यों नहीं लिखा गया” — कुछ ऐसा ही था
इसके उलट, अगर function name और variable name से ही अर्थ साफ हो सकता था, तो मैंने काफी बड़े functions भी बिना comment के लिखे हैं
इसलिए कम comments वाली तरफ़ की जीत तो होती है, लेकिन किसी comment-free codebase को देखकर यह समझने के लिए खुद देखना पड़ता है कि वह खूबसूरती से तराशी गई masterpiece है या beginners द्वारा बनाया गया अस्थिर code
यह पूरा workaround जैसा दिखे, फिर भी कभी-कभी सच में वही सबसे अच्छा होता है जो हासिल किया जा सकता है
अगर 1 साल बाद code फिर देखने पर यह मेरे लिए उपयोगी लगेगा, तो मैं सब कुछ comment में छोड़ देता हूँ। आम तौर पर यह क्यों और क्यों नहीं होता है, और जब code जटिल होता है तो flow बेहतर देखने के लिए छोटा सा “क्या” भी लिखता हूँ
जो उपयोगी नहीं है, वह mandatory comments हैं। Public API को पर्याप्त रूप से document करना चाहिए, लेकिन कुछ organizations private functions तक हर function पर comment enforce करती हैं, और उद्देश्य इतना obvious होता है कि वह function name को दोहराने जैसा बन जाता है। यह सिर्फ समय की बर्बादी नहीं, बल्कि comments के प्रति संवेदनहीन बनाकर उन्हें ignore करने की आदत सिखाता है
Tools द्वारा जोड़े जाने वाले wasteful comments भी मुझे पसंद नहीं। हर loop पर
//forया//tryलगाना खास तौर पर खराब लगता हैMandatory और generated comments हटाकर, dark themes में comments को चमकीले neon colors में बदलना बेहतर है ताकि वे नज़र आएं। अगर comment लगा है, तो उसका मतलब होना चाहिए कि वह महत्वपूर्ण है
Tight schedules वाले business environment में पुराने बड़े systems maintain करने हों तो कभी-कभी अजीब काम करने पड़ते हैं, और तब यह समझाना पड़ता है कि ऐसा क्यों है
Comments के खिलाफ़ एक बड़ा कारण यह है कि comments भी code का हिस्सा बन जाते हैं और maintenance मांगते हैं। लेकिन ज़्यादातर लोग सिर्फ अटकने पर comments पढ़ते हैं, और editors भी comments को gray करके फीका कर देते हैं, जिससे वे मनोवैज्ञानिक रूप से अदृश्य हो जाते हैं। इसलिए comments आसानी से पुराने पड़ जाते हैं
मुझे जिज्ञासा है कि “future me” के लिए context देना, कई developers द्वारा छुए जाने वाले shared codebase में भी उपयोगी है या यह तरीका तब बेहतर चलता है जब code को सिर्फ कुछ ही लोग छूते हैं
इसलिए मैंने मौजूदा comment में “=> yes!” जोड़ दिया, और अपने पुराने self का आभारी हुआ कि उसने वह सवाल document करके छोड़ा था। काम में, खासकर bug fixes के दौरान, मैं अक्सर unclear change के ऊपर ticket number के साथ एक-दो line का comment छोड़ देता हूँ
Code में छोड़े गए comments में मेरा सबसे पसंदीदा format यह template है: “DEAR MAINTAINER: यह code [कारण] की वजह से ऐसा है। अगर आप इसे ‘ठीक’ करने की कोशिश करते हुए समझ जाएँ कि यह भयानक गलती थी, तो अगले व्यक्ति के लिए warning के तौर पर
total_hours_wasted_here = ncounter बढ़ा दें”मैं original author नहीं हूँ, लेकिन एक-दो बार आभार के साथ इस्तेमाल किया है, और सिर्फ counter बढ़ाने वाली one-line commit देखना मजेदार था
एक अधिक senior engineer ने codebase संभाला और सब कुछ loop-based तरीके से “ठीक” कर दिया, और email में यह lecture देने की कोशिश की कि recursion क्यों खराब है, लेकिन उसका code असल requirements पूरी नहीं कर पाया और आखिर में उसने मूलतः वही चीज़ें फिर से बना डालीं जो मैंने recursion से की थीं
बाद में उसने अपनी कुछ बातों के लिए माफी तो मांगी, लेकिन अगर ऊपर ऐसा comment लगा दिया होता, तो पूरा मामला टाला जा सकता था
मैं सहमत हूँ कि title ambiguous है, और इसलिए मैंने article पढ़ा। व्यक्तिगत रूप से मैं overall कम comments पसंद करता हूँ, लेकिन article में आए explanatory comments निश्चित रूप से valuable हैं। यह अच्छी याद दिलाता है कि क्यों ऐसा किया गया, और दूसरा तरीका क्यों नहीं चुना गया
खासकर अपने उस code पर लागू होता है जिसे 5, 10, 15 साल बाद भी maintain करना है। हाल ही में एक colleague के नए code की review करते हुए मैंने सोचा, “ऐसा क्यों किया?”, और 10 lines ऊपर 8 साल पहले मेरे द्वारा ठीक वही करने का कारण मौजूद था। उस colleague ने maintenance का core rule follow किया था: यानी उसे existing code जैसा दिखाना
यह बस उस व्यापक सिद्धांत का एक खास मामला है जिसका पालन करना चाहिए: कोड पढ़ते समय जो चीज़ चौंकाने वाली हो उस पर comment लिखें
कोड लिखते समय अगर कोई व्यक्ति मन ही मन लगातार पूछता है “क्या मैं बाद में इस कोड को समझ पाऊँगा?” और हर बार सहज रूप से “हाँ” जवाब देता है, तो वह घमंडी है और अक्सर गलत होता है। अगर जवाब “पक्का नहीं” है, तो अगला सवाल स्वाभाविक रूप से “क्यों?” होता है, और उसी का जवाब comment में लिखा जाना चाहिए
कभी-कभी जवाब होता है “क्योंकि पढ़ने वाले को यह जिज्ञासा हो सकती है कि इसे किसी और तरीके से क्यों नहीं लिखा गया,” और यही इस लेख में चर्चा किया गया खास मामला है। लेकिन कभी-कभी जवाब होता है “यह कैसे काम करता है या सही क्यों है, यह स्पष्ट नहीं है,” और तब अलग तरह के comment की ज़रूरत होती है
ऐसा आम तौर पर strings को काटने या किसी अजीब data structure को intermediate step के रूप में explore करते समय होता है
Identifiers ही आपको काफी दूर तक ले जा सकते हैं, लेकिन अंत तक नहीं। निजी तौर पर मुझे public methods या variables, fields, parameters के लिए jsdoc/xmldoc जैसे documentation comments की मांग करना पसंद है
method का नाम अच्छा रखना भी महत्वपूर्ण है, लेकिन वह क्या करता है इसे छोटा लिखकर देखने से बात और स्पष्ट हो जाती है, खासकर obvious खामियाँ सामने आती हैं। पहला वाक्य लिखते ही अक्सर बेहतर नाम सूझ जाता है, और अगर explanation में “और” आने लगे, तो यह संकेत है कि method बहुत ज्यादा काम कर रहा है और उसे अधिक logical तरीके से तोड़ा जा सकता है
properties इतनी स्पष्ट लग सकती हैं कि उन्हें documentation की ज़रूरत नहीं, लेकिन
/** The API key */ string ApiKey;जैसी चीज़ में बहुत कुछ missing है। यह key कहाँ से आती है, क्या यह केवल internal use के लिए है या external systems के साथ भेजी-ली जाती है, क्या यह required है, क्या null या empty value संभव है, क्या maximum length है, invalid value हो तो क्या होगा, क्या पढ़ने के लिए और code या documentation है—इनमें से कुछ पता नहीं चलतामूल लेखक के लिए यह जानकारी लिखने में 1–2 मिनट लगेंगे, लेकिन किसी नए व्यक्ति को इसे modify या use करते समय, या कुछ साल बाद bug fix करने के लिए लगाए जाने पर, यह पता लगाने में कई घंटे लग सकते हैं
Code review में अगर अंदाज़ा हो कि बहुत ज्यादा बारीकी से टोकने वाला reviewer क्या कहेगा, तो अक्सर “Y की वजह से X नहीं किया” जैसे comments लिखता हूँ। मकसद परेशान करने वाली round-trip discussions को कम करना होता है
“हर string को 16 बार traverse करता है, लेकिन book में अब तक सिर्फ 25 formula strings हैं और ज्यादातर 5 characters से कम हैं, इसलिए यह काफी fast है” जैसे comment के दूसरे variants भी हैं
यानी ऐसा debug log डालना जो तब trigger हो जब input मूल design constraints से बहुत बड़ा हो जाए। यह future developer को लगभग वही message देता है, लेकिन जल्दी पकड़ में आता है, जिससे diagnosis और debugging time और कम हो सकता है
आदर्श logging और observability system हो तो app के हर component का समय नापेगा और debug information बार-बार छोड़ेगा, लेकिन असल में ऐसा perfect system कौन use करता है। जिन हिस्सों में बाद में performance खराब हो सकती है या जिन्हें optimize करने का समय नहीं मिला, उनमें खास तौर पर logs डालने की कोशिश ज़्यादा महत्वपूर्ण है
पीछे मुड़कर देखें तो यह obvious idea है, लेकिन अब तक तरीका यह था कि जहाँ बाद में फिर देखना होगा वहाँ comment छोड़ देता था, और उम्मीद करता था कि जब चीज़ें बिगड़ेंगी तो वह comment याद रहेगा
कोई कुछ भी कहे, मैं code में जगह-जगह comments और documentation comments बहुत लिखता हूँ। बस तरीका उल्टा रखता हूँ: पहले application के steps की सूची को मोटे तौर पर comments के रूप में लिखता हूँ, फिर development के दौरान बड़े steps को छोटे steps में तोड़ता हूँ, कभी मूल comments हटाता हूँ, कभी छोड़ देता हूँ, और comments को तब तक refine करता रहता हूँ जब तक वह लगभग पूरा algorithm न बन जाए
आम तौर पर मैं बाहर से अंदर की ओर code करता हूँ, इसलिए comments को तोड़ते समय code भी साथ-साथ लिखता हूँ। कभी-कभी पहले एक साथ खूब code कर लेता हूँ और बाद में इतने comments जोड़ता हूँ कि ज़्यादातर लोग ऊब जाएँ। हर function और variable के साथ explanation जोड़ता हूँ, और
deg_to_radfunction पर भी"""Converts degrees to radians."""लगाता हूँ। storage सस्ता है, इसलिएमुझे पता है कि ज़्यादातर लोगों को यह पसंद नहीं है, लेकिन ठीक है। अगर देखना नहीं चाहते, तो script से हटा दें या code review में हटा दें। फिर भी बिना comments वाले किसी और के code की तुलना में अपना पुराना code पढ़ना मुझे कहीं ज़्यादा अच्छा लगता है। Python में Flask API जैसे सरल boilerplate code आम तौर पर self-documenting होते हैं, लेकिन उल्टा ऐसे ही boilerplate में बदलाव ज़्यादा होते हैं और वहाँ महत्वपूर्ण comments लग जाते हैं। industry में algorithms वाले हिस्से अक्सर पूरे के पूरे दोबारा लिख दिए जाते हैं
आगे भी मुझे comments और documentation comments पसंद रहेंगे
मुझे दिमाग में पूरी conceptualization करना पसंद है, और शुरुआती चरण में कई design options को सचमुच लिखकर प्रयोग करना धीमा लगता है। इसलिए जब design choice तय हो जाए, तो उसे document करना ज़रूरी है। क्योंकि बाकी लोग अभी मेरे दिमाग तक पहुँच नहीं सकते
details के बारे में उम्मीद करता हूँ कि जब दूसरे लोग भी conceptualization पूरी कर लेंगे, तो वे ज़्यादा स्पष्ट हो जाएँगी। लेकिन अगर किसी वजह से वह conceptualization न हो पाए, तो पढ़ना और मुश्किल हो सकता है, इसलिए कम-से-कम basic readability बनाए रखने के लिए अतिरिक्त polishing करता हूँ
अक्सर comments update करना भी code ठीक करने जितना ही काम बन जाता है। इसलिए realistic तौर पर comments आम तौर पर झूठ बनने के इंतज़ार में होते हैं। आखिरकार comments और code अलग दिशा में चले जाते हैं, और यह बिना comments वाले code से भी बुरा हो सकता है
इसकी जगह intent दिखाने वाले automated tests बेहतर हैं। tests आम तौर पर झूठ नहीं बोल सकते, क्योंकि अगर ऐसा होता तो उन्हें merge नहीं किया गया होता। अगर tests का एक ठीक-ठाक सेट हो जो दिखाए कि code को कैसे इस्तेमाल करने का इरादा था, तो मैं उसे देखना चाहूँगा, क्योंकि वह explanatory भी है और लगभग सच होने की guarantee भी देता है
5 हफ्ते बाद फिर देखना पड़े तो यह बेहद मददगार होता है
मैं “comments भविष्य के अपने-आप को भेजी गई माफ़ी हैं” वाली सोच अपनाता हूँ
अगर code अजीब है या धीमा है, या ऐसा हिस्सा है जिसे किसी को समझाते समय कहना पड़े कि “थोड़ा rough है”, तो आम तौर पर comment छोड़ता हूँ। खासकर अगर पहले उसे बदलकर देखा हो, तो क्या काम नहीं किया था या क्या fix किया था, आदि document करता हूँ
इस कसौटी से चलें तो गैर-ज़रूरी comments स्वाभाविक रूप से हट जाते हैं, और आम तौर पर सच में ज़रूरत होने पर ही क्यों को document किया जाता है। अपने codebase में इसे करीब एक महीने आज़माएँ, तो अंदाज़ा हो जाएगा