2.14

अंग्रेज़ी में देखें

2.14 प्रोजेक्ट और रिपॉज़िटरी संरचना

अवलोकन और प्रेरणा

प्रोजेक्ट और रिपॉज़िटरी संरचना किसी कोडबेस का भौतिक संगठन है: वे फ़ोल्डर, फ़ाइलें, और नामकरण परंपराएँ जो तय करती हैं कि कोई भी दी गई चीज़ कहाँ रहती है। एक रिपॉज़िटरी (अक्सर संक्षेप में “रेपो”) वह वर्ज़न-नियंत्रित कंटेनर है जो किसी प्रोजेक्ट की फ़ाइलों और उनके इतिहास को रखता है। एक प्रोजेक्ट, जिसे कभी-कभी सॉल्यूशन कहा जाता है जब यह कई संबंधित कंपोनेंट को समूहित करता है, वह सॉफ़्टवेयर की तार्किक इकाई है जिसे आप बना रहे हैं। संरचना वह मानचित्र है जिसका इस्तेमाल आप उस सॉफ़्टवेयर को खोजने, समझने, और बदलने के लिए करते हैं।

एक छोटी टीम में, एक व्यक्ति पूरे ले-आउट को अपने दिमाग़ में रख सकता है। एक बड़ी टीम में, सैकड़ों या हज़ारों इंजीनियरों के साथ, टीमों के बीच बार-बार आवाजाही, और आने-जाने वाले ठेकेदारों के साथ, हर वह रिपॉज़िटरी जो अलग ढंग से व्यवस्थित है, एक ताज़ा संज्ञानात्मक कर वसूलती है। जब आप एक अपरिचित रेपो खोलते हैं, तो आपको बिना कोई मैनुअल पढ़े यह अंदाज़ा लगाने में सक्षम होना चाहिए कि सोर्स, टेस्ट, दस्तावेज़ीकरण, और परिनियोजन कॉन्फ़िगरेशन कहाँ रहते हैं। जब हर रेपो इन सवालों का एक ही तरह से जवाब देता है, तो गतिशीलता सस्ती होती है और ऑनबोर्डिंग तेज़ होती है। जब हर रेपो एक स्नोफ़्लेक होता है, तो हर संदर्भ-स्विच एक छोटी शोध परियोजना बन जाता है।

उद्यम और सरकारी परिवेश में, संगत संरचना एक नियंत्रण और आश्वासन चिंता भी है। ऑडिटर, सुरक्षा समीक्षक, और दीर्घकालिक अनुरक्षक, जो अक्सर मूल लेखकों के जाने के वर्षों बाद काम कर रहे होते हैं, उन्हें विनिर्देश दस्तावेज़, लाइसेंस फ़ाइलें, सुरक्षा नीतियाँ, और बिल्ड परिभाषाएँ विश्वसनीय ढंग से खोजने की ज़रूरत होती है। एक पूर्वानुमेय ले-आउट स्वचालित टूलिंग (स्कैनर, डिपेंडेंसी विश्लेषक, अनुपालन जाँच) को भी सिस्टम के पूरे पोर्टफ़ोलियो में एक ही तरह से काम करने देता है। इसलिए यह अध्याय संरचना को एक ऐसी परंपरा के रूप में मानता है जिसे आप एक बार तय करते हैं और हर जगह लागू करते हैं। यह कोडिंग मानक और शैली (अध्याय 2.1), वर्ज़न कंट्रोल और सोर्स प्रबंधन (अध्याय 2.6), और दस्तावेज़ीकरण (अध्याय 2.7) से निकटता से जुड़ा है।

मुख्य सिद्धांत

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

सिफ़ारिशें

एक संगत शीर्ष-स्तरीय ले-आउट अपनाएँ

शीर्ष-स्तरीय फ़ोल्डरों का एक मानक सेट परिभाषित करें जिसे हर रिपॉज़िटरी जहाँ लागू हो वहाँ इस्तेमाल करे, और दस्तावेज़ करें कि हर एक किसलिए है। एक सामान्य, विक्रेता-निरपेक्ष परंपरा में शामिल हैं: प्रोडक्शन कोड के लिए एक सोर्स फ़ोल्डर (अक्सर src); स्वचालित टेस्ट के लिए एक टेस्ट फ़ोल्डर (अक्सर test या tests); दस्तावेज़ीकरण के लिए एक docs फ़ोल्डर; बिल्ड परिभाषाओं और आउटपुट के लिए एक build फ़ोल्डर; परिनियोजन और इन्फ्रास्ट्रक्चर ऐज़ कोड (सर्वर, नेटवर्क, और सेवाओं की मशीन-पठनीय परिभाषाएँ, जिन्हें अध्याय 8.2 में कवर किया गया है) के लिए एक deploy फ़ोल्डर; स्वचालन और डेवलपर टूलिंग के लिए एक scripts फ़ोल्डर; चलाने-योग्य उदाहरणों के लिए एक examples फ़ोल्डर; और आवश्यकताओं व डिज़ाइन विनिर्देशों के लिए एक spec या specification फ़ोल्डर। हर रेपो को हर फ़ोल्डर की ज़रूरत नहीं है, लेकिन जहाँ कोई चिंता मौजूद है, वहाँ उसे अपेक्षित जगह पर अपेक्षित नाम के साथ होना चाहिए।

