Steven
Steven7 मिनट पढ़ें

सॉफ़्टवेयर को परफेक्शन तक शिप करने की एनाटॉमी: कोड रिव्यू ने वह पकड़ा जो टेस्ट न पकड़ सके

GeekBye v2 सीरीज़ में बार-बार वही एक चीज़ होती रही: एक फिक्स डेवलपर की मशीन पर हर टेस्ट पास कर जाता है, और फिर कोड रिव्यू साबित कर देता है कि यह करीब-करीब सबके लिए फेल हो जाता। यह नौ रिलीज़ के पीछे की वर्कफ़्लो है — रिव्यू गेट, फिक्स-फर्स्ट कैच, और शिप-से-पहले-टेस्ट का अनुशासन जो 'मेरे यहाँ तो चलता है' को 'यह चलता है' में बदल देता है।

इंजीनियरिंग
प्रक्रिया
कोड रिव्यू
GeekBye रिलीज़
सॉफ़्टवेयर को परफेक्शन तक शिप करने की एनाटॉमी: कोड रिव्यू ने वह पकड़ा जो टेस्ट न पकड़ सके

कुछ हफ़्तों में GeekBye ने नौ रिलीज़ शिप कीं — v2.0.0 से v2.0.11 तक — और इस सीरीज़ ने हर एक की कहानी सुनाई। इन्हें साथ पढ़िए तो एक पैटर्न उभरकर सामने आता है जो किसी भी अकेले बग से ज़्यादा दिलचस्प है: बार-बार, एक फिक्स डेवलपर की मशीन पर हर टेस्ट पास कर गया, और कोड रिव्यू ने साबित कर दिया कि यह करीब-करीब बाकी सबके लिए फेल हो जाता।

वही फासला — ''मेरे यहाँ तो चलता है'' और ''यह चलता है'' के बीच — जहाँ भरोसेमंदी असल में बसती है। यह वही वर्कफ़्लो है जो उसे पाटता है, और उससे बनी हर रिलीज़ का इंडेक्स।

पैटर्न: हरे टेस्ट, गलत जवाब

सीरीज़ के सबसे साफ़ तीन मामले यहाँ हैं, क्योंकि ये अमूर्त को ठोस बना देते हैं।

  • मल्टी-मॉनिटर कैप्चर फिक्स (v2.0.10) में, पहले इम्प्लीमेंटेशन ने स्क्रीन कैप्चर को ऐप की ओवरले विंडो पर ऐंकर किया। यह टेस्टिंग पास कर गया — एक सिंगल-मॉनिटर डेव मशीन पर। रिव्यू ने इस पर तर्क किया कि वह ओवरले असल में कहाँ रहता है (हमेशा प्राइमरी डिस्प्ले पर, जब तक आप उसे शारीरिक रूप से घसीट न लें) और साबित कर दिया कि यह ''फिक्स'' करीब-करीब हर असली यूज़र के लिए वापस उसी गलत मॉनिटर पर पहुँच जाता। सही ऐंकर — कर्सर — उस बहस से निकला, किसी टेस्ट रन से नहीं।
  • WebSocket-fallback रिलीज़ (v2.0.8) में, रिव्यू ने पाया कि ब्लॉक करने वाला proxy जो ठीक-ठीक 403 लौटाता है, वह एक fatal auth error के तौर पर वर्गीकृत था — इसलिए जिस fallback को ट्रिगर करने के लिए यह फीचर मौजूद था, वह कभी चल ही न पाता। फीचर शिप हो जाता, अपने happy-path टेस्ट पास कर लेता, और अपने असली दर्शकों के लिए कुछ न करता।
  • idle-timeout फिक्स (v2.0.9) में, पहला वर्ज़न ''अभी ज़िंदा है'' वाली घड़ी को एक ऐसे कोड पाथ के अंदर स्टैंप करता था जिसे ट्रांसक्रिप्ट का एक हिस्सा वाजिब तौर पर छोड़ देता है — दूसरे वक्ता का। रिव्यू ने पकड़ा कि आगे का कोई बदलाव चुपचाप ठीक उसी बग को फिर से पैदा कर सकता है जिसे फिक्स किया जा रहा था, और स्टैंप को कहीं ऐसी जगह ले जाया गया जो शर्त-रहित हो, साथ में एक टेस्ट जो उसे वहीं टिकाए रखे।

