5 पॉइंट द्वारा GN⁺ 2025-06-18 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • जटिलता डेवलपमेंट में सबसे ख़तरनाक तत्व है
  • असली दक्षता "80/20 solution" जैसे व्यावहारिक अप्रोच से आती है जो जटिलता से बचते हैं
  • टेस्टिंग और रिफैक्टरिंग के प्रति संतुलित और लचीला रवैया बनाए रखना महत्वपूर्ण है
  • टूल्स के उपयोग और पढ़ने व मेंटेन करने में आसान कोड लिखने की आदत अपनाने पर ज़ोर दिया गया है
  • अत्यधिक abstraction और ट्रेंड्स से सावधान रहने तथा सादगी को अपनाने की सलाह दी गई है

परिचय

  • यह लेख लंबे समय तक सॉफ़्टवेयर बनाते हुए अनुभव से सीखी गई बातों को समेटने वाले Grug Brain डेवलपर के विचारों का संग्रह है
  • Grug Brain डेवलपर खुद को बहुत स्मार्ट नहीं मानता, लेकिन लंबे समय तक प्रोग्रामिंग करते हुए उसने बहुत कुछ सीखा है
  • वह चाहता है कि दूसरे लोग गलतियों से सीखें, इसलिए अपनी समझ को आसान और मज़ेदार तरीके से साझा करता है
  • जटिलता ही डेवलपर जीवन की सबसे बड़ी दुश्मन है
  • जटिलता कोडबेस में चुपके से घुस जाती है, और जो कोड शुरू में समझने में आसान था, उसे धीरे-धीरे बदलना लगभग असंभव बना देती है

जटिलता के दानव से निपटना

  • जटिलता एक अदृश्य आत्मा की तरह बिना शोर किए भीतर घुसती है, और project manager तथा non-Grug डेवलपर अक्सर इसे ठीक से पहचान नहीं पाते
  • जटिलता को रोकने का सबसे अच्छा तरीका है "नहीं" कहना
    • "मैं यह feature नहीं बनाऊँगा"
    • "मैं यह abstraction नहीं लाऊँगा"
    • बेशक, करियर के हिसाब से ज़ोर से "हाँ" कहना ज़्यादा फ़ायदेमंद हो सकता है, लेकिन Grug Brain डेवलपर अपने प्रति ईमानदार विकल्प को महत्व देता है
  • परिस्थितियों के अनुसार समझौता ("ok") भी ज़रूरी है, और ऐसे मामलों में वह 80/20 solution (Pareto law) से समस्या को सरल तरीके से हल करना पसंद करता है
  • project manager को सब कुछ बताए बिना, असल में 80/20 तरीके से काम पूरा कर देना भी एक समझदार रणनीति है

कोड संरचना और abstraction

  • कोड की सही इकाइयाँ (cut points) समय के साथ स्वाभाविक रूप से सामने आती हैं, इसलिए शुरुआती abstraction से बचना बेहतर है
  • अच्छा cut point वह है जिसका बाकी सिस्टम के साथ interface संकरा हो
  • जल्दी abstraction करने की कोशिश अक्सर विफल होती है, और अनुभवी डेवलपर कोड का आकार कुछ स्थिर होने के बाद धीरे-धीरे संरचना बनाते हैं
  • कम अनुभवी या “big brain” डेवलपर प्रोजेक्ट की शुरुआत में ही ज़रूरत से ज़्यादा abstraction करने लगते हैं, जिससे maintenance का बोझ रह जाता है

टेस्ट रणनीति

  • टेस्टिंग के प्रति लगाव और संतुलन दोनों महत्वपूर्ण हैं
  • वह prototyping के बाद, जब कोड कुछ हद तक स्थिर हो जाए, तब टेस्ट लिखना पसंद करता है
  • unit test शुरुआती चरण में काम आते हैं, लेकिन व्यवहार में बीच का स्तर (integration test) सबसे ज़्यादा असरदार होता है
  • end-to-end test भी ज़रूरी हैं, लेकिन अगर बहुत ज़्यादा हों तो maintenance असंभव हो सकता है, इसलिए केवल आवश्यक paths की सीमित संख्या रखनी चाहिए
  • bug report आने पर, bug ठीक करने से पहले उसका reproduction test ज़रूर जोड़ा जाना चाहिए