README को प्रवेश बिंदु बनाएँ

रिपॉज़िटरी रूट पर एक README फ़ाइल को एकल, कैनोनिकल शुरुआती बिंदु के रूप में अनिवार्य बनाएँ। इसे बताना चाहिए कि प्रोजेक्ट क्या है, इसे कैसे बनाएँ और चलाएँ, टेस्ट कैसे चलाएँ, गहरा दस्तावेज़ीकरण कहाँ मिलेगा, इसका मालिक कौन है, और इसमें योगदान कैसे करें। README पूरा दस्तावेज़ीकरण सेट नहीं है; यह वह सूचकांक है जो बाकी की ओर इशारा करता है (अध्याय 2.7)। एक गायब या पुराना README को एक दोष मानें, क्योंकि यह पहली चीज़ है जिसे हर नया इंजीनियर, ऑडिटर, या इंटीग्रेटर पढ़ेगा।

संपादक और कॉन्फ़िगरेशन फ़ाइलों को मानकीकृत करें

साझा संपादक और टूलिंग कॉन्फ़िगरेशन को रिपॉज़िटरी में चेक करें ताकि हर योगदानकर्ता को स्वचालित रूप से संगत व्यवहार मिले। एक .editorconfig फ़ाइल (एक सरल, संपादक-निरपेक्ष फ़ाइल जो व्हाइटस्पेस, इंडेंटेशन, और लाइन-एंडिंग नियम परिभाषित करती है) विभिन्न संपादकों और ऑपरेटिंग सिस्टम में बुनियादी फ़ॉर्मेटिंग को समान रखती है। वर्ज़न-कंट्रोल सिस्टम के लिए एक इग्नोर फ़ाइल जोड़ें (ताकि बिल्ड आउटपुट और स्थानीय आर्टिफ़ैक्ट कभी कमिट न हों), साथ ही अध्याय 2.1 में वर्णित साझा फ़ॉर्मेटर और लिंटर कॉन्फ़िगरेशन। ये फ़ाइलें रिपॉज़िटरी की परंपराओं को सक्रिय बनाती हैं, केवल दस्तावेज़ीकृत नहीं।

नामकरण और फ़ोल्डर परंपराएँ परिभाषित करें

फ़ोल्डर और फ़ाइलों के नामकरण के लिए परंपराओं पर सहमत हों (केसिंग, विभाजक, एकवचन बनाम बहुवचन, और टेस्ट को चिह्नित करने वाले आवश्यक प्रत्यय जैसे), और उन्हें समान रूप से लागू करें। नामों को इरादा प्रकट करना चाहिए और संगठन में अन्यत्र इस्तेमाल की गई डोमेन शब्दावली से मेल खाना चाहिए। लक्ष्य सरल है: एक पथ को अर्थ संप्रेषित करना चाहिए, ताकि किसी फ़ोल्डर या फ़ाइल के नाम को पढ़ना आपको बिना उसे खोले बताए कि अंदर क्या है।

परतों और डिपेंडेंसी को जानबूझकर व्यवस्थित करें

कोडबेस को इस तरह संरचित करें कि इसकी आर्किटेक्चरल परतें फ़ोल्डर ले-आउट में दिखें, और डिपेंडेंसी एक ही, समझदार दिशा में बहें। उच्च-स्तरीय नीति को निम्न-स्तरीय विवरण पर निर्भर नहीं होना चाहिए। साझा, स्थिर कोड को वहाँ रहना चाहिए जहाँ कई मॉड्यूल चक्र बनाए बिना उस तक पहुँच सकें। जब आप स्तरीकरण को भौतिक बनाते हैं, जो डायरेक्टरी ट्री में प्रतिबिंबित होता है, तो इंजीनियरों के इसका सम्मान करने की संभावना ज़्यादा होती है, और समीक्षा और स्वचालित डिपेंडेंसी जाँच दोनों में उल्लंघनों को पहचानना आसान होता है।

स्कैफ़ोल्डिंग और टेम्पलेट से संरचना लागू करें

स्कैफ़ोल्डिंग प्रदान करें, एक स्टार्टर प्रोजेक्ट का स्वचालित निर्माण, ताकि नई रिपॉज़िटरी पहले से ही सही शुरू हों। एक टेम्पलेट या कुकीकटर (एक पैरामीटराइज़्ड प्रोजेक्ट स्केलेटन जो कुछ प्रॉम्प्ट के जवाबों से एक तैयार रिपॉज़िटरी बनाता है) मानक ले-आउट, README, कॉन्फ़िग फ़ाइलों, और CI सेटअप को एक ही जगह में एनकोड करता है। जब इंजीनियर एक साझा टेम्पलेट से नई सेवाएँ बनाते हैं, तो संगति एक आकांक्षा के बजाय डिफ़ॉल्ट बन जाती है, और टेम्पलेट में सुधार भविष्य की परियोजनाओं तक पहुँचते हैं।

बड़े पैमाने पर कई रिपॉज़िटरी में संरचना को संगत रखें

