69 पॉइंट द्वारा xguru 2024-07-15 | 6 टिप्पणियां | WhatsApp पर शेयर करें

अगर आप बार-बार अपने ही पैर पर गोली मार रहे हैं, तो बंदूक को ठीक कीजिए

  • टीम में सिस्टम को लेकर बार-बार होने वाली गलतियाँ होती हैं, लेकिन अक्सर लोग यह नहीं सोचते कि उन गलतियों को कम कैसे किया जाए
  • ऐसे मामलों में सिस्टम को बेहतर बनाकर गलतियाँ कम करना महत्वपूर्ण है
  • अनुभव:
    • iOS development में CoreData इस्तेमाल करते समय, UI update सिर्फ main thread पर ही किया जा सकता है
    • subscription callback main thread और background thread दोनों पर आते थे, इसलिए अक्सर समस्या होती थी
    • पुराने टीम सदस्य इसे जानते थे और अच्छे से संभाल लेते थे, लेकिन नए टीम सदस्यों के review में यह बात अक्सर सामने आती थी
    • कभी-कभी गलती होने पर crash report देखकर DispatchQueue.main.async जोड़ते रहे
    • इसे हल करने के लिए subscription layer को update किया गया ताकि subscriber को main thread पर call किया जाए। इसमें सिर्फ 10 मिनट लगे
    • पूरे crash class और थोड़ा-सा mental burden खत्म हो गया
  • कोई भी कुछ मिनट सोचता तो यह साफ समस्या दिखती
  • लेकिन ऐसे मुद्दों को हल करने का स्वाभाविक समय नहीं आता, इसलिए वे अजीब तरह से लंबे समय तक बने रहते हैं
    • यानी टीम में लंबे समय तक रहने पर ऐसी समस्याएँ बैकग्राउंड में गायब-सी लगने लगती हैं
  • mindset बदलने की ज़रूरत है
    • ऐसे मुद्दे होने पर कभी-कभी खुद को याद दिलाना चाहिए कि आप अपनी और टीम की ज़िंदगी आसान बना सकते हैं

quality और speed के बीच संतुलन बनाइए

  • implementation speed और correctness पर भरोसे के बीच हमेशा trade-off होता है
    • खुद से पूछना चाहिए कि मौजूदा स्थिति में bug release होना कितना स्वीकार्य है
    • अगर इसका जवाब आपके काम करने के तरीके को प्रभावित नहीं करता, तो आप शायद ज़रूरत से ज़्यादा rigid हैं
  • पहली नौकरी में data processing project करते समय data को पीछे जाकर reprocess करने का अच्छा सिस्टम मौजूद था
    • bug release होने का असर बहुत मामूली था, और ऐसे माहौल में कुछ हद तक guardrail पर भरोसा करके तेज़ी से आगे बढ़ा जा सकता है
    • 100% test coverage या बहुत व्यापक QA process सिर्फ development speed को धीमा करते हैं
  • दूसरी नौकरी में करोड़ों लोगों द्वारा इस्तेमाल किए जाने वाले product में high-value financial data और personally identifiable information को संभाला जाता था, इसलिए bug घातक साबित हो सकते थे
    • छोटे bug के लिए भी postmortem करना पड़ता था
    • features बहुत धीमी गति से release किए, लेकिन लगता है उस साल एक भी bug release नहीं किया
  • ज़्यादातर मामलों में आप दूसरी कंपनी जैसी स्थिति में नहीं होते
    • जहाँ bug घातक नहीं हैं (जैसे 99% web apps), वहाँ तेज़ी से ship करना और bug को जल्दी fix करना बेहतर है
    • शुरुआत से ही perfect feature release करने में समय लगाने की तुलना में इससे ज़्यादा प्रगति हो सकती है