प्रोसेस, Agile, रिफैक्टरिंग

  • Agile Grug डेवलपर के लिए बुरा नहीं है, और सबसे ख़राब भी नहीं, लेकिन "Agile shaman" से बहुत ज़्यादा उम्मीद रखना ख़तरनाक है
  • prototyping, टूल्स और अच्छे सहकर्मी वास्तव में ज़्यादा महत्वपूर्ण सफलता कारक हैं
  • refactoring भी अच्छी आदत है, लेकिन बड़ा और ज़बरदस्ती किया गया refactoring ख़तरनाक होता है
  • जटिल abstraction को ज़बरदस्ती लाना उल्टा प्रोजेक्ट की विफलता का कारण बन सकता है

मेंटेनेंस, पूर्णतावाद और विनम्रता

  • मौजूदा सिस्टम को बिना वजह उखाड़-पछाड़ करना ख़तरनाक है, और “यह संरचना क्यों है, पता नहीं” कहकर उसे बस हटा देना अच्छी आदत नहीं है
  • परफ़ेक्ट कोड का सपना देखने वाला आदर्शवाद, व्यवहार में, अधिकतर समस्याएँ पैदा करता है
  • अनुभव बढ़ने के साथ यह गहराई से महसूस होता है कि “जो कोड काम कर रहा है, उसका सम्मान” करना चाहिए

टूल्स और उत्पादकता

  • अच्छे डेवलपमेंट टूल्स (IDE code completion, debugger आदि) उत्पादकता को बहुत बढ़ाते हैं, और उन्हें गहराई से समझना महत्वपूर्ण है
  • type system की असली क़ीमत “auto-complete” और गलती से बचाव में है, और अत्यधिक abstraction तथा generics उल्टा ख़तरनाक हो सकते हैं

कोड स्टाइल और दोहराव

  • ज़्यादा पढ़ने योग्य और debug करने में आसान कोड के लिए, condition expressions को कई लाइनों में बाँटने जैसी शैली की सिफ़ारिश की गई है
  • DRY(Don’t Repeat Yourself) सिद्धांत का सम्मान किया जाता है, लेकिन बार-बार आने वाले कोड को ज़बरदस्ती हटाने से ज़्यादा संतुलन महत्वपूर्ण है
  • कई स्थितियों में साधारण दोहराव, जटिल DRY implementation से बेहतर होता है

सॉफ़्टवेयर डिज़ाइन सिद्धांत

  • SoC(Separation of Concerns) सिद्धांत से ज़्यादा behavior locality को पसंद किया जाता है, और यह तर्क दिया जाता है कि “जो कोड वह व्यवहार करता है, वही उस object में होना चाहिए ताकि maintenance आसान रहे”
  • callback/closure, type system, generics, abstraction आदि का सीमित और उचित उपयोग करने की चेतावनी दी गई है
  • closure का ज़रूरत से ज़्यादा उपयोग JavaScript में "callback hell" बना सकता है

लॉगिंग, संचालन

  • logging बहुत महत्वपूर्ण है; हर प्रमुख branch पर इसे छोड़ा जाना चाहिए, और cloud environment में request ID आदि के ज़रिए trace किया जा सके, ऐसा सेटअप होना चाहिए
  • dynamic log level और user-specific log का उपयोग कर सकें, तो चल रहे सिस्टम में समस्या ट्रैक करने में बहुत मदद मिलती है

concurrency, optimization

  • concurrency में केवल अधिकतम सरल मॉडल (stateless web requests, अलग worker queue आदि) पर भरोसा किया जाता है
  • optimization केवल तब करने की सलाह दी जाती है जब वास्तविक performance profile data उपलब्ध हो
  • network I/O जैसे छिपे हुए costs पर ध्यान देना चाहिए; केवल CPU complexity देखकर निर्णय लेना ख़तरनाक है

API डिज़ाइन

  • अच्छा API इस्तेमाल में आसान होना चाहिए, और बहुत जटिल डिज़ाइन या abstraction डेवलपर अनुभव को नुकसान पहुँचाते हैं
  • "use case के अनुरूप simple API" और "जटिल case भी implement किए जा सकें ऐसा layered API" ढाँचा सुझाया गया है

