दीर्घकालिक (long term) सॉफ़्टवेयर विकास
(berthub.eu)- आधुनिक सॉफ़्टवेयर को continuous delivery (CD) और automated testing (CI) के ज़रिए बार-बार अपडेट किया जाता है, लेकिन "लंबे समय तक उपयोग होने वाले सॉफ़्टवेयर" के लिए अलग दृष्टिकोण की ज़रूरत होती है
- उदाहरण: परमाणु ऊर्जा संयंत्र, विमान, pacemaker, चुनाव प्रणाली आदि
- जिन क्षेत्रों में reliability और stability महत्वपूर्ण हैं, वहाँ लगातार बदलाव की बजाय स्थिरता और अनुमानित बदलाव को प्राथमिकता दी जाती है
- उदाहरण: परमाणु ऊर्जा संयंत्र, विमान, pacemaker, चुनाव प्रणाली आदि
दीर्घकालिक सॉफ़्टवेयर विकास के मुख्य सिद्धांत
निर्भरताएँ (Dependencies)
- सॉफ़्टवेयर की dependencies उसकी दीर्घकालिक सफलता का महत्वपूर्ण तत्व हैं
- सॉफ़्टवेयर को बाहरी दुनिया के साथ होने वाली अंतःक्रिया को ध्यान में रखना चाहिए, और programming language जैसी बुनियादी पसंदें महत्वपूर्ण होती हैं
- सॉफ़्टवेयर dependency layers को समझना
- बाहरी दुनिया: client software जिसे हम नियंत्रित नहीं कर सकते (जैसे browser आदि)।
- बुनियादी विकल्प: programming language जैसे तत्व, जिन्हें बदलने के लिए पूरे stack को फिर से लिखना पड़ सकता है।
- framework: Spring Framework, React आदि, जो codebase के साथ मज़बूती से जुड़े होते हैं। इन्हें बदला जा सकता है, लेकिन इसकी लागत बहुत अधिक होती है।
- database: अधिकतर मामलों में बदला जा सकता है, लेकिन इसके लिए बारीक समायोजन और काम की ज़रूरत होती है।
- helper libraries: ऐसे बदले जा सकने वाले libraries जो किसी विशेष function को उपलब्ध कराते हैं।
- समय के साथ dependencies और बाहरी दुनिया बदलती रहती हैं:
- dependencies में बदलाव के कारण code changes या behavior changes हो सकते हैं।
- नए major version आने पर compatibility issues पैदा हो सकते हैं।
- project के बंद हो जाने या गायब हो जाने का जोखिम।
- security risk: dependency के किसी malicious actor द्वारा compromise हो जाने की संभावना (
npm,PyPIआदि)। - commercialization: नए venture capital (VC) मालिकों द्वारा उसे paid बना देना।
- dependencies के बीच conflicts की समस्या।
- दीर्घकालिक उपयोग को ध्यान में रखते हुए dependencies चुनते समय जाँचने योग्य बिंदु:
- तकनीकी स्तर: क्या source code देखकर उसकी quality का आकलन किया जा सकता है।
- user base: कौन इसका उपयोग कर रहा है, यह देखना।
- development purpose: developer कौन हैं और उनका लक्ष्य क्या है, यह समझना।
- financial support: funding है या नहीं, और उसका स्रोत क्या है।
- maintenance: क्या security releases नियमित रूप से आते हैं।
- क्या community maintenance अपने हाथ में ले सकती है।
- क्या मैं स्वयं maintenance कर सकता हूँ।
- क्या ज़रूरत पड़ने पर financial support देकर project की sustainability सुनिश्चित करनी चाहिए।
- dependencies की dependencies:
- निचले स्तर की dependencies के security history की भी समीक्षा करें।
- व्यावहारिक दृष्टिकोण
- dependency limits:
- 1600 से अधिक dependencies वाले projects में code तेज़ी से बदल सकता है और अस्थिर हो सकता है।
- बहुत अधिक dependencies वाले project में यह समझना भी कठिन हो जाता है कि वास्तव में कौन-सा code deploy किया जा रहा है।
- सावधानी से जोड़ें:
- dependency जोड़ते समय उसे technical difficulty जैसा भार दें, ताकि स्वाभाविक review time मिल सके।
- दीर्घकालिक project में अनावश्यक dependencies से बचना चाहिए।
- dependency limits:
runtime dependencies
- अब तक की चर्चा build/compile dependencies तक सीमित थी।
- लेकिन आधुनिक projects में अक्सर runtime dependencies भी शामिल होती हैं:
- उदाहरण: Amazon S3, Google Firebase।
- कुछ को लगभग standard की तरह माना जाता है (जैसे S3)।
- लेकिन अधिकतर runtime dependencies किसी खास service में lock-in पैदा करती हैं।
- 10 साल बाद भी आज उपयोग हो रही service का विकल्प ढूँढना बहुत महँगा साबित हो सकता है।
- third-party service dependencies की सूची को न्यूनतम रखें या ख़ाली रखें:
- खासकर cloud native software development में कई advanced third-party services का उपयोग आम है।
- लेकिन दीर्घकालिक projects के लिए ऐसी dependencies बहुत अधिक risk लाती हैं।
- build-time service dependencies भी महत्वपूर्ण हैं:
- उदाहरण: अगर
npm installकाम करना बंद कर दे, तो सॉफ़्टवेयर को build करना ही असंभव हो सकता है। - इससे project की reusability गंभीर रूप से घट सकती है।
- उदाहरण: अगर
- runtime dependencies की गहराई से समीक्षा करें:
- संभावित lock-in issues को पहचानें, और dependencies को कम या समाप्त करें।
- दीर्घकालिक maintainability सुनिश्चित करें:
- cloud या third-party services को बदलने की संभावना पर पहले से विचार करें।
test, test, और test
- testing की आवश्यकता एक बुनियादी सिद्धांत है जिस पर लगभग सभी सहमत हैं:
- जितने संभव हों उतने अधिक tests लिखें।
- सभी tests समान मूल्य के नहीं होते, लेकिन test लिखने पर पछताना बहुत कम पड़ता है।
- खासकर बहुत-सी dependencies वाले projects में testing अनिवार्य है:
- dependencies बदलने या drift होने पर यह समस्याओं को जल्दी पहचानने में मदद करती है।
- testing की भूमिका
- समस्या-समाधान में सहायता:
- बदलाव की स्थिति के अनुसार तेज़ी से समायोजन संभव बनाती है।
- refactoring में सहायता:
- code dependencies को हटाते या बदलते समय आत्मविश्वास देती है।
- दीर्घकालिक maintenance में उपयोगी:
- 3 साल या उससे अधिक समय तक development रुके रहने के बाद भी tests के ज़रिए यह जाँचा जा सकता है कि system अभी भी काम कर रहा है या नहीं।
- नए compiler, runtime और operating system पर भी functionality बनी हुई है या नहीं, यह सत्यापित किया जा सकता है।
- समस्या-समाधान में सहायता:
- testing कोई लागत नहीं, बल्कि investment है
- और अधिक tests लिखें:
- tests maintenance और stability की नींव हैं।
- code बदलते या बढ़ाते समय tests बहुत बड़ा मानसिक सहारा देती हैं।
- और अधिक tests लिखें:
जटिलता: सॉफ़्टवेयर विकास का अंतिम बॉस
- जटिलता सॉफ़्टवेयर विकास की परम शत्रु है:
- सबसे अच्छे developer या team भी जटिलता के सामने टूट सकते हैं।
- entropy और मानवीय व्यवहार के प्रभाव से जटिलता हमेशा बढ़ती है।
- अगर जटिलता को जानबूझकर manage न किया जाए, तो project असंभालनीय स्थिति में जा सकता है।
- जटिलता और code की मात्रा का संबंध
- code की मात्रा और जटिलता:
- code कम हो तो थोड़ी जटिलता भी manageable हो सकती है।
- code बढ़ने के साथ simplicity बनाए रखना ज़रूरी है, तभी चीज़ें नियंत्रण में रहती हैं।
- manageable complexity team की क्षमता और "हरे त्रिकोण" के भीतर होनी चाहिए।
- जटिलता की सीमा:
- team के लोगों की संख्या बढ़ाने या बहुत कुशल developers रखने पर भी जटिलता सँभालने की एक सीमा होती है।
- उस सीमा के पार project maintenance-असंभव स्थिति में पहुँच जाता है।
- code की मात्रा और जटिलता:
- code हमेशा 'ऊपर-दाईं ओर' क्यों बढ़ता है: (ग्राफ़ में)
- और अधिक feature requests।
- अनावश्यक optimization की कोशिशें।
- bug fix करते समय मौजूदा जटिलता घटाने की बजाय नया code जोड़ना।
- गलत API design की लागत:
- उदाहरण:
CreateFilefunction अधिकांश मामलों में file बनाता ही नहीं है। - ऐसी उलझन अतिरिक्त cognitive load और गलती की संभावना बढ़ाती है।
- उदाहरण:
- जटिलता प्रबंधन की रणनीतियाँ
- refactoring जल्दी और बार-बार करें:
- अनावश्यक code हटाएँ और सरल बनाने में समय लगाएँ।
- testing में निवेश करें:
- जितने अधिक tests होंगे, जटिलता घटाने का काम उतना आसान होगा।
- जटिलता प्रबंधन का महत्व:
- अगर सरलता के लिए पहले से प्रयास नहीं किया, तो दीर्घकालिक project अंततः "maintenance impossible" स्थिति में गिरने का जोखिम रखता है।
- refactoring जल्दी और बार-बार करें:
उबाऊ और सरल code लिखें। उससे भी अधिक सरल। और उससे भी अधिक उबाऊ।
"Debugging किसी program को लिखने से दोगुना कठिन है। इसलिए यदि आप code लिखते समय अपनी पूरी चतुराई लगा देते हैं, तो फिर उसे debug कैसे करेंगे?" - Brian Kernighan
- बेहद उबाऊ और स्पष्ट code लिखें:
- naive लेकिन सीधे समझ आने वाले code को प्राथमिकता दें।
- "premature optimization सभी बुराइयों की जड़ है।"
- optimization केवल तब करें जब वास्तव में ज़रूरी हो:
- अगर अभी code बहुत सरल है और वही समस्या बन जाए, तो बाद में जटिलता जोड़ना मुश्किल नहीं है।
- हो सकता है वह समय कभी आए ही नहीं।
- जटिल code लिखने से बचें:
- बिल्कुल आवश्यक होने तक प्रतीक्षा करें।
- सरल code लिखने पर पछताने की संभावना बहुत कम होती है।
- high-performance code या features केवल खास वातावरण में ही काम कर सकते हैं।
- उदाहरण:
- LMDB: PowerDNS में इसे स्थिर रूप से उपयोग करने तक बहुत कठिनाइयाँ आईं।
- RapidJSON: SIMD-accelerated JSON library। performance शानदार है, लेकिन उपयोग की शर्तें कठिन हैं।
- उदाहरण:
- भले ही आपको भरोसा हो कि "मैं इन सीमाओं को पार कर सकता हूँ":
- इस साल संभव हो, फिर भी 5 साल बाद आप या आपके बाद आने वाले developer को कठिनाई हो सकती है।
- जटिल programming languages पर भी यही सिद्धांत लागू होता है।
- निष्कर्ष:
- code को सरल बनाइए:
- सचमुच सरल। उससे भी अधिक सरल।
- optimization बाद के लिए टालिए:
- ज़रूरत होने पर जटिलता बाद में जोड़ी जा सकती है, लेकिन शुरुआत में ही चीज़ों को जटिल बना देने पर maintenance कठिन हो जाती है।
- code को सरल बनाइए:
LinkedIn-आधारित सॉफ़्टवेयर विकास
- वास्तविकता बनाम आदर्श
- आदर्श दृष्टिकोण: dependency चुनते समय गहराई से मूल्यांकन और समीक्षा करें (ऊपर दी गई checklist का उपयोग करें)।
- व्यावहारिक वास्तविकता: कभी-कभी लोग आकर्षक technology को आज़माते हैं, और अगर वह चल जाए तो उसी का उपयोग करते रहते हैं।
- आकर्षण के कारण
- LinkedIn के मशहूर लोगों या influencers द्वारा सुझाई गई technology।
- Hacker News जैसे community में खूब सराही गई "latest framework"।
- trending technologies का दीर्घकालिक सत्यापन कम होता है:
- वे "10 साल से अधिक समय तक चलने वाले software project" के लिए उपयुक्त न भी हों।
- नई technologies में शुरुआती चरण में stability और maintainability से जुड़ी समस्याएँ आने की संभावना अधिक होती है।
- सिफ़ारिशें
- केवल experimental क्षेत्रों में उपयोग करें:
- नई technology को पहले छोटे projects या non-core क्षेत्रों में परखें।
- Lindy effect पर विचार करें:
- किसी technology की आयु अक्सर उसके अब तक के उपयोग-काल के अनुपात में बढ़ती है।
- जितनी पुरानी technology, उतनी अधिक दीर्घकालिक स्थिरता की उम्मीद।
- केवल experimental क्षेत्रों में उपयोग करें:
- नई technologies आकर्षक लग सकती हैं, लेकिन दीर्घकालिक projects के लिए tested और stable technologies अधिक उपयुक्त हैं।
logging, telemetry, performance
- अगर software लगातार update या deploy नहीं किया जाता:
- website टूटने पर तुरंत feedback न मिल पाने की संभावना अधिक होती है।
- deploy के बाद वास्तविक समस्या-समाधान तक पहुँचने में लंबा समय लग सकता है।
- पहली release से ही thorough logging और telemetry लागू करें:
- software की performance, failures, और activity history रिकॉर्ड करें।
- समय के साथ जमा हुआ data, कम-घटने वाले bugs को ठीक करने में बेहद उपयोगी होता है।
- कम logging से होने वाली समस्याएँ:
- एक user ने UI deploy होने के बाद 3000 folders बना दिए और फिर समस्या report की।
- user ने केवल इतना कहा, "काम नहीं करता", इसलिए root cause समझने में महीनों लग गए।
- अगर performance logging और telemetry होती, तो समस्या कहीं तेज़ी से हल हो सकती थी।
- logging और telemetry अनिवार्य हैं:
- software activity को गहराई से monitor करने योग्य ढंग से design करें।
- दीर्घकालिक deployment और maintenance के दौरान अनपेक्षित समस्याओं के समाधान में बहुत मदद मिलती है।
documentation
- documentation का महत्व:
- केवल API docs अच्छी तरह लिखना ही काफ़ी नहीं, बल्कि "ऐसा design क्यों किया गया" यह भी समझाना चाहिए।
- system कैसे काम करता है, उससे जुड़े विचार और philosophy को दर्ज करें।
- solution को अलग तरह से बनाने के कारण और non-intuitive design decisions के आधार को भी छोड़ना चाहिए।
- architecture documents के अलावा उपयोगी सामग्री:
- internal blog posts: जहाँ developers system design पर खुली चर्चा साझा करें।
- team interviews: जिनमें design decisions की पृष्ठभूमि दर्ज हो।
- ऐसे documents समय बीतने पर भी team के भीतर knowledge transfer संभव बनाते हैं।
- code में comments छोड़ें:
- "अच्छे code को comments की ज़रूरत नहीं" जैसी प्रवृत्ति के बावजूद, code के 'क्यों' को समझाने वाले comments आवश्यक हैं।
- किसी खास function के अस्तित्व का कारण बताने वाली जानकारी महत्वपूर्ण है।
- commit messages लिखें:
- commit messages कार्य-इतिहास का मुख्य हिस्सा हैं। इनके माध्यम से code changes के कारणों को trace किया जा सकता है।
- ऐसा वातावरण बनाएँ जहाँ लोग commit messages आसानी से देख सकें।
- documentation के लिए समय सुरक्षित रखें:
- जिस दिन development अच्छा न चल रहा हो, उस दिन उपयोगी comments और records छोड़ने में समय लगाएँ।
- team स्तर पर documentation के लिए नियमित समय निर्धारित करें।
- यह दर्ज करें कि design ऐसा क्यों किया गया:
- 7 साल बाद नई team तक philosophy और background पहुँचाने वाली सामग्री बेहद मूल्यवान होती है।
- comments और commit messages के ज़रिए इतिहास छोड़ें:
- यह केवल development के दौरान ही नहीं, बल्कि दीर्घकालिक maintenance के लिए भी अनिवार्य है।
टीम संरचना
- team continuity और software की दीर्घकालिक सफलता:
- कुछ software को 80 साल तक support करने के लिए design किया जाता है। ऐसे दीर्घकालिक projects में team का बने रहना केंद्रीय महत्व रखता है।
- आधुनिक development environment में औसतन 3 साल की नौकरी भी लंबी tenure मानी जाती है।
- अच्छी documentation और testing team बदलने के असर को कुछ हद तक कम कर सकती हैं, लेकिन उनकी भी सीमा है।
- लंबे समय तक बने रहने के फायदे:
- 10 साल या उससे अधिक समय तक team members को बनाए रखना:
- लोगों को वास्तविक कर्मचारियों के रूप में रखना और developers को अच्छी तरह manage करना महत्वपूर्ण है।
- इसे दीर्घकालिक project success का एक अहम "hack" माना जा सकता है।
- 10 साल या उससे अधिक समय तक team members को बनाए रखना:
- outsourcing पर निर्भरता की समस्या:
- बाहरी developers अक्सर code system को सौंपकर चले जाते हैं।
- अगर लक्ष्य 10 साल से अधिक टिकने वाली software quality है, तो यह बेहद अप्रभावी तरीका है।
- ऐसा वातावरण बनाएँ जिसमें team members लंबे समय तक साथ काम कर सकें।
- बाहरी consultants पर निर्भरता कम करें, और internal team की sustainability बढ़ाने की रणनीति बनाएँ।
open source पर विचार करें
- open source के फायदे:
- बाहरी review के माध्यम से code quality बनाए रखना:
- बाहरी नज़र developers से ऊँचे standards की अपेक्षा करती है।
- बेहतर code standards बनाए रखने का मज़बूत तंत्र।
- बाहरी review के माध्यम से code quality बनाए रखना:
- open source की तैयारी की वास्तविकता:
- कंपनियाँ या सरकारें अक्सर कहती हैं कि open source बनाने की तैयारी में महीनों से लेकर सालों तक लग जाते हैं।
- कारण:
- आंतरिक रूप से अक्सर ऐसा code लिखा जाता है जिसे बाहर दिखाने में संकोच होता है।
- open source करने से पहले code साफ़-सुथरा करना पड़ता है।
- उपयुक्तता का आकलन:
- open source हमेशा संभव विकल्प नहीं होता।
- अगर संभव हो, तो यह code quality और transparency बढ़ाने का अच्छा तरीका है।
- जहाँ संभव हो, open source एक महत्वपूर्ण रणनीति है।
- बाहरी नज़र और ऊँचे standards project को सही दिशा में बनाए रखने में मदद करते हैं।
dependency health check
- dependencies में बदलाव की समस्या:
- समय के साथ dependencies अपेक्षा से अलग बदल सकती हैं या दिशा बदल सकती हैं।
- अगर इसे यूँ ही छोड़ दिया जाए, तो:
- bugs
- build failures
- और अन्य निराशाजनक परिणाम सामने आ सकते हैं।
- नियमित health check की सिफ़ारिश:
- periodic dependency checks:
- पहले से समस्याएँ खोजने का मौका देते हैं।
- dependency के नए features खोजकर code को सरल करने या दूसरी dependencies हटाने की संभावना भी दिखा सकते हैं।
- preventive maintenance का महत्व:
- अगर आप स्वयं review time plan नहीं करेंगे, तो समस्या आने पर वही समय आपको मजबूरन देना पड़ेगा।
- periodic dependency checks:
- maintenance का रूपक:
- मैकेनिकों की कहावत:
- "maintenance का समय खुद तय करो, नहीं तो equipment वह समय खुद तय कर देगा।"
- मैकेनिकों की कहावत:
- नियमित dependency checks, दीर्घकालिक software stability और efficiency के लिए अनिवार्य अभ्यास हैं।
- इन्हें समस्याएँ पहले से हल करने और सकारात्मक बदलाव खोजने के अवसर की तरह उपयोग करें।
प्रमुख संदर्भ पुस्तकें
- The Practice of Programming (Brian W. Kernighan, Rob Pike)
- The Mythical Man-Month (Fred Brooks)
- A Philosophy of Software Design (John Ousterhout)
- Kill It with Fire: Manage Aging Computer Systems (Marianne Bellotti)
अंत में
दीर्घकालिक सॉफ़्टवेयर विकास के लिए मुख्य सिफ़ारिशें:
- सरलता बनाए रखें:
- सरल रखें, उससे भी अधिक सरल! ज़रूरत पड़ने पर बाद में जटिलता जोड़ी जा सकती है, इसलिए शुरुआत में चीज़ों को अनावश्यक रूप से जटिल न बनाएँ।
- सरलता बनाए रखने के लिए नियमित refactoring और code deletion ज़रूरी हैं।
- dependencies के बारे में सावधानी से सोचें:
- जितनी कम dependencies हों, उतना बेहतर। ध्यान से review और audit करें।
- अगर आप 1600 dependencies का audit नहीं कर सकते, तो योजना पर पुनर्विचार करना चाहिए।
- trends या hype (जैसे LinkedIn-आधारित development) के पीछे चलने वाले चुनावों से बचें।
- नियमित dependency checks: dependencies की स्थिति पर लगातार नज़र रखें।
- test, test, और test:
- बदलती dependencies को समय रहते पहचानें।
- refactoring के दौरान आत्मविश्वas देते हैं और simplicity बनाए रखने में मदद करते हैं।
- documentation:
- केवल code ही नहीं, बल्कि philosophy, ideas, और "ऐसा क्यों किया गया" की पृष्ठभूमि भी document करें।
- यह भविष्य की teams के लिए अमूल्य संपत्ति बनती है।
- स्थिर team बनाए रखें:
- दीर्घकालिक project investment के लिए long-term hiring पर विचार करें।
- team members को लंबे समय तक project के प्रति समर्पित रहने में सहायता करें।
- open source पर विचार करें:
- जहाँ संभव हो, open source के माध्यम से उच्च code standards बनाए रखें।
- logs और performance telemetry:
- समस्याओं को जल्दी पहचानने और हल करने में महत्वपूर्ण भूमिका निभाते हैं।
- ये सिफ़ारिशें नई नहीं हो सकतीं, लेकिन अनुभवी developers इन्हें बार-बार रेखांकित करते हैं, इसलिए इन पर गंभीरता से विचार करना सार्थक है।
4 टिप्पणियां
स्थिरता महत्वपूर्ण होने वाली layer और गति महत्वपूर्ण होने वाली layer को अलग करना, और दोनों के बीच के संबंध को कैसे संभालना है—यही सबसे महत्वपूर्ण engineering क्षमता है।
अगर Toss ने सिर्फ स्थिरता का ही पीछा किया होता, तो वह बाकी बैंकों से अलग नहीं होता।
जोखिम वाली बात SpaceX में भी है। Tesla भी वैसी ही है..
क्या रिज़्यूमे-चालित development ही समस्या है।
Hacker News राय
toolchain को सक्रिय रूप से अपडेट करना development process का एक महत्वपूर्ण हिस्सा है। कई कंपनियां toolchain upgrade को priority से बाहर रखती हैं, जिससे security vulnerability जैसी समस्याएं पैदा होती हैं। हर नए compiler या build system release पर branch बनाकर build status जांचा जाता है, और अगर error हो तो उसे bug मानकर तुरंत ठीक किया जाता है। इससे codebase को नए language features के साथ धीरे-धीरे modernize और refactor करने में मदद मिलती है.
third-party dependencies लंबे समय में अक्सर निराशाजनक साबित होती हैं। नए project में short term में समस्या हल करने के लिए third-party dependency उपयोगी हो सकती है, लेकिन long term में उसे अपने code से replace करना बेहतर है.
dependency को vendoring करके और code review के जरिए manage करना ज़रूरी है। कई बार third-party code की quality कम होती है, इसलिए उसे खुद लिखना बेहतर होता है.
Qt, CMake, और modern C++ का उपयोग करके long-term scalability को लक्ष्य बनाने वाला एक project चल रहा है। यह tech stack लगातार features और improvements देता रहता है.
Emacs Lisp में काम करना एक ताज़ा अनुभव था। इसकी एक बड़ी खासियत यह है कि library update न होने पर भी यह स्थिर रूप से काम करता है। Gatsby और Node के साथ अनुभव update समस्याओं की वजह से कठिन रहा.
simple code लिखना महत्वपूर्ण है। complex code केवल तब लिखना चाहिए जब उसकी सच में ज़रूरत हो, जबकि simple code पर शायद ही कभी पछतावा होता है.
system और code का documentation महत्वपूर्ण है। software development का अनुभव बढ़ने के साथ documentation की अहमियत और स्पष्ट होती जाती है.
testing planning में महत्वपूर्ण भूमिका निभाती है। NASA की development approach से सीखते हुए programming errors ढूंढने पर ज़ोर देना चाहिए। medical software development में ambiguity से बचा जाता है और dynamic memory allocation का उपयोग नहीं किया जाता.
लंबे समय तक चलने वाला software लिखने का सबसे अच्छा तरीका है "boring" code लिखना। dependencies से बचना चाहिए और fundamentals पर टिके रहना चाहिए.
Python में dependency समस्याओं से जूझने का अनुभव रहा है। इसे "DLL Hell" कहा जाता है, और COM ने इसे हल करने की कोशिश की थी, लेकिन वह सफल नहीं हुआ.
industrial software में अपनाई जाने वाली practices सामान्य software पर लागू करने के लिए पर्याप्त रूप से robust नहीं होतीं। engineers जोखिम को कम करने की कोशिश करते हैं, लेकिन हम risk mitigation पर ही ज़ोर देते हैं.