ले-आउट को खुद एक गवर्न किए गए मानक के रूप में मानें: किसी भी अन्य इंजीनियरिंग मानक (अध्याय 1.7) की तरह केंद्रीय रूप से बनाए रखा गया, और कोड (अध्याय 2.6) की तरह वर्ज़न किया गया। इसे प्रकाशित करें, इसे लागू करने वाले टेम्पलेट प्रदान करें, और विचलन को केवल एक दस्तावेज़ीकृत अपवाद प्रक्रिया के ज़रिए अनुमति दें, ताकि “मानक” अपना अर्थ बनाए रखे। पोर्टफ़ोलियो पैमाने पर, संरचना का लगभग सारा मूल्य रिपॉज़िटरी में इसकी एकरूपता से आता है, इसलिए बहाव (drift) प्रबंधित करने वाला मुख्य जोखिम है।

संरचना को मोनोरेपो बनाम मल्टी-रेपो विकल्प को सूचित करने दें

संरचना को अध्याय 2.6 में कवर किए गए रिपॉज़िटरी-सीमा निर्णय से जोड़ें। एक मोनोरेपो (एक रिपॉज़िटरी जो कई प्रोजेक्ट रखती है) को प्रोजेक्ट और उनके साझा कोड को अलग करने के लिए एक स्पष्ट आंतरिक परंपरा की ज़रूरत होती है, ताकि एकल ट्री नेविगेट करने योग्य बना रहे। एक मल्टी-रेपो दृष्टिकोण (कई छोटी रिपॉज़िटरी, प्रति प्रोजेक्ट या सेवा एक) को मज़बूत क्रॉस-रेपो संगति की ज़रूरत होती है, ताकि हर रेपो अकेला खड़ा होने पर भी परिचित लगे। किसी भी तरह, एक दस्तावेज़ीकृत, टेम्पलेटेड संरचना ही है जो नेविगेशन को पूर्वानुमेय बनाए रखती है। सीमा का चुनाव यह बदलता है कि आप परंपरा को कहाँ लागू करते हैं, इसे नहीं कि आपको इसकी ज़रूरत है या नहीं।

ट्रेड-ऑफ़: फ़ायदे और नुकसान

विकल्पफ़ायदेनुकसान
सख्त संगठन-व्यापी मानक ले-आउटतुरंत परिचितता; पोर्टेबल इंजीनियर; समान टूलिंगअसामान्य परियोजनाओं के लिए कभी-कभी खराब फ़िट; गवर्नेंस की ज़रूरत
प्रति-टीम ले-आउट स्वतंत्रतास्थानीय अनुकूलन; उच्च स्वायत्तताविखंडन; महंगा संदर्भ-स्विचिंग; असंगत टूलिंग
स्कैफ़ोल्डिंग और टेम्पलेटडिफ़ॉल्ट रूप से सही रेपो; बदलाव प्रचारित होते हैंटेम्पलेट रखरखाव; जनरेट किए गए रेपो में बहाव का जोखिम
गहरा, स्तरीकृत फ़ोल्डर पदानुक्रमस्पष्ट संरचना; स्पष्ट सीमाएँनेविगेशन का बोझ; लंबे पथ; अति-इंजीनियरिंग का जोखिम
सपाट, उथला ले-आउटस्कैन करना आसान; कम औपचारिकताखराब अलगाव; प्रोजेक्ट के बढ़ने पर टूट जाता है

प्रमुख ट्रेड-ऑफ़ एकरूपता बनाम स्वायत्तता है। एक एकल मानक ले-आउट उन कई इंजीनियरों के लिए घर्षण हटाता है जो कोडबेस के बीच घूमते हैं, इसकी कीमत उस कभी-कभार वाली परियोजना को चुकानी पड़ती है जिसकी ज़रूरतें साँचे में ठीक से फिट नहीं बैठतीं। एक बड़े संगठन में, परिचितता से होने वाला सामूहिक लाभ लगभग हमेशा उस स्थानीय हानि से ज़्यादा होता है। यही कारण है कि अनुशंसित रुख एक मज़बूत डिफ़ॉल्ट मानक और एक दस्तावेज़ीकृत अपवाद पथ (अध्याय 1.7) है, न कि कठोर एकरूपता या अप्रबंधित स्वतंत्रता। एक द्वितीयक ट्रेड-ऑफ़ गहराई बनाम सरलता है: वास्तविक चिंताओं को अलग करने के लिए पर्याप्त संरचना, लेकिन इतनी नहीं कि नेविगेशन खाली फ़ोल्डरों की एक पैदल यात्रा बन जाए।