आरी तेज़ करने में लगाया गया समय लगभग हमेशा फायदेमंद होता है

  • tools को अच्छी तरह इस्तेमाल करना महत्वपूर्ण है
  • code तेज़ी से लिखना, मुख्य shortcuts जानना, और operating system व shell में सहज होना ज़रूरी है
    • rename, type definition पर जाना, reference खोजना जैसी चीज़ें बहुत करनी होंगी
    • editor के मुख्य shortcuts सब पता होने चाहिए, और typing में confidence व speed होनी चाहिए
    • browser developer tools का असरदार इस्तेमाल करना भी महत्वपूर्ण है
  • tools का सही चुनाव और उनका दक्ष उपयोग बहुत बड़ा फ़ायदा है
  • नए engineer में दिखने वाले सबसे बड़े green flag में से एक है tools के चुनाव और कुशल उपयोग में रुचि

अगर आप कठिनाई को आसान शब्दों में समझा नहीं सकते, तो शायद वह accidental complexity है, और इसे हल करना मूल्यवान है

  • मेरे पसंदीदा managers में से एक की आदत थी कि जब भी मैं कहता कि implementation मुश्किल है, तो वह लगातार सवाल करते थे
    • अक्सर उनका जवाब कुछ ऐसा होता था, "क्या यह बस X को Y करते समय भेजने भर की बात नहीं है?" या "क्या यह कुछ महीनों पहले किए गए Z जैसा नहीं है?"
    • यह बहुत high-level counterpoint होता था, न कि उन actual function और class level details जैसा जिन्हें मैं समझाने की कोशिश कर रहा था
  • आम धारणा यह है कि manager की ऐसी simplification बस परेशान करने वाली होती है
  • लेकिन हैरानी की बात यह रही कि बहुत बार manager के बार-बार पूछने पर मुझे एहसास हुआ कि जिस complexity को मैं समझा रहा था उसका बड़ा हिस्सा accidental complexity था
  • और सच में, उसे पहले हल करके समस्या को उतना मामूली बनाया जा सकता था जितना manager कह रहा था
  • इस तरह का approach आगे होने वाले बदलावों को भी आसान बनाता है

bugs को एक परत और गहराई में जाकर हल करने की कोशिश कीजिए

  • bug को सिर्फ ऊपर-ऊपर से patch करने के बजाय, उसकी जड़ में जाकर कारण ढूँढना और उसे हल करना महत्वपूर्ण है
  • मान लीजिए dashboard में एक React component है जो current logged-in user state से लिया गया User object इस्तेमाल करता है
    • Sentry में bug report आता है कि rendering के दौरान user null था
      • आप जल्दी से if (!user) return null जोड़ सकते हैं
    • या थोड़ा और जाँच करने पर पता चलता है कि logout function दो अलग state update कर रहा है
      • पहला user को null सेट करता है, और दूसरा homepage पर redirect करता है
    • अगर इन दोनों का क्रम बदल दिया जाए, तो अब किसी भी component में यह bug दोबारा नहीं आएगा
    • क्योंकि dashboard के भीतर user object कभी null नहीं होना चाहिए
  • अगर आप पहले प्रकार के bug fix करते रहेंगे, तो सिस्टम गड़बड़ हो जाएगा,
    दूसरे प्रकार के bug fix करते रहेंगे, तो आपके पास साफ-सुथरा सिस्टम और invariants की गहरी समझ होगी