इनमें से कोई भी कोड चलाकर नहीं पकड़ा गया। ये सब एक रिव्यूअर द्वारा इस पर तर्क करके पकड़े गए कि कोड क्यों चलता है — और एक ऐसा मामला ढूँढकर जहाँ नहीं चलता।

गेट के तीन हिस्से

सीरीज़ के पीछे की वर्कफ़्लो कोई पेचीदा चीज़ नहीं। ये तीन आदतें हैं, बिना किसी अपवाद के लागू।

1. रिव्यू सिर्फ़ कोड चलाता नहीं, सहीपन पर तर्क करता है। एक पास होता टेस्ट साबित करता है कि कोड उस मामले के लिए चलता है जो आपने सोचा था। रिव्यू सिस्टम का एक दूसरा, अडवर्सेरियल मॉडल है जो पूछता है किस मामले के बारे में आपने नहीं सोचा? — दूसरा मॉनिटर, कॉर्पोरेट proxy, वह ट्रांसक्रिप्ट जो शाखा को छोड़ देता है, वह क्लाइंट जो एक वर्ज़न पीछे है। इस सीरीज़ में रिव्यू स्टेप अक्सर एक स्वतंत्र एजेंट रिव्यूअर था जिसे फिक्स को खारिज करने के लिए कहा गया, आशीर्वाद देने के लिए नहीं। यही फ्रेमिंग असली बात है: एक रिव्यूअर जो आपके तर्क को तोड़ने की कोशिश करता है, वह छेद ढूँढ लेता है जिसे मंज़ूरी देने की कोशिश करने वाला रिव्यूअर सरसरी निगाह से छोड़ जाता है।

2. हर बिहेवियर फिक्स एक ऐसे टेस्ट के साथ शिप होता है जो ठीक-ठीक उसी फेल्योर को पिन करता है। ऐसा टेस्ट नहीं जो साबित करे कि फीचर चलता है — ऐसा टेस्ट जो साबित करे कि यह ख़ास बग मर चुका है। ब्लॉक-किए-गए proxy का 403 ज़रूर fallback तक पहुँचे; एक असली auth 403 ज़रूर न पहुँचे। activity घड़ी ज़रूर एक ऐसे ट्रांसक्रिप्ट पर स्टैंप करे जो attribution को छोड़ देता है। ये टेस्ट इसलिए हैं ताकि छह महीने बाद जब कोई पास में रिफैक्टर करे तो बग चुपचाप वापस न आ सके — फेल्योर फ़र्श में ठोक दिया गया।

3. बिल्ड शिप होने से पहले notarized और वेरिफ़ाई होता है। इनमें से कई फिक्स डायग्नोसिस से लेकर एक signed, notarized, ऑटो-अपडेट होती रिलीज़ तक एक ही दिन में पहुँच गए। वह रफ़्तार सिर्फ़ इसलिए सुरक्षित है क्योंकि गेट अनुशासित है: डायग्नोस्टिक मूल कारण साबित करता है (माइक्रोफ़ोन-परमिशन रिलीज़ ने अपना डायग्नोस्टिक पहले शिप किया), टेस्ट फिक्स को पिन करता है, रिव्यू तर्क को खारिज करने की कोशिश करता है, और तभी एक असली notarized बिल्ड बाहर जाता है। सख़्ती वही है जो रफ़्तार को सुरक्षित बनाती है, न कि वह जिससे रफ़्तार की सौदेबाज़ी होती है।

एक AI ऐप के लिए यह ज़्यादा क्यों मायने रखता है