अपनी टीम के साथ चर्चा करने के लिए प्रश्न

  1. जब कोई इंजीनियर हमारे किसी अपरिचित रेपो में जाता है, तो टेस्ट, डिप्लॉय कॉन्फ़िग, और मालिक को खोजने में उसे कितना समय लगता है? यही वह नेविगेशन कर है जिसे खत्म करने के लिए संरचना मौजूद है, और पोर्टफ़ोलियो पैमाने पर इसे हर साल हज़ारों बार छोटी-छोटी बढ़ोतरी में चुकाया जाता है जो जुड़कर गंभीर खोए हुए इंजीनियरिंग समय में बदल जाती हैं। न्यूनतम आश्चर्य के सिद्धांत का मुद्दा यह है कि एक अनुभवी इंजीनियर को बिना मैनुअल पढ़े यह अंदाज़ा लगाने में सक्षम होना चाहिए कि सोर्स, टेस्ट, डॉक्स, और परिनियोजन कहाँ रहते हैं, इसलिए ईमानदार परीक्षा यह है कि क्या वह अंदाज़ा आपके रेपो में सफल होता है। बैठक में एक वास्तविक संख्या लाएँ: खुद को दो या तीन अपरिचित आंतरिक रिपॉज़िटरी में उन्मुख होते हुए समय दें, या यह ऑनबोर्डिंग डेटा निकालें कि नए शामिल होने वालों को पहला बदलाव करने में कितना समय लगता है। अगर जवाब पहचान के मिनटों के बजाय शोध के दिनों में मापा जाता है, तो आपने स्नोफ़्लेक रेपो की लागत को मात्रात्मक बना दिया है, और यह उस मानक ले-आउट में एक-बार के निवेश को उचित ठहराता है जिसे हर रेपो साझा करता है।

  2. क्या हमारी आर्किटेक्चरल परतें फ़ोल्डर ट्री में दिखती हैं, या डिपेंडेंसी चक्र एक सपाट ले-आउट के अंदर छुपते हैं? संरचना खोजने-योग्यता से कहीं ज़्यादा के बारे में है: जब आप स्तरीकरण को भौतिक बनाते हैं, तो इंजीनियर इसका सम्मान करते हैं और समीक्षक व स्वचालित डिपेंडेंसी जाँच उल्लंघनों को पहचान सकते हैं, जबकि एक सपाट ढेर अनुचित कपलिंग और चक्रों को तब तक अनदेखा रेंगने देता है जब तक बदलाव खतरनाक न हो जाए। एक बड़े, दीर्घकालिक सिस्टम में यही वह चीज़ है जो उच्च-स्तरीय नीति को चुपचाप निम्न-स्तरीय विवरण पर निर्भर होने से रोकती है, और यह ठीक उस तरह का क्षरण है जिसे रोकना सस्ता और सुलझाना महंगा है। अपना डिपेंडेंसी ग्राफ लाएँ या एक त्वरित जाँच चलाएँ: क्या चक्र हैं, और क्या कोई स्थिर चीज़ किसी अस्थिर चीज़ पर निर्भर है? जवाब को आपको परतों को डायरेक्टरी में प्रतिबिंबित करने और स्वचालित डिपेंडेंसी-दिशा जाँच जोड़ने की ओर धकेलना चाहिए, ताकि सीमाएँ ट्री में दृश्यमान हों और पाइपलाइन में लागू हों, न कि केवल किसी के मानसिक मॉडल में रहें।

  3. क्या हमारी नई रिपॉज़िटरी एक टेम्पलेट से सही शुरू होती हैं, या हम एक विकी पेज और अच्छे इरादों पर निर्भर हैं? स्कैफ़ोल्डिंग द्वारा लागू की गई संरचना डिफ़ॉल्ट है; एक दस्तावेज़ में वर्णित संरचना बहती है, क्योंकि वास्तविकता उसी का अनुसरण करती है जो रेपो जनरेट करता है, न कि उसका जो एक पेज कहता है कि वे कैसे दिखने चाहिए। एक बड़े या विनियमित संगठन के लिए यह एक आश्वासन चिंता भी है: जब हर रेपो एक साझा टेम्पलेट से जनरेट होता है, तो सुरक्षा स्कैनर, डिपेंडेंसी विश्लेषक, और ऑडिटर हर बार, विक्रेताओं और वर्षों के आर-पार, लाइसेंस, सुरक्षा नीति, विनिर्देश, और बिल्ड परिभाषा को एक ही जगह पाते हैं। प्रमाण लाएँ: आपके कितने हाल के रेपो मानक टेम्पलेट से स्कैफ़ोल्ड किए गए थे बनाम हाथ से जोड़े गए, और टेम्पलेटेड वाले तब से कितना बहक गए हैं? कार्रवाई यह है कि टेम्पलेट को रेपो शुरू करने का एकमात्र आसान तरीका बनाएँ, इसे एक दस्तावेज़ीकृत अपवाद पथ के साथ एक वर्ज़न किए गए मानक के रूप में गवर्न करें, और बहाव को स्वचालित रूप से पहचानें, क्योंकि एकरूपता ही वह जगह है जहाँ संरचना का लगभग सारा मूल्य रहता है।

  4. क्या हमने तय किया है कि हमारा मानक एक मोनोरेपो या कई अलग रिपॉज़िटरी तक फैला है, और क्या वही परंपरा वास्तव में उस सीमा के दोनों तरफ लागू होती है? रिपॉज़िटरी-सीमा का चुनाव यह बदलता है कि आप परंपरा को कहाँ लागू करते हैं, इसे नहीं कि आपको इसकी ज़रूरत है या नहीं, और इसे गलत करने का मतलब है एक विशाल ट्री जिसे कोई नेविगेट नहीं कर सकता या रेपो का एक ऐसा फैलाव जिनमें से हर एक अपरिचित लगता है। एक मोनोरेपो को प्रोजेक्ट और उनके साझा कोड को अलग करने के लिए एक स्पष्ट आंतरिक परंपरा की ज़रूरत होती है ताकि एक ट्री नेविगेट करने योग्य बना रहे, जबकि एक मल्टी-रेपो दृष्टिकोण को मज़बूत क्रॉस-रेपो संगति की ज़रूरत होती है ताकि हर स्टैंडअलोन रेपो फिर भी परिचित लगे। वर्तमान सूची लाएँ: आपके पास कितने रेपो हैं, किसी मोनोरेपो के अंदर साझा कोड कैसे अलग किया जाता है, और यह समयबद्ध परीक्षण कि क्या कोई इंजीनियर बड़े ट्री के अंदर उतनी ही तेज़ी से एक प्रोजेक्ट ढूँढ सकता है जितनी तेज़ी से वह एक स्टैंडअलोन रेपो में ढूँढता है। एक बड़े उद्यम या एक सरकारी कार्यक्रम के लिए जहाँ अलग-अलग विक्रेता अलग रिपॉज़िटरी देते हैं, जानबूझकर तय करें कि परंपरा के कौन-से हिस्से सार्वभौमिक हैं और कौन-से सीमा-विशिष्ट, क्योंकि ऑडिटर और प्लेटफ़ॉर्म टूलिंग को एक ही तरह काम करना होता है चाहे कोड एक ट्री के रूप में आए या पचास के रूप में।

  5. हमारे संरचना मानक का मालिक कौन है, और जब कोई परियोजना वास्तव में इसमें फिट नहीं बैठती तो वास्तव में क्या होता है? पोर्टफ़ोलियो पैमाने पर संरचना का लगभग सारा मूल्य एकरूपता से आता है, इसलिए असली जोखिम एक ऐसा बिना-मालिक वाला मानक है जो सड़ जाता है और एक इतना अस्पष्ट अपवाद पथ है कि हर टीम चुपचाप अपना खुद का ले-आउट बना लेती है। तनाव कठोर एकरूपता के बीच है जो किसी भी असामान्य परियोजना में फिट नहीं बैठती और अप्रबंधित स्वतंत्रता के बीच है जो सब कुछ खंडित कर देती है, और स्वस्थ जवाब एक मज़बूत डिफ़ॉल्ट के साथ एक दस्तावेज़ीकृत, ऑडिट-योग्य अपवाद प्रक्रिया है जो एक नामित मालिक द्वारा गवर्न की जाती है और कोड की तरह वर्ज़न की जाती है। प्रमाण लाएँ: क्या एक ही जवाबदेह मालिक है, एक चेंजलॉग के साथ एक वर्ज़न किया गया मानक दस्तावेज़, दी गई और क्यों दी गई अपवादों का लॉग, और जंगल में मिलने वाले अदस्तावेज़ीकृत विचलनों की एक गिनती। उद्यम और सरकारी परिवेश में, एक अपवाद जिसे किसी ने दर्ज नहीं किया वह एक नियंत्रण अंतर है, इसलिए हर विचलन को एक लिखित औचित्य और एक समीक्षा तारीख से जोड़ें, और सुनिश्चित करें कि ले-आउट को अनिवार्य करने वाले खरीद अनुबंध यह भी नाम बताएँ कि इससे विचलन को कौन मंज़ूर कर सकता है।

  6. क्या हमारा README और चेक-इन किए गए कॉन्फ़िगरेशन फ़ाइलें हमारी परंपराओं को सक्रिय बनाती हैं, या वे सजावटी हैं? एक README सामने का दरवाज़ा है, और चेक-इन किए गए .editorconfig, इग्नोर फ़ाइल, और लिंटर कॉन्फ़िगरेशन वे हैं जो परंपराओं को स्व-प्रवर्तक बनाते हैं, फिर भी ये पहली चीज़ें हैं जो पुरानी होती हैं और आखिरी चीज़ें हैं जिन्हें कोई नोटिस करता है जब तक कोई ऑडिटर या नया शामिल हुआ व्यक्ति प्रोजेक्ट को बिल्ड न कर पाए। तनाव एक दुबले README के बीच है जो अद्यतन बना रहता है और एक व्यापक README के बीच है जो बहक जाता है, और लोगों पर कोड को सही ढंग से फ़ॉर्मेट करने के लिए भरोसा करने और साझा कॉन्फ़िगरेशन को इसे स्वचालित रूप से लागू करने देने के बीच है। एक नमूना लाएँ: पाँच रेपो निकालें और जाँचें कि कितने README वास्तव में बताते हैं कि प्रोजेक्ट क्या है, इसे कैसे बनाएँ, टेस्ट करें, और चलाएँ, और इसका मालिक कौन है, और कितने व्यक्तिगत आदतों पर निर्भर रहने के बजाय साझा कॉन्फ़िगरेशन फ़ाइलें रखते हैं। एक बड़े या विनियमित संगठन के लिए, जहाँ इंटीग्रेटर, सुरक्षा समीक्षक, और दीर्घकालिक अनुरक्षक किसी भी और चीज़ से पहले README पढ़ते हैं, एक गायब या पुराने सामने के दरवाज़े को एक मालिक वाला दोष मानें, और कॉन्फ़िग-फ़ाइल की मौजूदगी को स्वचालित रूप से जाँचें ताकि अनुरूपता सद्भावना पर निर्भर न हो।