bug की जाँच के लिए history में गहराई से जाने की अहमियत को कम मत आँकिए

  • मैं println और debugger जैसे सामान्य tools से अजीब समस्याओं को debug करने में काफी अच्छा था
  • इसलिए bug की history समझने के लिए git को ज़्यादा नहीं देखता था, लेकिन कुछ bugs में यह बहुत महत्वपूर्ण होता है
  • हाल ही में server में memory लगातार leak होती दिख रही थी, और OOM की वजह से वह बंद होकर फिर restart हो रहा था
    • हर संभावित कारण को खारिज किया जा चुका था, और local में issue reproduce नहीं हो रहा था
    • ऐसा लग रहा था जैसे आँख बंद करके dart फेंक रहे हों
    • commit history देखने पर पता चला कि यह Play Store billing support जोड़ने के बाद शुरू हुआ
    • यह सिर्फ कुछ HTTP requests का मामला लग रहा था, इसलिए शायद मैं लाख साल में भी वहाँ नहीं देखता
    • निकला यह कि पहला access token expire होने के बाद access token लाने वाला infinite loop शुरू हो गया था
    • हर request शायद memory में सिर्फ 1kB जोड़ रही थी, लेकिन अगर कई threads 10ms पर retry करें तो यह जल्दी बढ़ जाता है
    • आम तौर पर इससे stack overflow होता, लेकिन Rust में async recursion इस्तेमाल हो रही थी, इसलिए stack overflow नहीं हुआ
    • यह बात कभी दिमाग में नहीं आती, लेकिन जब साफ तौर पर problem पैदा करने वाले code को देखा, तो अचानक theory समझ में आ गई
  • इस approach को कब अपनाना है, इसका कोई तय नियम नहीं है
    • यह intuition पर आधारित है; bug report देखकर आने वाला एक अलग तरह का "हूँ?" इस तरह की जाँच शुरू करा देता है
    • समय के साथ इस intuition को विकसित किया जा सकता है, लेकिन कभी-कभी बस इतना जानना भी काफ़ी है कि यह बहुत मूल्यवान हो सकता है
  • जहाँ उपयुक्त हो, git bisect आज़माइए
    • जब आपके पास एक ऐसा commit हो जिसे आप गलत जानते हों, और एक ऐसा commit हो जिसे आप सही जानते हों

खराब code feedback देता है, लेकिन perfect code नहीं देता। गलती इस तरफ कीजिए कि थोड़ा खराब code लिख लिया जाए

  • बहुत खराब code लिखना सचमुच आसान है
  • लेकिन ऐसा code लिखना भी बहुत आसान है जो हर best practice का पूरी तरह पालन करता हो
    • unit, integration, fuzz, mutation testing सब करना होगा, और उससे पहले ही startup के पैसे खत्म हो जाएँगे
  • programming का बड़ा हिस्सा सही संतुलन खोजने में है
  • अगर आप तेज़ी से code लिखने की दिशा में गलती करते हैं...
    • कभी-कभी खराब technical debt की वजह से मुश्किल में पड़ेंगे
    • आप सीखेंगे कि "data processing के लिए शानदार tests जोड़ने चाहिए"
      • क्योंकि बाद में उसे ठीक करना अक्सर संभव नहीं होता
    • आप यह भी सीखेंगे कि "table design पर सच में अच्छे से सोचना चाहिए"
      • क्योंकि बिना downtime के बदलाव करना बहुत कठिन हो सकता है
  • अगर आप perfect code लिखने की दिशा में गलती करते हैं...
    • आपको कोई feedback नहीं मिलेगा
    • हर चीज़ में सार्वभौमिक रूप से ज़्यादा समय लगेगा
    • आपको पता नहीं चलेगा कि कहाँ समय सही लग रहा है और कहाँ व्यर्थ जा रहा है
    • feedback mechanism सीखने के लिए ज़रूरी है, लेकिन आपको वह मिल ही नहीं रहा
  • "खराब" code से क्या मतलब है, इसे स्पष्ट करें
    • इसका मतलब यह नहीं कि "मुझे hashmap बनाने का syntax याद नहीं था इसलिए inner loop दो बार इस्तेमाल कर लिया"
    • इसका मतलब कुछ ऐसा है:
      • किसी state को represent करना असंभव बनाने के लिए data collection दोबारा लिखने के बजाय, कुछ मुख्य checkpoints पर invariants के assertions जोड़ दिए
      • server model ठीक वही है जो लिखने वाला DTO होगा, इसलिए सारा boilerplate लिखने के बजाय फिलहाल उसे serialize कर दिया। ज़रूरत पड़ने पर बाद में DTO बनाया जा सकता है
      • ये components बहुत मामूली हैं और इनमें bug होने पर बड़ा नुकसान नहीं होगा, इसलिए tests लिखना छोड़ दिया

debugging को आसान बनाइए

  • सालों में मैंने software को debug करना आसान बनाने के कई छोटे tricks सीखे हैं
    • अगर आप debugging को आसान बनाने में मेहनत नहीं करेंगे, तो software के और जटिल होने के साथ हर issue को debug करने में बहुत समय खर्च होगा
    • आप बदलाव करने से डरने लगेंगे, क्योंकि कुछ नए bugs समझने में ही शायद एक हफ़्ता लग जाए
  • debugging time में setup, reproduction, और cleanup पर कितना समय जा रहा है, इस पर ध्यान दीजिए
    • अगर यह 50% से ज़्यादा है, तो भले इस बार थोड़ा ज़्यादा समय लगे, इसे आसान बनाने का तरीका ढूँढना चाहिए
    • बाकी सब समान हो, तो bug fix समय के साथ आसान होते जाने चाहिए

