2 पॉइंट द्वारा GN⁺ 2024-08-06 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • 2 साल तक खुद इस्तेमाल करते हुए सुधारते आए प्रोग्राम के core को एक महीने में फिर से लिखने के अनुभव ने tests और version control को लेकर मेरी पुरानी मान्यताओं को हिला दिया
  • 2015 में मुझे लगता था कि खराब abstraction से अधिक, लंबे समय तक टिकने वाले software की कुंजी tests और versions हैं, लेकिन Mu और Freewheeling Apps पर काम करते हुए मेरा वास्तविक काम करने का तरीका धीरे-धीरे बदलता गया
  • मेरा मानना है कि लंबे समय तक टिकने वाले प्रोग्राम बहुत सारे लोगों के लिए बनाने के बजाय, जाने-पहचाने लोगों, context और functionality के भीतर बनाए जाने चाहिए, और Dunbar's number जैसी वास्तविक सीमाओं को स्वीकार करना चाहिए
  • types, abstraction, tests, versions, state machines, immutability और formal analysis अनजान क्षेत्रों में उपयोगी हैं, लेकिन ज़्यादा हो जाएँ तो वे अनावश्यक complexity को छिपाने वाला technical debt बन जाते हैं
  • जब context की समझ स्थिर हो जाए, तो बड़े हिस्सों को फेंककर फिर से बनाना सार्थक होता है, और ज़रूरी scenarios को एक साथ दिमाग में रखकर पूरे सिस्टम को एक बार में गढ़ना चाहिए

tests और version control पर सोच में बदलाव

  • मैं लंबे समय तक भरोसेमंद रहने वाले प्रोग्राम चुनने और खुद बनाने की समस्या से लगातार जूझता रहा हूँ, लेकिन मुझे खुद भी नहीं लगता कि मैं यह काम बहुत अच्छे से करता हूँ
  • पिछले एक महीने में मैंने 2 साल तक इस्तेमाल और क्रमिक रूप से संशोधित किए गए एक प्रोग्राम के core को फिर से लिखा
    • उसके बाद कई दिनों तक मैंने यह समेटने में समय बिताया कि मैंने क्या सीखा और आगे कहाँ जाना है
    • इस काम के बहाने मुझे जीवन के व्यापक बदलाव भी दिखने लगे
  • 2015 में मैं abstraction पर संदेह करता था और tests व version control को महत्व देता था
    • मुझे लगता था कि code में खराब abstraction बहुत हैं, और tests व versions 2000s की सबसे अहम प्रगति हैं
    • मैं समस्याओं के कारण खराब incentives, अत्यधिक abstraction, और tests व versions की कमी में देखता था
    • Mu1 tests और layers को आधारभूत constraints मानकर platform design करने की कोशिश थी
  • 2017 में मैंने Mu1 को फिर से आज के Mu के रूप में बनाना शुरू किया
    • शुरुआत में मैंने tests और layers के बारे में अपने सारे नए ideas इस्तेमाल किए
    • समय के साथ मैंने उन ideas का उपयोग कम कर दिया
    • आज के Mu में tests बहुत हैं, लेकिन ज़्यादातर साधारण tests हैं, और मैं layers infrastructure को साथ नहीं ला सका
  • 2022 में मैंने Freewheeling Apps बनाना शुरू किया
    • शुरुआत में इसमें tests नहीं थे, बाद में इसके मुख्य हिस्से text editor के लिए मैंने बहुत thorough tests लिखे
    • बाकी हिस्सों को test करने का तरीका ढूँढना मुश्किल था, लेकिन बिना tests के भी काम पर्याप्त रूप से आगे बढ़ता रहा
  • 2024 में मैंने सारे tests हटा दिए
    • मैंने text editor को बड़े पैमाने पर फिर से बनाना शुरू किया, और इस तरीके से Freewheeling Apps के दूसरे हिस्सों के साथ merge conflicts की चिंता हो सकती थी
    • नतीजतन मैंने version control के बारे में सोचना भी रोक दिया
    • tests और versions छोड़ने के बाद जब मुझे बेहतर प्रोग्राम मिला, तो अपनी पुरानी मान्यताओं के साथ होने वाले cognitive dissonance को अनदेखा करना मुश्किल हो गया