क्षेत्र-विशेष दृष्टिकोण

स्टार्टअप। गति जीतती है, इसलिए अपने पहले रेपो के लिए एक सरल, पर्याप्त रूप से सपाट ले-आउट (src, test, docs, scripts, एक भरा हुआ README, एक .editorconfig, और इग्नोर फ़ाइलें) पर सहमत हों और उसी दोपहर इसे एक हल्के टेम्पलेट के रूप में सहेज लें। दूसरी सेवा को इससे जनरेट करें ताकि दोनों रेपो परिचित लगें और एक नया ठेकेदार एक स्नोफ़्लेक को रिवर्स-इंजीनियर करने के बजाय घंटों में ऑनबोर्ड हो जाए। गहरे पदानुक्रमों और भारी गवर्नेंस का विरोध करें जिनकी आपको अभी ज़रूरत नहीं है; यहाँ पूरा प्रतिफल यह है कि दो संस्थापक और एक ठेकेदार एक नक्शा साझा करते हैं।

छोटा व्यवसाय। बिना किसी प्लेटफ़ॉर्म विशेषज्ञ और एक सीमित बजट के, अपनी खुद की एक बनाने के बजाय वह पारंपरिक ले-आउट अपनाएँ जिसे आपकी भाषा या फ़्रेमवर्क पहले से मानती है, ताकि रेडीमेड टूलिंग और कोई भी नया कर्मचारी इस पर पूर्व-प्रशिक्षित होकर आए। अपना खुद बनाने के बजाय स्कैफ़ोल्डिंग (एक फ़्रेमवर्क जनरेटर या एक कुकीकटर टेम्पलेट) खरीदें, और अपना सीमित प्रयास एक भरे हुए README को अद्यतन रखने में खर्च करें। वह README उस दिन के लिए सबसे सस्ता बीमा है जब वह एकमात्र व्यक्ति जो ले-आउट जानता था, आगे बढ़ जाता है।

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