parser डेवलपमेंट

  • recursive descent parser को अकादमिक दुनिया में कम आंका जाता है, लेकिन वास्तविक production code के लिए यह सबसे उपयुक्त और सबसे आसानी से समझ आने वाला तरीका है
  • parser डेवलपमेंट के अधिकतर अनुभव के अनुसार, tools से generate किए गए parser इतने जटिल हो जाते हैं कि समस्या हल करने में उल्टा नुकसान करते हैं
  • सुझाई गई किताबों में "Crafting Interpreters" को सर्वश्रेष्ठ बताया गया है, और इसमें बहुत सी व्यावहारिक सलाह है

फ्रंटएंड और रुझान

  • modern frontend (React, SPA, GraphQL आदि) उल्टा जटिलता के दानव को और बुलाते हैं, और कई बार अनावश्यक होते हैं
  • Grug खुद htmx, hyperscript जैसे सरल टूल्स के ज़रिए जटिलता घटाने का तरीका पसंद करता है
  • frontend में लगातार नए प्रयोग होते रहते हैं, लेकिन यह ध्यान रखना चाहिए कि उनमें पुराने विचारों की पुनरावृत्ति भी बहुत होती है

मनोवैज्ञानिक पहलू, imposter syndrome

  • ज़्यादातर डेवलपर कई बार ऐसा महसूस करते हैं कि “मुझे नहीं पता मैं क्या कर रहा हूँ”, और FOLD(Fear Of Looking Dumb) जैसी स्थिति से मुक्त होने की ज़रूरत है
  • जब senior डेवलपर खुलकर कहते हैं कि “यह मुझे भी कठिन लगता है, यह बहुत जटिल है”, तो junior डेवलपर भी दबाव कम महसूस कर सकते हैं
  • imposter syndrome एक आम भावना है, और सीखते हुए आगे बढ़ना पूरी तरह संभव है—यह बात प्रोत्साहित की गई है

निष्कर्ष

  • प्रोग्रामिंग में जटिलता से हमेशा सावधान रहना चाहिए, और सादगी बनाए रखना सफल डेवलपमेंट की कुंजी है
  • अनुभव, टूल्स का प्रभावी उपयोग, विनम्रता, और वास्तव में काम करने वाले कोड का सम्मान लंबे समय में अधिक दक्ष और मूल्यवान डेवलपमेंट की ओर ले जाते हैं
  • "जटिलता बहुत, बहुत बुरी है"—इस वाक्य को हमेशा याद रखना चाहिए