लंबे समय तक टिकने वाले प्रोग्रामों के लिए मेरी मौजूदा समझ

  • मेरा मानना है कि बहुत सारे लोगों के लिए लंबे समय तक टिकने वाली चीज़ बनाना बहुत कठिन है, इसलिए शुरुआत से ही ऐसा करने की कोशिश न करना बेहतर है
    • हमें उन्हीं चीज़ों, उन्हीं लोगों और उन्हीं सीमाओं के भीतर रहना चाहिए जिन्हें हम अच्छी तरह जानते हैं, और Dunbar's number से शासित होना चाहिए
  • मुझे लगता है कि दुनिया का अधिकांश software अल्पकाल में बहुत सारे लोगों की सेवा करने वाले incentives से संक्रमित है
    • मैं जहाँ तक हो सके, उन software पर ध्यान देता हूँ जिनकी websites पर बहुत सारे logos न हों
    • मैं ऐसे software को पसंद करता हूँ जो बनाना आसान हो, जिनकी dependencies कम हों, और जो automatic updates न करते हों
    • इन सीमाओं से छाँटने पर मानवता द्वारा अब तक बनाए गए long-lasting software की मात्रा बहुत कम रह जाती है
  • context में छोटे बदलाव भी — जैसे लोग, स्थान, या जिन features को support करना है — इस बात को बहुत बदल सकते हैं कि कोई प्रोग्राम उस context में कितना फिट बैठता है
    • अल्पकालवाद से dominated माहौल में इस सच्चाई के लिए तैयारी करना मुश्किल है
  • क्योंकि पिछले काम की मात्रा कम है और हर प्रोग्राम का लागू क्षेत्र भी सीमित है, इसलिए जो प्रोग्राम हम नया बनाना चुनते हैं वह किसी न किसी रूप में अनजाने क्षेत्र में प्रवेश करने की संभावना रखता है
    • जब मैं text editor में खास तरह की “drawing lines” डालना चाहता था, तब भी कई सवाल उठे
      • क्या cursor चित्र के ऊपर हो सकता है
      • जब cursor किसी दूसरी line पर हो, तब क्या एक line पर drawing की जा सकती है
      • चित्र text line से ऊँचा है, तो क्या वह screen के ऊपर केवल आंशिक रूप से दिखाई दे सकता है
      • जो चित्र आंशिक रूप से दिख रहा हो, क्या उसके ऊपर drawing की जा सकती है
    • इन सवालों के जवाब लंबे समय तक optimal नहीं थे, इसलिए अस्थायी उपायों के ऊपर और अस्थायी उपाय चढ़ते गए

tools ज़रूरी हैं, लेकिन ज़्यादा हो जाएँ तो technical debt बन जाते हैं

  • types, abstraction, tests, versions, state machines, immutability और formal analysis ऐसे tools हैं जिन्हें अनजाने भूभाग में इस्तेमाल किया जा सकता है
    • जितनी ज़रूरत हो, अपनी पसंद के हिसाब से उनका उपयोग करें
  • इंसान अक्सर जिन tools की ओर खिंचता है, उनका ज़रूरत से ज़्यादा इस्तेमाल कर बैठता है
    • मुझे लगता है कि इन tools की आदर्श मात्रा बहुत कम होती है
    • और यह मात्रा अल्पकालवादी माहौल में सीखी गई सहज धारणाओं से कहीं कम होनी चाहिए
  • tools का अति-उपयोग technical debt बन जाता है
    • यह समझना कठिन हो जाता है कि प्रोग्राम अनावश्यक रूप से जटिल है
    • प्रोग्राम जितना लंबे समय तक टिक सकता था, उससे कम टिकाऊ बन जाता है
    • context बदलने पर प्रोग्राम को बदलना और कठिन हो जाता है

फिर से लिखना और “पूरे को एक बार में बनाना”

  • जब context की समझ स्थिर हो जाए, तब प्रोग्राम के बड़े हिस्सों को फेंककर शुरू से फिर बनाना मूल्यवान होता है
  • फिर से लिखने से पहले प्रोग्राम से चाहिए हर चीज़ और जिन सभी scenarios को संभालना है, उन्हें एक साथ दिमाग में लाना होता है
    • यह प्रक्रिया कठिन है, लेकिन लक्ष्य उस स्थिति तक पहुँचना है जहाँ सब कुछ एक बार में बनाया जा सके
  • अंतिम तरीका है सब कुछ एक बार में बनाना
  • इस बार के अनुभव में tests और versions ने इस evolution के अंत तक पहुँचने में उल्टा बाधा डाली
    • tests आपको उन समस्याओं को भूलने देते हैं जिनकी चिंता करनी चाहिए
    • version control आपको अतीत से चिपकाए रखता है
    • दोनों का असर उल्टा पड़ा, और इन्हें छोड़ने के लिए बड़े स्तर का दिशा-परिवर्तन चाहिए था
  • मेरा मानना है कि अब तक बनाया गया मेरा सारा software और Freewheeling Apps इस trajectory के stage 6 पर हैं