सरकार। खरीद, पारदर्शिता, और दीर्घकालिक जवाबदेही ले-आउट को आकार देते हैं, इसलिए हर विक्रेता को बाँधने वाले डिलीवरी मानकों में एक सामान्य संरचना अनिवार्य करें। कोड को अनुमोदित आवश्यकताओं से जोड़ने वाले एक specification फ़ोल्डर, रूट पर एक लाइसेंस और सुरक्षा-नीति फ़ाइल, और इन्फ्रास्ट्रक्चर-ऐज़-कोड परिभाषाएँ रखने वाले एक deploy फ़ोल्डर की माँग करें, ताकि ऑडिटर हर सिस्टम में अनुपालन कलाकृतियों को एक ही तरह खोज सकें। क्योंकि अलग-अलग विक्रेताओं के ठेकेदार सभी एक नक्शे का पालन करते हैं, एक अनुबंध समाप्त होने के बाद रखरखाव की लागत बहुत कम होती है, और जनता को आवश्यकता से चलते कोड तक एक बचाव-योग्य, निरीक्षण-योग्य निशान मिलता है।

उदाहरण

स्टार्टअप। तीन-व्यक्ति की एक स्टार्टअप अपने पहले रेपो के लिए एक सरल मानक ले-आउट (src, test, docs, scripts, एक भरा हुआ README, एक .editorconfig, और इग्नोर फ़ाइलें) पर सहमत होती है और इसे एक हल्के टेम्पलेट के रूप में सहेज लेती है। जब वे एक महीने बाद अपनी दूसरी सेवा शुरू करते हैं, तो वे इसे उस टेम्पलेट से जनरेट करते हैं, इसलिए दोनों रेपो पहले से ही परिचित लगते हैं और नया ठेकेदार एक दोपहर में ऑनबोर्ड हो जाता है। वे उन गहरे फ़ोल्डर पदानुक्रमों का विरोध करते हैं जिनकी उन्हें अभी ज़रूरत नहीं है, ट्री को एक नज़र में स्कैन करने लायक पर्याप्त सपाट रखते हुए। लागत सेटअप की एक दोपहर थी, और यह उन्हें उस स्नोफ़्लेक फैलाव से बचाती है जो अन्यथा हर भावी रेपो को एक छोटी शोध परियोजना बना देती।