एक वजह है कि GeekBye जैसे टूल के लिए ख़ासकर यह अनुशासन गैर-समझौता है। सीरीज़ के कई सबसे शातिर बग खामोशी-से-गलत थे, न कि क्रैश-जैसे शोर वाले: एक स्क्रीनशॉट जो AI को गलत मॉनिटर खिला देता (v2.0.10), एक ट्रांसक्रिप्शन जो कचरा शब्दों की ओर झुका हुआ था इसलिए ''speak'' एक नाम बनकर निकला (v2.0.11), एक असिस्टेंट जो गलत मोड में जवाब देता और उसे देखने का कोई ज़रिया नहीं (v2.0.3 + v2.0.5)। जब आपका ऐप किसी मॉडल को context खिलाता है, तो एक गलत इनपुट भरोसे-भरा गलत आउटपुट पैदा करता है और कहीं कोई error नहीं। जो फेल्योर throw ही नहीं करते, आप उनसे टेस्ट करके बाहर नहीं निकल सकते। आपको तर्क करके बाहर निकलना पड़ता है — जिसके लिए ठीक-ठीक रिव्यू गेट है।

सीरीज़, क्रम में

इनमें से हर एक किसी एक रिलीज़ का अपने-आप में पूरा केस स्टडी है। शुरू से आख़िर तक पढ़िए, ये एक प्रोडक्ट को ''चलता है'' से ''भरोसेमंद है'' तक ले जाने की एनाटॉमी हैं।

  1. एक वर्ज़न 2 असल में क्या माँगता है: ईमानदार स्टेट्स के 206 कमिट — v2.0.0. बुनियाद: कभी ऐसी स्टेट न दिखाओ जो सच न हो।
  2. जिस दिन हमारे ऐप ने खुद पर DDoS किया — v2.0.1 + v2.0.4. एक स्टार्टअप अपलोड बैकलॉग जो हमारे ही बैकएंड को कुचल रहा था, और जिस liveness सीढ़ी को इसने मजबूर किया।
  3. शांत सॉफ़्टवेयर: फ़्लिकर फिक्स और आंसर-मोड चिप — v2.0.3 + v2.0.5. बिना-फीचर वाली रिलीज़ जिन्होंने एक-एक ब्योरे से भरोसा खरीदा।
  4. आपका Mac ऐप हर लॉन्च पर माइक्रोफ़ोन एक्सेस भूल जाता है — v2.0.6. macOS App Translocation, और फिक्स से पहले डायग्नोस्टिक शिप करना।
  5. एक CSS वेरिएबल, पाँच रिव्यू राउंड, और एक Swift टूलचेन जिसने झूठ बोला — v2.0.7. एकसमान पारदर्शिता, और एक बाइनरी जिसका आकार बदल गया क्योंकि डॉक्स एनफ़ोर्समेंट स्क्रिप्ट से असहमत थे।
  6. जब फ़ायरवॉल WebSocket को ब्लॉक कर दे, तब लाइव ट्रांसक्रिप्शन — v2.0.8. एक प्योर-HTTPS fallback, और वह 403 जो उसे खुद से ही छुपा देता।
  7. आपका AI नोटटेकर मीटिंग के बीच में रिकॉर्डिंग क्यों बंद कर देता है — v2.0.9. एक idle टाइमर जो सिर्फ़ आपको सुन सकता था, और एक क्रैश जो आपके डेस्कटॉप को लॉक कर सकता था।
  8. स्क्रीन रिकॉर्डिंग गलत मॉनिटर क्यों कैप्चर करती है — v2.0.10. गलत-डिस्प्ले बग, और वह फिक्स जो एक मॉनिटर पर पास हुआ और दो पर फेल हो जाता।
  9. AI ट्रांसक्रिप्शन तकनीकी शब्दों को गलत क्यों सुनता है — v2.0.11. स्पीच को आपकी शब्दावली की ओर झुकाना — और वह regression जिसने बेहतर करने से पहले इसे बदतर बना दिया।

निचोड़