complexity की सीमाएँ और data-oriented design

  • अगर प्रोग्राम बहुत जटिल हो जाए, तो stage 8 में उसे पूरे का पूरा दिमाग में रखना असंभव हो सकता है
    • मुझे लगता है कि अब तक का अधिकांश software, खासकर वह software जिसे दो-तीन से अधिक लोगों ने लिखा हो, इसी श्रेणी में आता है
    • एक छोटा text editor भी इतना भारी लग सकता है कि मैंने महीने का बड़ा हिस्सा उस डर का सामना करने की तैयारी में बिताया
  • हर software का stage 9 तक पहुँचना ज़रूरी नहीं है
    • कई Freewheeling Apps पर्याप्त रूप से simple हैं और धीरे-धीरे evolve होते हैं
    • मेरा मानना है कि कुछ ही लोगों द्वारा उपयोग किया जाना भी उन्हें शुरुआती design choices से स्वतंत्र होकर bug-free स्थिति में स्थिर कर सकता है
    • खासकर अब जब मुझे core के एक जटिल हिस्से को सरल बनाने का तरीका समझ में आ गया है
  • फिर भी, जब मूल्य पैदा हो, तब यह जानना अच्छा है कि उसे बेहतर कैसे किया जा सकता है
  • stage 9 तक पहुँचने में जो तरीका निश्चित रूप से उपयोगी लगता है, वह है data-oriented design
    • यह ऐसा tool नहीं है जिसे आँख मूँदकर लागू किया जा सके, बल्कि यह उस बड़े चित्र को देखने का तरीका है कि प्रोग्राम data तक कैसे पहुँचता है
    • ध्यान रखना चाहिए कि ECS जैसे tools इस मूल बौद्धिक काम को ढक न दें
  • हो सकता है यह stage-विभाजन पूरी तरह सही न हो
    • जिन tools का मेरा अनुभव कम है, मैं उनकी उपयोगिता को कम आँक रहा हो सकता हूँ
    • और इन stages के आगे क्या है, यह भी अभी एक खुला सवाल है
  • 2019 में लिखे गए प्रोग्रामिंग के तरीके पर लेख के बाद से मेरी सोच कैसे बदली है, इसके संकेत यहाँ देखे जा सकते हैं