उद्यम। एक बहुराष्ट्रीय खुदरा विक्रेता कई भाषाओं में सैकड़ों सेवाएँ चलाता है। इसकी प्लेटफ़ॉर्म टीम एक वर्ज़न किया गया रिपॉज़िटरी-संरचना मानक और इसे लागू करने वाले प्रोजेक्ट टेम्पलेट का एक सेट प्रकाशित करती है। हर नई सेवा एक टेम्पलेट से जनरेट होती है, इसलिए यह मानक src, test, docs, deploy, और scripts फ़ोल्डरों, एक भरे हुए README, एक .editorconfig, इग्नोर फ़ाइलों, और एक काम करने वाली CI पाइपलाइन के साथ आती है। क्योंकि हर रिपॉज़िटरी एक जैसी दिखती है, एक टीम को फिर से सौंपा गया इंजीनियर घंटों के भीतर उत्पादक हो जाता है, और संगठन-व्यापी सुरक्षा व डिपेंडेंसी स्कैनर समान रूप से चलते हैं क्योंकि वे हमेशा फ़ाइलों को वहीं पाते हैं जहाँ वे उम्मीद करते हैं।

सरकार। विरासत सिस्टम को आधुनिक बना रही एक राष्ट्रीय एजेंसी अपने सभी विक्रेताओं के लिए डिलीवरी मानकों के हिस्से के रूप में एक सामान्य रिपॉज़िटरी ले-आउट अनिवार्य करती है। हर रिपॉज़िटरी में कोड को अनुमोदित आवश्यकताओं से जोड़ने वाला एक specification फ़ोल्डर, एक दस्तावेज़ीकृत README, रूट पर एक लाइसेंस और सुरक्षा-नीति फ़ाइल, और इन्फ्रास्ट्रक्चर-ऐज़-कोड परिभाषाएँ (अध्याय 8.2) रखने वाला एक deploy फ़ोल्डर होना चाहिए। क्योंकि अलग-अलग विक्रेताओं के ठेकेदार सभी एक ही संरचना का पालन करते हैं, एजेंसी के ऑडिटर हर सिस्टम में अनुपालन कलाकृतियों को एक ही तरह खोज सकते हैं, और अनुबंध समाप्त होने के बाद दीर्घकालिक रखरखाव की लागत बहुत कम होती है क्योंकि आने वाले अनुरक्षक पहले से ही नक्शा जानते हैं।

व्यवसाय मामला: प्रेरणाएँ, ROI, और TCO

एक संरचना मानक अपनाने की लागत ज़्यादातर एक-बार की है: ले-आउट पर सहमत होना, टेम्पलेट बनाना, और परंपरा को दस्तावेज़ीकृत करना। आवर्ती लागत कम है, जो टेम्पलेट बनाए रखने और अपवादों को गवर्न करने में केंद्रित है। एक मानक न होने की लागत आवर्ती और चक्रवृद्धि होती है: हर इंजीनियर जो एक अपरिचित रेपो खोलता है वह एक नेविगेशन कर चुकाता है, हर ऑनबोर्डिंग धीमी चलती है, और स्वचालित टूलिंग को प्रति-रेपो कॉन्फ़िगर करना पड़ता है क्योंकि कुछ भी वहाँ नहीं है जहाँ आप उम्मीद करते हैं। एक बड़े संगठन में, ये छोटे घर्षण गुणा होकर इंजीनियरिंग समय की गंभीर हानि में बदल जाते हैं।

प्रतिफल तेज़ ऑनबोर्डिंग, टीमों के बीच सस्ती गतिशीलता, पोर्टफ़ोलियो-व्यापी टूलिंग से उच्च संकेत, और विनियमित परिवेश में, कम ऑडिट और दीर्घकालिक-रखरखाव लागत के रूप में दिखता है, क्योंकि कलाकृतियाँ हमेशा खोजने योग्य होती हैं। कुल स्वामित्व लागत (TCO, यानी किसी सिस्टम को बनाने, चलाने, और बनाए रखने की पूरी जीवनकाल लागत) दीर्घकालिक सिस्टम में सबसे ज़्यादा घटती है, जहाँ पूर्वानुमेय संरचना से लाभ पाने वाले अनुरक्षक आमतौर पर वे लेखक नहीं होते जिन्होंने इसे बनाया था। नेतृत्व के सामने मामला रखने के लिए, संरचना को एक कम-लागत, उच्च-लाभ वाले मानक के रूप में फ़्रेम करें जो डेवलपर उत्पादकता और ऑडिट तैयारी में सुधार करता है, और ऑनबोर्डिंग-समय डेटा तथा अपरिचित रिपॉज़िटरी में चीज़ें ढूँढने में खर्च हुए प्रयास का इस्तेमाल करके आज की असंगति की लागत पर एक संख्या डालें।

एंटी-पैटर्न और नुकसान

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