1 टिप्पणियां

 
GN⁺ 2025-06-18
Hacker News राय
  • मैं एक अच्छे debugger की कीमत को पत्थरों में भी नहीं आँक सकता, बल्कि मुझे लगता है कि उसकी कीमत उससे भी ज़्यादा है। चाहे छोटी startup हो या मशहूर big tech team, अक्सर टीम में debugger सिर्फ मैं ही इस्तेमाल करता था। मैंने देखा है कि बहुत से लोग अब भी print statements से debugging करते हैं। मैं अपना workflow साथियों को बताने की कोशिश करता हूँ, लेकिन कोई खास प्रतिक्रिया नहीं मिलती। मैं सहमत हूँ कि किसी system को समझने की सबसे अच्छी शुरुआत debugger से होती है। टेस्ट के दौरान किसी दिलचस्प code line पर रुककर stack देखना, दिमाग में code को ट्रेस करने से कहीं आसान है। अगर debugger इस्तेमाल करना सीख लिया जाए, तो सच में एक छोटा-सा superpower मिल जाता है। अगर संभव हो तो इसे ज़रूर आज़माएँ
    • मैं सच में proper debugger इस्तेमाल करना चाहता हूँ, लेकिन बड़े enterprise में ही काम करने वाले व्यक्ति के रूप में यह व्यवहारिक रूप से असंभव रहा है। microservice mesh architecture में local पर कुछ चलाया ही नहीं जा सकता, और test environment में भी step debugger attach न कर सकें, ऐसी setup बहुत आम है। इसलिए print debugging ही एकमात्र संभव विकल्प बनती है। यहाँ तक कि अगर log system में भी समस्या हो, या program log छापने से पहले ही crash हो जाए, तो print भी काम नहीं आता
    • इस विषय पर कई साल पहले एक अच्छी चर्चा हुई थी। Brian Kernighan और Rob Pike का एक मशहूर कथन है, और दोनों ही युवा developers नहीं हैं। "हम debugger का उपयोग stack trace या कुछ variable values देखने से आगे किसी खास मकसद के लिए नहीं करते। जटिल data structures और control flow की वजह से details में फँस जाना आसान होता है। program के बारे में दिमाग से ज़्यादा सोचना, और बीच-बीच में print output व self-checking code जोड़ना, ज़्यादा productive होता है। print डालना debugger में step-by-step जाने से कहीं तेज़ है। और print code program में रह जाता है, जबकि debugging session गायब हो जाता है।" मैं भी इस राय से सहमत हूँ। development के ज़्यादातर हिस्से में print-hypothesis-run loop कहीं तेज़ problem solving देता है। मैं code को दिमाग में "चलाता" नहीं, बल्कि flow का एक working model पहले से होता है, इसलिए जब print गलत output दिखाता है तो ज़्यादातर बार असली स्थिति का अंदाज़ा जल्दी हो जाता है। संबंधित लिंक: The unreasonable effectiveness of print debugging
    • Linux दुनिया में printf debugging हमेशा आम रहने का एक कारण यह भी था कि GUI-based debuggers पर भरोसा नहीं किया जा सकता था। Linux का GUI अक्सर अस्थिर रहता है। मेरे लिए भी debugger को ठीक से इस्तेमाल करना तब शुरू हुआ जब (1) Windows में GUI अच्छा चलता था लेकिन CLI अक्सर टूट जाता था, और (2) print debugging code गलती से version में commit होकर कई बार समस्या पैदा कर चुका था। उसके बाद मैंने CLI debugger के साथ कई प्रयोग किए, और Junit+debugger (जैसे Eclipse जैसे IDE आधारित) के साथ experimental code तुरंत लिखकर उसे test के रूप में छोड़ देने वाली प्रक्रिया मुझे Python REPL जितनी सुविधाजनक लगी। हाँ, debugger को environment के हिसाब से सेट करने के लिए शुरुआती investment चाहिए
    • अपने code में debugger इस्तेमाल करना आसान है और मुझे बहुत पसंद भी है। लेकिन जैसे ही debugger मेरे लिखे हुए code से निकलकर library या framework के अंदर गहराई तक चला जाता है, मैं भी तुरंत रास्ता भूल जाता हूँ और नापसंद करने लगता हूँ। ऐसे frameworks/libraries को बनाने में लाखों घंटे लगे होते हैं, इसलिए वे तुरंत मेरी समझ की सीमा से बाहर चले जाते हैं
  • Professor Carson, अगर आप यह पढ़ रहे हों, तो मैं दिल से आपका धन्यवाद कहना चाहता हूँ। कॉलेज के समय मुझे समझ नहीं आता था कि हम HTMX क्यों सीख रहे हैं, और आप इसके लिए इतने passionate क्यों थे, लेकिन कुछ साल बाद मुझे सही मायनों में समझ आया। HTML over the wire ही असल में सब कुछ है। Staff Ruby on Rails Engineer के रूप में काम करते हुए मैंने Hotwire में भी आपका काम कई बार देखा है, और जब कभी आपको GitHub या Hacker News पर सक्रिय देखता हूँ तो सच में हैरानी होती है। आप हमेशा programming community के लिए एक रोशनी जैसे रहे हैं। गहरा सम्मान और आभार
    • यहाँ भावुक होने वाला सिर्फ मैं नहीं हूँ, यह बहुत छू लेने वाला है
    • क्या HTMX बस एक meme नहीं था? Poe’s Law की वजह से समझ नहीं आ रहा कि यह गंभीर है या नहीं
  • इस लेख में सच में बहुत से शानदार कथन हैं, लेकिन मुझे microservices वाला हिस्सा सबसे ज़्यादा पसंद आया: "grug को समझ नहीं आता कि big brain के लिए system को ठीक से तोड़ना पहले ही कठिन है, फिर लोग उसमें network calls और क्यों जोड़ते हैं"
    • कुछ लोग system को parts में बाँटने का एक ही तरीका जानते हैं: उसे API बना देना। अगर वह API के रूप में expose न हो, तो वे उसे बस ऐसा opaque code मानते हैं जिसे न समझा जा सकता है, न reuse किया जा सकता है
    • अफ़सोस की बात है कि कई कारणों से microservices कभी-कभी व्यवहारिक भी होते हैं, इसलिए उनका उपयोग होता है
    • मैं बार-बार देखता हूँ कि एक मामूली web app में सिर्फ पाँच forms हों, फिर भी दो लोगों की छोटी dev team उसे “microservices” architecture में बेवजह जटिल बना देती है—shared database, API management, queue के जरिए batch jobs, email notifications, अपना observability platform वगैरह जोड़कर। और आखिर में साधारण forms को भी SPA बना दिया जाता है, क्योंकि कथित तौर पर वह ‘ज़्यादा आसान’ है। अब मुझे समझ आता है कि “architecture” और “patterns” अक्सर बेकार developers के लिए काम पैदा करने के औज़ार हैं। अगर ये न हों, तो वे सड़क पर “एक सैंडविच दे दो, मैं JavaScript इस्तेमाल कर लूँगा” वाला बोर्ड लेकर खड़े मिलें
    • मेरी एक conspiracy theory है कि microservices pattern को cloud vendors ने धक्का देकर यह हाल किया है। - K8S जैसे orchestrator के बिना कुछ चल ही न सके, ऐसा बना दिया जाता है, जिससे managed cloud बेचना आसान हो जाता है - ज़्यादा network traffic/CPU usage से बिलिंग बढ़ती है - बड़े पैमाने पर state share करना कठिन हो जाता है, इसलिए managed databases/event queues की ज़रूरत पड़ती है - local पर चलाना कठिन हो जाता है, जिससे dev environment भी cloud cost में बदल जाता है - cloud-specific तरीकों पर निर्भरता बढ़ती है और निकलना मुश्किल होता है। पहले cloud का विज्ञापन IT cost बचाने वाले समाधान के रूप में किया जाता था, जो बेहद हास्यास्पद है। 2000s से ही पता था कि यह एक भ्रम है, और आखिर में नतीजा सिर्फ सब कुछ महँगा होना ही है
  • "complexity बनाम Tyrannosaurus की आमने-सामने की लड़ाई में, grug complexity की जगह Tyrannosaurus चुनेगा: कम से कम Tyrannosaurus दिख तो रहा है" — यह वाक्य इतना प्रभावशाली है कि मैं इसे हफ़्ते में एक बार याद कर लेता हूँ
    • उद्धरण: "गिरते हुए भी Leyster ने फावड़ा नहीं छोड़ा था। घबराहट में वह यह बात भूल गया। इसलिए उसने बेतहाशा फावड़ा उठाकर baby tyrannosaur की टांग पर दे मारा..."। यह Tyrannosaurus के साथ चरम survival struggle का बेहद जीवंत वर्णन है। आखिर में उसकी साथी Tamara ने बहादुरी से भाले को Tyrannosaurus के चेहरे के बीचोंबीच घोंपकर संकट टाल दिया। लड़ाई, तनाव और उसके बाद की ख़ामोशी—सब बहुत प्रभावशाली है
    • grug ने शायद कभी ‘अदृश्य’ Tyrannosaurus से लड़ाई नहीं लड़ी। मैं अभी भी एक अदृश्य Tyrannosaurus से 1:1 लड़ाई में हूँ, और यह सच में बहुत कठिन है
  • इस लेख की सबसे प्रशंसनीय बात यह है कि लेखक “और जटिल चीज़” कर सकता है, लेकिन अनुभव के आधार पर उस रास्ते को नहीं चुनता। बेशक abstraction और complexity की भी अपनी जगह और समय है, लेकिन grug का दर्शन यह कहता है कि उनमें अपने आप में कोई अंतर्निहित मूल्य नहीं है। यह बात मुझे बहुत सही लगती है। AI भी अधिक संगत और data-based code पर ज़्यादा प्रभावी लगता है
    • complexity और abstraction का उपयोग तभी करना चाहिए जब उससे code पहले से ज़्यादा समझने योग्य हो जाए। यह शर्त ज़रूर याद रखनी चाहिए: “उसे समझने के लिए अलग से विशेष पाठ्यक्रम की ज़रूरत न पड़े।” (हालात के अनुसार अलग हो सकता है)
    • "हर चीज़ को जितना संभव हो उतना simple बनाना चाहिए, लेकिन उससे ज़्यादा simple नहीं"
  • यक़ीन करना कठिन है कि यह लेख 2022 का है। ऐसा लगता है मानो इसे 10 साल पहले पढ़ा था और यह पहले से ही एक ‘classic’ हो
  • software बनाने पर यह essay मेरे सबसे पसंदीदा लेखों में से एक है। इसकी शैली भी आकर्षक है (हालाँकि कुछ लोगों को इससे असहजता हो सकती है), और इसका सार हमेशा प्रासंगिक रहता है
  • "दुखद लेकिन सच: 'yes' कहना सीखो, और fail होने पर किसी दूसरे grug को दोष देना सीखो—सबसे बेहतरीन career strategy" वाला code fragment वास्तविकता जैसा लगता है। मैंने भी शुरू में सोचा था कि कंपनी में बस tech team की communication problems ही कारण हैं, लेकिन समय के साथ (grug की तरह) सीखा कि बात सच में ऐसी ही है
  • visitor pattern के बारे में अब तक जो भी व्याख्या देखी, उनमें इस लेख वाली सबसे अच्छी लगी
    • मैं typical OO codebase में काम नहीं करता, इसलिए visitor pattern क्या है यह ठीक से नहीं जानता था, लेकिन मैं "Crafting Interpreters" नाम की interpreter/VM बनाने वाली किताब की सिफारिश करना चाहूँगा। उसमें दिखाया गया है कि visitor pattern वास्तव में कैसे इस्तेमाल होता है। मैंने खुद पढ़ते हुए उसकी complexity की वजह समझने की कोशिश की, लेकिन आखिर में उसे tagged union से बदल दिया। शायद मैं OO में कमज़ोर हूँ, लेकिन grug लेख का बिंदु भी कुछ ऐसा ही है। जब जटिलता और indirection को खुद पर लादने की ज़रूरत न हो, तब ज़्यादा सीधा तरीका भी हो सकता है
    • मैं naming को लेकर संवेदनशील हूँ, और visitor pattern जैसा नाम मुझे बहुत अस्पष्ट लगता है, इसलिए उससे शिकायत है। मैंने वास्तव में कभी किसी चीज़ का नाम Visitor नहीं रखा। उदाहरण के लिए, अगर AST पर काम हो, तो Visitor की जगह AstWalker, AstItem::dispatch(AstWalker), AstWalker::process(AstItem) जैसे ठोस नाम कहीं अधिक अर्थपूर्ण लगते हैं। visitor यानी “मुलाक़ात करने वाला” इतना abstract और अर्थहीन है कि उससे मदद नहीं मिलती। संदर्भ के अनुसार नाम अलग होना चाहिए, और चाहें तो comment में बस ‘visitor pattern’ लिख देने से पहचान में कोई समस्या नहीं होती। अतीत में मुझे दो object trees को match करके data compare/import करना था, तब मैंने AbstractImporter नाम इस्तेमाल किया था। वह ज़्यादा specific था, process और role दोनों स्पष्ट थे। वह typical visitor pattern से अलग था
    • सच में खोजकर देखा तो उस पर “Bad” जैसा आकलन भी मिला। haha
  • संबंधित पोस्ट साझा कर रहा हूँ। क्या किसी के पास और राय या अतिरिक्त लेख हैं?<br/><i>The Grug Brained Developer (2022)</i> - https://news.ycombinator.com/item?id=38076886 - अक्टूबर 2023 (192 comments)<br/><i>The Grug Brained Developer</i> - https://news.ycombinator.com/item?id=31840331 - जून 2022 (374 comments)