टीम में काम करते समय हमेशा सवाल पूछिए

  • एक spectrum है: "सब कुछ खुद समझने की कोशिश करना" से लेकर "छोटे-छोटे सवालों से सहकर्मियों को परेशान करना" तक
    • मेरा मानना है कि career की शुरुआत में ज़्यादातर लोग पहले वाले छोर की तरफ बहुत ज़्यादा झुके होते हैं
  • आपके आसपास हमेशा कोई न कोई ऐसा होता है जो codebase में आपसे ज़्यादा समय से है, या तकनीक X को आपसे बेहतर जानता है, या product को बेहतर समझता है, या बस अधिक अनुभवी engineer है
  • किसी नई जगह काम शुरू करने के पहले 6 महीनों में अक्सर आप किसी चीज़ को समझने में एक घंटे से ज़्यादा बर्बाद कर सकते हैं, जबकि जवाब कुछ मिनटों में मिल सकता है
  • सवाल पूछिए। सवाल पूछना किसी को तभी परेशान करता है जब साफ़ दिखता हो कि आप कुछ ही मिनटों में जवाब खुद ढूँढ सकते थे

deployment cycle बहुत महत्वपूर्ण है। तेज़ और बार-बार deploy करने के तरीके पर गंभीरता से सोचिए

  • startup का runway सीमित होता है, और projects की deadlines होती हैं
  • नौकरी छोड़कर स्वतंत्र काम करने निकलें, तो आपकी बचत सिर्फ कुछ महीनों तक चलेगी
  • आदर्श रूप से project की गति समय के साथ compound होकर बढ़नी चाहिए, ताकि आप कल्पना से भी तेज़ features deploy कर सकें
  • तेज़ deploy करने के लिए बहुत-सी चीज़ें चाहिए
    • ऐसा system जो bug-prone न हो
    • teams के बीच तेज़ turnaround time
    • नए feature के उस 10% हिस्से को काट देने की इच्छा, जो engineering time का 50% खा जाएगा, और उसे पहचानने की समझ
    • नए screen/feature/endpoint के लिए composable, consistent, reusable patterns
    • तेज़ और आसान deployment
    • ऐसे process जो speed कम न करें (flaky tests, slow CI, परेशान करने वाले linter, धीमा PR review, और धर्म की तरह माने जाने वाला JIRA आदि)
    • और ऐसी ही लाखों दूसरी चीज़ें
  • धीमी deployment पर भी उतनी ही गंभीर postmortem होनी चाहिए जितनी production बंद कर देने पर होती है
    • हमारी industry भले ऐसे न चलती हो, लेकिन इसका मतलब यह नहीं कि आप व्यक्तिगत रूप से fast deployment को अपना north star नहीं बना सकते

6 टिप्पणियां

 
carnoxen 2024-07-19

"पैर पर गोली मारना" = अपने ही जाल में फँसना
क्या इसका यही मतलब है?

 
yunghn 2024-07-25

अगर किसी गलत कोड (खराब बंदूक) की वजह से समस्या हो रही है (अपने ही पैर में गोली मारना), तो बात यह है कि बंदूक को ठीक करो।

 
gargoyle92 2024-07-16

ऐसा लगा जैसे मेरे दिमाग के अंदर की बातों को ज्यों का त्यों बाहर निकाल दिया हो, ज़बरदस्त झटका लगा, haha..

 
cbbatte 2024-07-16

बहुत अच्छा पढ़ा!!

 
hannah0su 2024-07-15

अच्छी तरह पढ़ा।

 
arfwene 2024-07-15

मैं डेवलपर नहीं हूँ, लेकिन इसमें कई बातें ऐसी हैं जिनसे जुड़ाव महसूस होता है।