परिपक्वता मॉडल

  • स्तर 1 (आरंभ): हर रिपॉज़िटरी को उसके लेखकों द्वारा तदर्थ रूप से व्यवस्थित किया जाता है, जो भी क्षण को चाहिए उस पर प्रतिक्रिया करते हुए; ले-आउट व्यापक रूप से भिन्न होते हैं; README गायब या अविश्वसनीय हैं; नए लोगों को हर रेपो में हाथ से घुमाया जाना चाहिए।
  • स्तर 2 (विकास): बुनियादी परंपराएँ अनौपचारिक रूप से मौजूद हैं और कई रेपो एक-दूसरे से मिलते-जुलते हैं; कुछ टीमें अपना खुद का स्टार्टर ले-आउट रखती हैं; लेकिन कोई आधिकारिक मानक नहीं है, कोई साझा स्कैफ़ोल्डिंग नहीं है, और संरचना एक टीम से दूसरी टीम में स्पष्ट रूप से बहती है।
  • स्तर 3 (मानकीकरण): एक दस्तावेज़ीकृत, वर्ज़न किया गया संरचना मानक पूरे संगठन में लागू किया गया है; नई रिपॉज़िटरी एक मानक ले-आउट, README, कॉन्फ़िगरेशन फ़ाइलें, और CI रखने वाले साझा टेम्पलेट से जनरेट होती हैं; विचलन चुपचाप होने के बजाय एक दस्तावेज़ीकृत अपवाद प्रक्रिया से गुज़रते हैं।
  • स्तर 4 (प्रबंधन): मानक के प्रति अनुरूपता को डेटा से मापा और नियंत्रित किया जाता है: स्वचालित जाँच रिपोर्ट करती हैं कि रेपो का कितना हिस्सा ले-आउट से मेल खाता है, टेम्पलेटेड रेपो कितना बह गए हैं, README पूर्णता, और डिपेंडेंसी-दिशा उल्लंघन, सब बेसलाइन के विरुद्ध ट्रैक किए जाते हैं; ऑनबोर्डिंग और नेविगेशन समय मापे जाते हैं; अपवाद लॉग और समीक्षित किए जाते हैं, और टेम्पलेट बदलावों को राय के बजाय प्रमाण पर स्वीकृत किया जाता है।
  • स्तर 5 (समन्वय): संरचना को लगातार सुधारा और अनुकूलित किया जाता है: टेम्पलेट सुधार स्वचालित रूप से मौजूदा रिपॉज़िटरी तक प्रचारित होते हैं, संरचना गवर्नेंस सुरक्षा, अनुपालन, और प्लेटफ़ॉर्म टूलिंग के साथ एकीकृत होता है, और भाषाओं, आर्किटेक्चर, और पोर्टफ़ोलियो के बदलने के साथ मानक जानबूझकर विकसित होता है, संगठन के आसपास बदलते हुए भी एकरूपता को ऊँचा रखते हुए।

चर्चा के लिए विचार

  • आपके संगठन में कौन-से शीर्ष-स्तरीय फ़ोल्डर वास्तव में सार्वभौमिक होने चाहिए, और कौन-से वैकल्पिक होने चाहिए?
  • आप एक टेम्पलेट से जनरेट की गई रिपॉज़िटरी को समय के साथ उससे बहने से कैसे रोकते हैं?
  • एक सहायक, स्तरीकृत पदानुक्रम और अति-इंजीनियर्ड फ़ोल्डर औपचारिकता के बीच रेखा कहाँ है?
  • आपका संरचना मानक मोनोरेपो और मल्टी-रेपो दृष्टिकोण के बीच कितना अलग होना चाहिए, अगर बिल्कुल भी?
  • ऐसी परियोजना के लिए सही अपवाद प्रक्रिया क्या है जिसकी वास्तविक ज़रूरतें मानक ले-आउट में फिट नहीं बैठतीं?
  • आपकी कितनी संरचना को स्वचालित रूप से जाँचा जा सकता है, और अभी भी मानव समीक्षा पर क्या निर्भर करता है?
  • संरचना मानक और उसके टेम्पलेट का मालिक कौन है, और बदलाव कैसे प्रस्तावित और रोलआउट किए जाते हैं?

मुख्य निष्कर्ष

  • हर रिपॉज़िटरी को इस तरह व्यवस्थित करें कि कोई भी इंजीनियर न्यूनतम आश्चर्य के सिद्धांत का पालन करते हुए, उम्मीद के आधार पर किसी भी कोडबेस को नेविगेट कर सके।
  • एक संगत शीर्ष-स्तरीय ले-आउट (सोर्स, टेस्ट, डॉक्स, बिल्ड, डिप्लॉय, स्क्रिप्ट, उदाहरण, विनिर्देश) अपनाएँ और README को प्रवेश बिंदु बनाएँ।
  • संपादक और टूलिंग कॉन्फ़िगरेशन (जैसे .editorconfig) चेक इन करें ताकि परंपराएँ सक्रिय हों, केवल लिखी हुई न हों।
  • नई रिपॉज़िटरी को डिफ़ॉल्ट रूप से सही बनाने के लिए स्कैफ़ोल्डिंग और टेम्पलेट से संरचना लागू करें।
  • पैमाने पर, मूल्य एकरूपता में है: मानक को गवर्न करें, बहाव प्रबंधित करें, और विचलन को केवल दस्तावेज़ीकृत अपवाद से अनुमति दें।

संदर्भ और आगे पढ़ने के लिए

  • Robert C. Martin, Clean Architecture: A Craftsman’s Guide to Software Structure and Design
  • Steve McConnell, Code Complete: A Practical Handbook of Software Construction
  • Andrew Hunt and David Thomas, The Pragmatic Programmer
  • Titus Winters, Tom Manshreck, and Hyrum Wright (eds.), Software Engineering at Google
  • Scott Chacon and Ben Straub, Pro Git
  • EditorConfig project documentation (as a reference standard for editor configuration)