परफेक्शन कोई स्टेट नहीं जहाँ आप पहुँचते हैं; यह एक गेट है जिसे आप बनाए रखते हैं। नौ रिलीज़, और हर एक पर वही तीन सवाल: किस मामले के बारे में आपने नहीं सोचा, क्या ठीक फेल्योर एक टेस्ट से पिन है, और क्या एक असली signed बिल्ड सचमुच बाहर गया? इनमें से कुछ भी चमक-दमक वाला नहीं। ये सब मिलकर वह वजह हैं कि GeekBye v2 शांत महसूस होता है। अगर आप सॉफ़्टवेयर बनाते हैं — AI या कुछ और — तो हस्तांतरणीय हिस्सा कोई एक फिक्स नहीं। यह वह आदत है कि एक हरे टेस्ट सूट को बहस के अंत की जगह उसकी शुरुआत मानो।

ऊपर की हर रिलीज़ ऑटो-अपडेट के ज़रिए लाइव है। ये फिक्स मिलकर जो प्रोडक्ट बनाते हैं, उसके लिए देखिए GeekBye v2 में नया क्या है

संबंधित लेख

ख़ामोशी भार-वहन कर रही थी
Steven
Steven9 मिनट पढ़ें

ख़ामोशी भार-वहन कर रही थी

GeekBye v1 की आख़िरी दो releases एक ही असहज सच्चाई के बारे में हैं: एक असली network पर real-time transcription लॉसलेस नहीं है, और ईमानदार चाल है यह दिखावा बंद करना कि वह है। v1.8.20 ने एक reconnect के दौरान हर audio chunk को गिराने से पहले उसकी एक प्रति disk पर रखी, और transcript के अंतरालों को ज़ोर से चिह्नित करना शुरू किया। v1.9.0 ने bandwidth बचाने के लिए silence भेजना बंद किया — और पाया कि वह silence ही वह ठीक-ठीक संकेत था जिससे transcriber जानता था कि एक वाक्य ख़त्म हो चुका है। चीज़ें फेंक देने की क़ीमत के बारे में दो releases।

इंजीनियरिंग
Audio
विश्वसनीयता
तीन क्रियाएँ जो Web Audio को ज़िंदा रखती हैं
Steven
Steven10 मिनट पढ़ें

तीन क्रियाएँ जो Web Audio को ज़िंदा रखती हैं

GeekBye की दो point releases, दो महीने के फ़ासले पर और दो अलग files में, हमारे audio code को उलटे छोरों से एक ही सबक़ सिखा गईं: browser के AudioContext को इस्तेमाल-कर-फेंको जैसा मानना बंद करो। एक release ने एक ऐसे context को resume() करना सीखा जिसे macOS ने record के बीचोंबीच चुपचाप suspend कर दिया था; दूसरी ने close() के बजाय suspend() करना सीखा ताकि पीठ-दर-पीठ चलती sessions Chromium की लगभग-छह-context वाली छत से टकराना बंद कर दें। resume, suspend, close — यही पूरी कहानी है।

इंजीनियरिंग
Audio
डेस्कटॉप
एक call को एक खुले हुए app से अलग पहचानना
Steven
Steven10 मिनट पढ़ें

एक call को एक खुले हुए app से अलग पहचानना

GeekBye यह ताड़ सकता है कि आप एक video meeting में शामिल हो गए हैं और एक क्लिक में उसे record करने की पेशकश करता है। पता चलता है कि detection ही आसान वाला आधा था — एक Swift binary जो हर दस सेकंड window titles पढ़ती है। मुश्किल आधा है सटीकता: जब Zoom बस खुला हो तब न भड़कना, एक ऐसी meeting के लिए न टोकना जिसे आप पहले से record कर रहे हैं, और उस call में microphone को mute न करना जिसमें आप असल में हैं। तीन releases, और हर एक एक ऐसा guard है जिसे ख़ुद को न हराना सीखना पड़ा।

इंजीनियरिंग
macOS
डेस्कटॉप