1 टिप्पणियां

 
GN⁺ 2024-08-06
Hacker News की राय
  • अगर टेस्ट ही नहीं हैं तो test failures दिखेंगे ही नहीं, इसलिए बस ऐसा लगेगा कि समस्या गायब हो गई है
    मैंने कभी ऐसा कुछ टेस्ट नहीं किया जिसमें कोई bug न मिला हो, और जिन चीज़ों को मैंने टेस्ट किया उनमें से ज़्यादातर मुझे पहले से ही release के लिए तैयार लग रही थीं
    अगर आप टेस्ट हटा देते हैं, तो आखिर में सबसे ज़्यादा खुद को ही धोखा दे रहे होते हैं। यह पढ़कर लगता है कि लेखक टेस्ट से ज़्यादा mutation/configuration management से थक गया है, और उससे सहमत हुआ जा सकता है। लेकिन users होने चाहिए तभी पैसा बनता है, और अगर समस्या आसान होती तो बाज़ार पहले ही किसी सर्व-उपयोगी solution से भर चुका होता

    • मुझे लगता है यह domain-dependent है। जिस codebase पर मैं अभी काम कर रहा हूँ, उसके कुछ हिस्सों में टेस्ट refactoring के लिए बहुत मददगार हैं, लेकिन दूसरे हिस्सों में UI behavior इतना ज़्यादा है कि manual testing कहीं तेज़ पड़ती है
      अगर UI या workflow बहुत तेज़ी से बदल रहा हो, तो पता होता है कि अगले iteration में टेस्ट बेकार हो जाएँगे, इसलिए टेस्ट लिखने का मन नहीं करता। और अगर बहुत धीरे बदल रहा हो, तो उस हिस्से को फिर छूने की ज़रूरत ही कम पड़ती है, इसलिए refactoring से नए bug आने की संभावना भी कम होती है। टेस्ट या types कोई जादुई उपाय नहीं हैं, वे बस काम के हिसाब से चुने जाने वाले tools हैं। मैंने कभी ऐसा codebase नहीं देखा जिसमें test coverage अच्छा हो और फिर भी manual testing या वास्तविक उपयोग से bugs न निकलें। थोड़ा बढ़ा-चढ़ाकर कहूँ तो, अगर आप इतने अच्छे हैं कि perfect tests लिख सकते हैं, तो बस perfect code ही लिख दीजिए। और अगर perfect tests नहीं लिख सकते, तो फिर कैसे पता कि वे tests वास्तव में complete, bug-free और उपयोगी हैं
    • “Tests can show the presence of bugs, but not their absence” वाली बात मेरे अनुभव से ज़्यादा मेल खाती है
      हर कुछ महीनों में नया bug मिलता था और मैं ईमानदारी से टेस्ट जोड़ता था, लेकिन कुछ महीनों बाद कोई व्यक्ति पहली बार 10 मिनट इस्तेमाल करके फिर एक नया bug ढूँढ लेता था। नए version में भी bugs मिलेंगे, लेकिन चुने गए data structures की वजह से मुझे लगता है कि पुराने कई tests अब संरचनात्मक रूप से ज़रूरी नहीं रहे। कम से कम हल्के उपयोग के लिए, अगर कुछ और bugs पकड़ लिए जाएँ तो यह काफ़ी stable हो जाएगा, ऐसी उम्मीद है। बड़े teams जब लगातार codebase बदलते रहते हैं तब tests बहुत कीमती होते हैं, लेकिन यहाँ मैं fixed feature set वाली कोई चीज़ बनाने की कोशिश कर रहा हूँ
    • हाल की एक thread में सुझाया गया Russ Cox का Go Testing By Example वीडियो मैंने देखा: https://www.youtube.com/watch?v=X4rxi9jStLo
      उसमें बहुत उपयोगी सलाह है, लेकिन खास तौर पर यह बात उल्लेखनीय लगी कि आप किसी और सरल implementation, जैसे brute-force implementation, को baseline बनाकर टेस्ट कर सकते हैं। इसमें गहरी समझ छिपी है। टेस्ट की उपयोगिता इस पर निर्भर करती है कि test implementation, जिस implementation को टेस्ट किया जा रहा है, उससे कितना सरल है। और ज़्यादा कड़े शब्दों में कहें तो, टेस्ट तभी उपयोगी हैं जब वे target से सरल हों। चाहे आप कितने भी tests लिख लें, आखिर में code पर तर्क करना ही पड़ता है, और सिर्फ़ किसी चीज़ का “test” होना उसे अपने-आप उपयोगी नहीं बना देता। इसी वजह से बहुत से programmers इस बात से सावधान रहते हैं कि tests को आसान बनाने के लिए functions को उपयोगी interface के बजाय टुकड़ों में बाँट दिया जाए, या सिर्फ़ coverage के लिए साधारण helpers या छोटे queries को टेस्ट किया जाए, या केवल testing के लिए dependency inversion and mocking जैसी abstraction लाई जाए। बेशक इन सबके अपने कारण हो सकते हैं, लेकिन ज़रूरी है कि मूल बात न खो जाए
    • मेरे मामले में, जब भी मैंने unit tests लिखे, bugs सामने आए
      आम तौर पर मैं पहले failing test लिखने वाली test-driven development शैली नहीं अपनाता, लेकिन कभी-कभी करता हूँ। इसलिए ऐसे tests आम तौर पर उस code के लिए होते हैं जिसे मैं पहले से working मान चुका होता हूँ। फिर भी, आमतौर पर मैं unit tests से ज़्यादा test harness को पसंद करता हूँ[0]। यह अब भी bugs ढूँढता है, लेकिन उसका flow कम सीधा होता है। इसकी वजह से development के दौरान ज़्यादा testing होती है और bug उसी समय ठीक हो जाता है
      [0] https://littlegreenviper.com/testing-harness-vs-unit/
    • automated unit/integration tests पर ज़ोर देना अपेक्षाकृत आधुनिक रुझान है, शायद 1990s के आखिर से। उससे पहले भी काफ़ी बड़े और बहुत stable software release हुए थे
      उदाहरण के लिए, Linux kernel में पहले ज़्यादा tests नहीं थे, हालाँकि अब शायद बढ़ गए हैं। Unix में भी शायद बहुत “tests” नहीं रहे होंगे। compilers में tests होते थे, लेकिन operating systems में कम, और Doom जैसे games में भी शायद tests कम रहे हों। आखिरकार balance point ढूँढना पड़ता है। हमें पता है कि automated tests, यानी unit, integration और end-to-end tests, अच्छी quality वाला software बनाने में मदद करते हैं। साथ ही, अच्छे tests हमेशा लिखना आसान नहीं होता, बुरे tests refactoring को कठिन बना देते हैं, और flaky tests बड़े projects में बहुत समय खा जाते हैं। फिर भी, खासकर अगर आप अकेले development कर रहे हैं, तो अलग-अलग तरीकों को आज़माकर अपने लिए सही तरीका ढूँढना अपने-आप में दिलचस्प है
  • “टेस्ट और version को छोड़ देने पर प्रोग्राम कहीं बेहतर हो गया” वाला हिस्सा समझना मुश्किल है। 2024 में कौन स्वेच्छा से source code management के बिना programming करना चाहेगा, समझ नहीं आता।
    एक अकेले व्यक्ति के project में भी कई devices पर काम करना, history देखना, rollback करना, और branch इस्तेमाल करना लगभग बिना लागत के बहुत बड़ा मूल्य देता है। हो सकता है कि लेखक का “version” से मतलब मैं गलत समझ रहा हूँ

    • मैं कुछ छोटा और तेज़ी से स्थिर feature set वाला बना रहा हूँ। मैंने उसे ऐसी नींव पर बनाने का फैसला किया है जो बार-बार नहीं बदलती, और पृष्ठभूमि https://akkartik.name/freewheeling में और है।
      यह कहना सही है कि यह approach आजकल लोगों द्वारा बनाए जाने वाले ज़्यादातर programs—यानी बड़ी teams और लगातार बदलती requirements—के लिए उपयुक्त नहीं है। फिर भी मैं source control अब भी इस्तेमाल करता हूँ। मूल लेख में जैसा कहा था, मैंने बस दूसरे forks के साथ merge conflicts की चिंता छोड़ दी है। अभी 24 से ज़्यादा forks हैं, और विवरण ऊपर के link में है। backup, “मैंने अभी क्या बदला?”, और नए device पर software डालने जैसे बुनियादी कामों के लिए मैं version control का उपयोग करता हूँ। बस इस program के मामले में मैंने version control को यह समझने और track करने का साधन मानना छोड़ दिया है कि क्या बदला। अधिक विवरण https://akkartik.name/post/wart-layers में है। उदाहरण के लिए, अब मैं commit message hygiene पर कम ध्यान देता हूँ। version control मौजूद है, लेकिन feature set स्थिर होने और दशकों तक टिकने वाले durable output बनाने की इस संकीर्ण context में इसकी priority “अच्छी programming practice” के रूप में कम हो गई है
    • लगता है लेखक ऐसी स्थिति में नहीं है जहाँ उसे professional users या paid users को support करना हो, और वह ज्ञात stable version की गारंटी से अधिक experiment करने की आज़ादी चाहता है।
      यह भी नहीं लगता कि वह बड़े systems या महत्वपूर्ण team work से निपट रहा है। ऐसी conditions में tools का मूल्य बहुत अधिक न भी हो सकता है। जटिल symphony बजाने वाले बड़े orchestra के flute वादक को sheet music और conductor चाहिए, लेकिन अगर कोई drum machine के साथ अकेले बजा रहा हो या free jazz कर रहा हो, तो sheet music की ज़रूरत कम हो सकती है, बल्कि वह बाधा भी बन सकती है
    • लगता है लेखक programming को लेकर मानसिक थकान या burnout झेल रहा है। अगर version control इतनी हद तक खटकने लगे, तो मेरे हिसाब से यह आराम करने का काफ़ी अच्छा संकेत है
    • programmer लगातार choices और options से दबा रहता है। tools और zeitgeist जिस “best tool” की बात करते हैं, वे आम तौर पर किसी काम को और आसान बनाने की दिशा में बढ़ते हैं।
      लेकिन अगर हमेशा 1000 आसान विकल्प मौजूद हों, तो सही विकल्प चुनने में बहुत बड़ा cognitive load पैदा होता है। industry हर तरह की best practices को पवित्र मानती है और उनका पालन न करने वालों पर सामाजिक दबाव डालती है, इसका एक कारण यही भी है। खराब architecture और भयानक spaghetti code के साथ काम करना बहुत कठिन होता है, लेकिन जो चीज़ें स्वतः सही लगती हैं उन पर संदेह करना और विकल्पों व tools को घटाने वाला कठोर development environment खोजना आपको अंतिम समस्या पर अधिक केंद्रित कर सकता है। version control भी branches के ज़रिए program को “independent features” में बाँटने की ओर धकेलता है, history पुरानी पड़ चुकी feature units का अंधाधुंध उपयोग करवाती है, और collaboration अक्सर असंबंधित organizational boundaries को code architecture में स्थायी बना देती है। यह Mel Conway की बात से भी जुड़ता है। version control के फ़ायदे सामान्य समझ की बात हैं, लेकिन “business problem X को solve करना” जैसी स्तर की बात करें तो वास्तविक trade-offs मौजूद हैं। industry स्तर पर ऐसे trade-offs लगभग दिखाई ही नहीं देते, यह बात काफ़ी संकेतपूर्ण है
    • इस मामले में लगता है लेखक का मतलब app के भीतर version logic को code करना है। उदाहरण के लिए backward compatibility के लिए version-specific API endpoints जैसी चीज़ें
  • शुरुआत में मुझे लगा लेखक पूरी तरह गलत है, लेकिन फिर भी इसमें कुछ अच्छी अंतर्दृष्टि है।
    यह workflow लेखक के लिए बहुत अच्छा काम करता है। हममें से ज़्यादातर लोग वह समय याद कर सकते हैं जब Git या automated tests की वजह से हम निराश हुए हों या productivity घटी हो। Dropbox, FTP आदि से code backup करने जैसे अधिक सरल और कम बाधक समाधान भी हैं। ऊपर का तरीका इसलिए काम करता है क्योंकि लेखक कुछ लोगों के साथ सहयोग वाले personal passion project में अपनी productivity optimize कर रहा है। automated tests उपयोगी हैं, लेकिन लगता है लेखक इतने छोटे programs बनाना पसंद करता है कि उनका मूल्य स्पष्ट होकर सामने आना मुश्किल होता है। इस context में भी मुझे automated tests का मूल्य दिखता है, लेकिन इस बात पर सब सहमत हो सकते हैं कि automated tests गति को धीमा करते हैं। बेशक, बहुत से लोग कहेंगे कि बाद में उसका लाभ वापस मिलता है। version control और automated tests वास्तविक समस्याएँ हल करते हैं। आज के समय में version control के बिना project शुरू करना बेतुका है, और automated tests best practice क्यों माने जाते हैं, इसके कारण हैं। फिर भी लेखक के खास use case में यह बात तर्कसंगत लगती है। विवादास्पद version control/test वाले हिस्से को छोड़ दें, तो item 7/8/9 बड़े programs लिखते और refactor करते समय मेरी सोच को पूरी तरह पकड़ते हैं। लिखो, फेंको, फिर से लिखो

    • मैं version control से सहमत नहीं हूँ। project अकेले का हो और कई version branches न भी हों, तब भी।
      इंसान गलती करता है, और 100,000 lines से बड़े project में पिछले 3 हफ्तों में क्या बदला यह जानना बहुत मददगार होता है। समस्या ढूँढने और ठीक करने में काम आता है। और बेहतर बात यह है कि branch के ज़रिए आप मनचाही चीज़ आज़मा सकते हैं, जबकि पहले की stable state में लौटने का रास्ता भी बना रहता है। automated tests न भी हों तो मुझे ठीक लगता है
    • अकेले के project में भी .gitignore सेट करना और git init, git add -A, git commit -a -m "before I changed the foo function to use bar" जैसे commands चलाना सीखने में लगाया गया समय इतना मूल्यवान है कि आप कम से कम पिछली revision पर लौट सकें, इसलिए Git सीखना पूरी तरह सार्थक है।
      Git में mastery ज़रूरी नहीं, लेकिन सिर्फ commit messages और लौटने लायक versions होने से ही मैं अनगिनत बार बचा हूँ। अधिक advanced features की तो बात ही अलग है
  • यह काफ़ी भ्रमित करने वाला लेख है। सच में जिज्ञासा है कि यह नंबर 1 तक क्यों पहुँचा।

    • एक तरफ़ यह ऐसे developer की पोस्ट हो सकती है जो अपनी ज़िंदगी बेहतर बनाने के लिए अलग tools और techniques के साथ प्रयोग कर रहा है। दूसरी तरफ़ यह लोगों को बहस में धकेलने वाला bait भी हो सकता है
  • एक उचित test suite रखने की मुख्य प्रेरणा हताशा को कम करना है। test suite डेवलपर को सिस्टम को आगे विकसित करने का आत्मविश्वास देती है
    अगर इसे सही तरह से बनाया जाए, तो अक्सर ऐसा भी लगता है कि “बाकी चीज़ों को test करने का तरीका ढूँढना मुश्किल था, और फिर भी किसी तरह ठीक-ठाक आगे बढ़ गए।” जैसे-जैसे feature की जटिलता बढ़ती है, component या पूरे system को test करना संभालना मुश्किल हो सकता है। लेकिन test और version control को छोड़ देने से program बेहतर हो जाता है — यह दर्शन एक व्यक्ति से आगे नहीं बढ़ पाता। वह भी तभी संभव है जब उस व्यक्ति को source code में मौजूद वर्तमान और पुराने सभी निर्णय हाल की, घनिष्ठ स्मृति की तरह याद हों। और अगर implementation की गहरी समझ है, तो हर बदलाव का सत्यापन परिभाषा के अनुसार मैन्युअली करना पड़ेगा

    • पहले HN पर मैंने एक व्यक्ति की कहानी देखी थी, जो उस दिन खुद लिखा हुआ code न हो तो उसे कभी merge नहीं करता था
      अगर दिन के अंत तक वह merge करने लायक स्थिति में नहीं पहुँचा, तो इसका मतलब था कि उसने समस्या को एक दिन में व्यक्त कर सकने लायक पर्याप्त रूप से समझा ही नहीं था, इसलिए अगली सुबह वह फिर से नई कोशिश करता था। पता नहीं किसी और को यह याद है या नहीं, या मैं किसी दूसरी site या किस्से के साथ इसे गड़बड़ा रहा हूँ
    • एक one-person programming team के लिए यह बात सही है। सच कहूँ तो अकेले काम करते हुए भी test suite या version control के बिना programming करने का विचार ही डरावना लगता है
      documentation, test, और version control उस code context के बारे में मुझे कितना कुछ याद रखना पड़ेगा, इसे कम कर देते हैं। सामने मौजूद code की details तो याद रखनी होती हैं, लेकिन अगर मैं उसे document कर दूँ, test कर दूँ, और क्यों/कैसे बदला यह अच्छे commit message के साथ check in कर दूँ, तो मैं उस code को दिमाग से निकालकर अगले काम पर बढ़ सकता हूँ
  • बिंदु 3 में कही गई बात — “जिन लोगों/स्थान/फ़ीचर जैसे संदर्भों को आप support करना चाहते हैं, उनमें छोटा बदलाव भी program उस संदर्भ में कितना फिट बैठता है, इसे अचानक बदल सकता है” — का एक अच्छा उदाहरण K9 Mail है। अब वह Android के लिए Thunderbird बनता जा रहा है
    K9 Mail की शुरुआत एक गैर-पारंपरिक UI के साथ हुई थी, जो home screen पर email account की सूची दिखाता था और हर account के unread message count तथा कुल message count को प्रदर्शित करता था। एक unified inbox था, लेकिन उसे उपयोगकर्ता पर थोपा नहीं गया था। मुझे याद है कि मैंने यह app इसलिए चुना था क्योंकि मैं एक personal account, एक work account, और ग्राहकों द्वारा दिए गए कई work accounts को अलग-अलग रखना चाहता था। शायद बहुत से K9 users ने भी यही वजह से यह app चुना होगा। जब डेवलपर पारंपरिक Android UI पर गया, जिसमें account list बाईं ओर से slide होती थी और accounts के बीच जाने के लिए एक extra tap चाहिए था, तब इतनी शिकायतें इसी वजह से आईं। अगर हमें वैसा UI पसंद होता, तो संभव है कि हम शुरू से K9 चुनते ही नहीं। यानी एक छोटा बदलाव — भले उसके पीछे बहुत coding लगी हो — उस app की उपयोगकर्ता-उपयुक्तता को बिगाड़ गया। मैं अब भी पुराने UI वाला आख़िरी version 5.600 इस्तेमाल करता हूँ, और हर बार नया device लेने पर उसे sideload करता हूँ। और भी अजीब बात यह है कि account access के लिए मैं सिर्फ POP3 इस्तेमाल करता हूँ। फ़ोन पर पहले देख लेता हूँ, जो मिटाना हो मिटा देता हूँ, ज़रूरत पड़े तो खुद को BCC में रखकर जवाब भेजता हूँ, और फिर आख़िर में laptop पर download करता हूँ; K9 इस workflow के लिए बिल्कुल सही था। मुझे कुछ fancy नहीं चाहिए, 90s के app जैसा भी चलेगा

    • ऐसे ठोस उदाहरण के लिए मैं सच में आभारी हूँ। यह मूल लेख में लिखे मेरे विचारों और इस thread के सारे विचारों को जोड़ देने से भी ज़्यादा मूल्यवान है
      https://news.ycombinator.com/favorites?id=akkartik&comments=t
  • यह रास्ता आगे कहाँ जाएगा, यह सोचकर मैं भी उत्सुक रहता हूँ। एक बात तो साफ़ है: अकेले software बनाना, team में software बनाने से बिल्कुल अलग गतिविधि है
    tests के बारे में, test लक्ष्य नहीं बल्कि साधन हैं। मुझे लगता है कि हम असल में आत्मविश्वास ढूँढ रहे होते हैं। अगर implementation पर भरोसा है, तो tests कम किए जाते हैं। उल्टा, अगर कुछ ऐसा है जो हर हाल में लगातार काम करना चाहिए, तो मैं outer boundary पर कुछ integration tests जोड़ता हूँ, जिन पर refactoring का असर कम पड़े और रफ़्तार भी कम न हो। यानी अंदरूनी हिस्सों को test करने के बजाय web backend को बाहर से poke करना। unit tests नई API design को ठोस रूप देने में अच्छे होते हैं, लेकिन दिशा समझ आने के बाद वे tests लगभग बेकार हो जाते हैं

    • one-person project में भी test रखने के बहुत अच्छे कारण हैं
      जिस feature पर आप काम कर रहे हैं, वहाँ जल्दी पहुँचने के लिए true || जैसी चीज़ से if statement को अस्थायी रूप से fix कर देना समय लेता है और बाद में हटाना भी पड़ता है। बस एक test बनाकर चला देने से वह बाद में regression test के रूप में बचा रह सकता है। अगर आप कोई बड़ा app या slow app deploy कर रहे हैं, तो कभी-कभी सिर्फ Qt इस्तेमाल करने से ही build या run में समय लग जाता है; ऐसे में एक single test जल्दी load होता है और जल्दी run भी होता है। अगर bug reproduce करने में 45 सेकंड लगते हैं, तो test लिखना बेहतर है। यह काम के सबसे उबाऊ हिस्सों को automate करता है, flow बनाए रखता है, हर बार यह सोचे बिना कि जाँचना उचित है या नहीं, आपको मनचाही आवृत्ति से bug state जाँचने देता है, और यह भी regression test बनकर रह जाता है
  • मुझे यह लेखक सच में बहुत पसंद है, और Mu मेरे सबसे पसंदीदा projects में से एक है। यह modern Lisp machine जैसी कोई चीज़ है, और वह भी QEMU पर चलने वाला एक दिलचस्प project

  • यह पंक्ति बहुत पसंद आई: “ज़्यादातर software इतने गहराई से इस प्रोत्साहन से संक्रमित हैं कि वे कम समय में बहुत से लोगों की सेवा करें, कि उन्हें ठीक नहीं किया जा सकता।” software की जगह “business” रख दें, तब भी यह उतनी ही सही लगती है

  • हम सब किसी न किसी हद तक software engineering की जटिलता से अभिभूत हैं। कभी-कभी वह जटिलता आकस्मिक भी होती है
    लेकिन मुझे नहीं लगता कि दशकों में बने सभी विचारों को खारिज कर देना उसका समाधान है। उल्टा, हर समाधान को अक्षरशः स्वीकार कर लेना या उनका “बहुत ज़्यादा” इस्तेमाल करना भी ठीक नहीं। परिभाषा के अनुसार, अभिभूत होना तब होता है जब आप किसी चीज़ का बहुत अधिक उपयोग करने लगते हैं। tests का इस्तेमाल करें, version control system का इस्तेमाल करें, abstraction का इस्तेमाल करें, लेकिन क्यों इस्तेमाल कर रहे हैं यह जानना चाहिए। जब वह “क्यों” अब लागू न रहे, तो फिर से मूल्यांकन करना चाहिए

    • मेरे हिसाब से समस्याओं के बड़े स्रोतों में से एक academia है। मैं Denmark में CS छात्रों के लिए external examiner का काम करता हूँ, और वे अब भी object-oriented और onion architecture शैली में abstraction को upfront बनाना सीखते हैं
      यह software development में लगभग सबसे खराब आदेशों में से एक है। इससे भी बुरी बात यह है कि ये चीज़ें लगभग धर्म के स्तर पर सिखाई जाती हैं। अजीब बात यह है कि पिछले कई वर्षों में experts के software लिखने का तरीका बहुत बदल गया है। जैसा मैंने कहा, abstraction हर चीज़ में अपने-आप बुरी नहीं है। SQL database में जाने वाले सामान्य data के लिए updated, updated_by जैसे fields रखने वाली base class न हो, यह कल्पना करना भी मुश्किल है। लेकिन सामान्य तौर पर, जब तक सच में मजबूरी न हो, मैं abstraction का लगभग इस्तेमाल ही नहीं करता। फिर भी academia में आज भी वही curriculum पढ़ाया जा रहा है जो मैंने 25 साल पहले सीखा था। जब छात्रों की यह क्षमता आँकी जाती है कि वे शानदार UML के साथ विशाल abstraction बनाएँ और उसे code में लागू करें, तो यह बहुत अजीब लगता है। उनमें से 90% लोग शायद फिर कभी एक भी UML diagram नहीं देखेंगे। कम से कम, मेरे छोटे-से क्षेत्र में तो ऐसा ही है। फिर भी, वास्तविकता तो वास्तविकता है
    • मैंने वास्तव में Git का इस्तेमाल शुरू ही magit की वजह से किया था
      अच्छा होगा अगर हर चीज़ के लिए command line स्तर का “porcelain” हो। अगर standard --help=ui output और dialog शैली का interface हो, तो लगता है उसे automate किया जा सकता है। यह जटिलता से अभिभूत होने की बात कम है, और ज़्यादा इस बात की कि उपयोग में लाई जा सकने वाली सक्रिय muscle memory की मात्रा की एक सीमा होती है, और कहीं न कहीं कटौती करनी ही पड़ती है