पिछले पेजों में, एक थीम बार-बार दोहराई जाती है: मैनेज करना तो आपका अपना कोड काफ़ी आसान है, लेकिन इसकी डिपेंडेंसी को मैनेज करना और मुश्किल हो जाता है. ये सभी चीज़ें निर्भर करती हैं: कभी-कभी किसी टास्क पर निर्भर हो. जैसे, “मैं रिलीज़ को इस रूप में मार्क करने से पहले दस्तावेज़ को पुश करना चाहता हूं पूरा) दिखता है, और कभी-कभी आर्टफ़ैक्ट पर निर्भरता होती है (जैसे कि “मुझे यह करना है” मेरे पास कोड बनाने के लिए, कंप्यूटर विज़न लाइब्रेरी का सबसे नया वर्शन होना चाहिए"). कभी-कभी, आपकी कोड बेस के दूसरे हिस्से पर इंटरनल डिपेंडेंसी होती हैं और कभी-कभी आपकी कंपनी अन्य टीम के मालिकाना हक वाले कोड या डेटा पर निर्भर करती है (या तो आपके संगठन में या किसी तीसरे पक्ष में). हालांकि, किसी भी मामले में, “मैं की ज़रूरत होती है, यह बात बार-बार आती रहती है और डिपेंडेंसी मैनेज करना, शायद दुनिया भर में बुनियादी काम है.
मॉड्यूल और डिपेंडेंसी चुनना
बेज़ल जैसे आर्टफ़ैक्ट पर आधारित बिल्ड सिस्टम का इस्तेमाल करने वाले प्रोजेक्ट को अलग-अलग कैटगरी में बांटा गया है
के मॉड्यूल के साथ, ये मॉड्यूल BUILD
के ज़रिए एक-दूसरे पर निर्भरता दिखाते हैं
फ़ाइलें. इन मॉड्यूल और डिपेंडेंसी को सही तरीके से व्यवस्थित करने से,
इसकी वजह से बिल्ड सिस्टम की परफ़ॉर्मेंस और काम करने में लगने वाला समय, दोनों का असर पड़ता है
बनाए रखें.
ज़्यादा जानकारी वाले मॉड्यूल और 1:1:1 नियम का इस्तेमाल करना
आर्टफ़ैक्ट पर आधारित बिल्ड को स्ट्रक्चर करते समय, सबसे पहला सवाल यह होता है कि किसी मॉड्यूल में कितनी सुविधाएं शामिल होनी चाहिए. Bazel में, किसी मॉड्यूल को टारगेट के तौर पर दिखाया जाता है. इस टारगेट में, java_library
या go_binary
जैसी ऐसी यूनिट की जानकारी होती है जिसे बिल्ड किया जा सकता है. एक तरफ़, पूरे प्रोजेक्ट को एक ही मॉड्यूल में रखा जा सकता है. इसके लिए, रूट में एक BUILD
फ़ाइल डालें और उस प्रोजेक्ट की सभी सोर्स फ़ाइलों को बार-बार ग्लोब करें. दूसरे पर
एक्सट्रीम, करीब हर सोर्स फ़ाइल को असरदार तरीके से इसके खुद के मॉड्यूल में बनाया जा सकता है
हर फ़ाइल को BUILD
फ़ाइल में शामिल करने के लिए, हर दूसरी फ़ाइल पर निर्भर करता है.
ज़्यादातर प्रोजेक्ट, इन सीमाओं के बीच होते हैं और फ़ैसला लेने के लिए
परफ़ॉर्मेंस और रखरखाव के बीच संतुलन बनाना. पूरे प्रोजेक्ट के लिए एक मॉड्यूल का इस्तेमाल करने का मतलब यह हो सकता है कि आपको बाहरी डिपेंडेंसी जोड़ने के अलावा, BUILD
फ़ाइल में कभी बदलाव करने की ज़रूरत न पड़े. हालांकि, इसका मतलब यह भी है कि बिल्ड सिस्टम को हमेशा पूरे प्रोजेक्ट को एक साथ बनाना होगा. इसका मतलब है कि यह इन सुविधाओं का इस्तेमाल नहीं कर पाएगा
बिल्ड के हिस्सों को साथ-साथ या डिस्ट्रिब्यूट नहीं करेगा. साथ ही, यह पार्ट को कैश मेमोरी में सेव भी नहीं कर पाएगा
पहले ही बन चुका है. हर फ़ाइल में एक मॉड्यूल का विकल्प इसके उलट है: बिल्ड सिस्टम के पास, बिल्ड के चरणों को कैश मेमोरी में सेव करने और शेड्यूल करने में ज़्यादा सुविधाएं होती हैं. हालांकि, जब भी इंजीनियर यह बदलते हैं कि कौनसी फ़ाइलें किसका रेफ़रंस देती हैं, तो उन्हें डिपेंडेंसी की सूचियों को मैनेज करने में ज़्यादा मेहनत करनी पड़ती है.
हालांकि, जानकारी का सटीक ब्यौरा, भाषा के हिसाब से अलग-अलग होता है. आम तौर पर,
है), तो Google किसी एक मॉड्यूल की तुलना में काफ़ी छोटे मॉड्यूल को पसंद करता है
आम तौर पर, टास्क पर आधारित बिल्ड सिस्टम में लिखा जाता है. आम तौर पर, प्रोडक्शन बाइनरी
Google अक्सर हज़ारों टारगेट पर निर्भर करता है. साथ ही, टारगेट के लिए
टीम अपने कोड बेस में सैकड़ों टारगेट अपने पास रख सकती है. इन भाषाओं के लिए
ऐसा Java जिसमें पैकेजिंग का बेहतरीन अनुभव मिलता है, हर डायरेक्ट्री आम तौर पर
इसमें एक पैकेज, टारगेट, और BUILD
फ़ाइल (पैंट, दूसरा बिल्ड सिस्टम) मौजूद है
बेज़ल के आधार पर, इसे 1:1:1 नियम कहते हैं). कमज़ोर पैकेजिंग वाली भाषाएं
कन्वेंशन अक्सर हर BUILD
फ़ाइल में कई टारगेट तय करते हैं.
छोटे बिल्ड टारगेट के फ़ायदे, बड़े पैमाने पर दिखने लगते हैं. ऐसा इसलिए होता है, क्योंकि इससे डिस्ट्रिब्यूट किए गए बिल्ड तेज़ी से बनते हैं और टारगेट को फिर से बनाने की ज़रूरत कम पड़ती है.
टेस्टिंग के बाद, ये फ़ायदे और भी ज़्यादा असरदार हो जाते हैं. ऐसा इसलिए, क्योंकि बेहतर टारगेट का मतलब है कि बिल्ड सिस्टम, टेस्ट के सिर्फ़ उस सीमित सबसेट को चलाने के बारे में ज़्यादा बेहतर तरीके से तय कर सकता है जिस पर किसी भी बदलाव का असर पड़ सकता है. Google, छोटे टारगेट का इस्तेमाल करने के सिस्टम के फ़ायदों में विश्वास करता है. इसलिए, हमने BUILD
फ़ाइलों को अपने-आप मैनेज करने के लिए टूल बनाने में निवेश किया है, ताकि डेवलपर पर बोझ न पड़े. इससे, इस समस्या को कम करने में मदद मिली है.
buildifier
और buildozer
जैसे कुछ टूल इसके साथ उपलब्ध हैं
बेज़ल इन द
buildtools
डायरेक्ट्री.
मॉड्यूल दिखने की संभावना कम करना
Bazel और अन्य बिल्ड सिस्टम, हर टारगेट के लिए एक विज़िबिलिटी तय करने की अनुमति देते हैं. यह एक ऐसी प्रॉपर्टी है जिससे यह तय होता है कि कौनसे अन्य टारगेट उस पर निर्भर हो सकते हैं. निजी टारगेट का रेफ़रंस, सिर्फ़ उसकी BUILD
फ़ाइल में दिया जा सकता है. टारगेट के तहत, ज़्यादा लोगों तक पहुंचा जा सकता है
साफ़ तौर पर तय की गई BUILD
फ़ाइलों की सूची के टारगेट को ऐक्सेस कर सकता है या
के मामले में हर टारगेट के लिए उपलब्ध है.
ज़्यादातर प्रोग्रामिंग भाषाओं की तरह, आम तौर पर इसे दिखने से जितना हो सके उतना कम करना सबसे अच्छा होता है. आम तौर पर, Google की टीमें टारगेट सिर्फ़ तब सार्वजनिक करती हैं, जब वे टारगेट, Google की किसी भी टीम के लिए उपलब्ध, ज़्यादा इस्तेमाल की जाने वाली लाइब्रेरी दिखाते हों.
जिन टीमों को अपने कोड का इस्तेमाल करने से पहले दूसरों के साथ मिलकर काम करना होता है वे ये काम करेंगी
टारगेट की विज़िबिलिटी के तौर पर, उन लोगों या संगठनों की सूची को बनाए रखना जिन्हें अनुमति मिली हुई है. हर
टीम के आंतरिक कार्यान्वयन लक्ष्य केवल डायरेक्ट्री तक सीमित होंगे.
और ज़्यादातर BUILD
फ़ाइलों का सिर्फ़ एक टारगेट होगा जो
निजी.
डिपेंडेंसी मैनेज करना
मॉड्यूल ऐसा होना चाहिए कि वे एक-दूसरे को रेफ़र कर सकें. कोडबेस को छोटे-छोटे मॉड्यूल में बांटने का नुकसान यह है कि आपको उन मॉड्यूल के बीच डिपेंडेंसी मैनेज करनी पड़ती है. हालांकि, टूल की मदद से इसे ऑटोमेट किया जा सकता है. आम तौर पर, BUILD
फ़ाइल में ज़्यादातर कॉन्टेंट, इन डिपेंडेंसी के बारे में जानकारी देने में खर्च होता है.
इंटरनल डिपेंडेंसी
बारीक मॉड्यूल वाले किसी बड़े प्रोजेक्ट में, ज़्यादातर डिपेंडेंसी होती हैं संगठन के अंदर हो सकती है; यानी, उसी पर आधारित किसी अन्य टारगेट पर डेटा स्टोर करने की जगह. इंटरनल डिपेंडेंसी, बाहरी डिपेंडेंसी से इसमें अलग होती हैं: कि उन्हें पहले से बने आर्टफ़ैक्ट के तौर पर डाउनलोड करने के बजाय, सोर्स से बनाया गया हो बिल्ड रन करते समय. इसका मतलब यह भी है कि ऐसी किसी रणनीति के लिए “वर्शन” इंटरनल डिपेंडेंसी—टारगेट और उसकी सभी इंटरनल डिपेंडेंसी हमेशा डेटा स्टोर करने की जगह में उसी कमिट/रिविज़न के साथ बनाया जाता है. एक समस्या जो यह होनी चाहिए कि यह समझना ज़रूरी है कि आंतरिक डिपेंडेंसी का ध्यान रखते हुए कैसे काम किया जाए ट्रांज़िटिव डिपेंडेंसी (इमेज 1). मान लीजिए कि टारगेट A, टारगेट B पर निर्भर करता है. एक सामान्य लाइब्रेरी टारगेट C पर निर्भर होता है. क्या टारगेट A, टारगेट C में तय की गई क्लास का इस्तेमाल कर सकता है?
पहली इमेज. ट्रांसीटिव डिपेंडेंसी
जहां तक टूल की बात है, इसमें कोई समस्या नहीं है. B और C, दोनों को टारगेट A के बनने पर लिंक कर दिया जाएगा. इसलिए, C में तय किए गए सभी सिंबल A को पता होंगे. Bazel ने कई सालों तक इसकी अनुमति दी, लेकिन Google के बड़े होने के साथ ही, हमें समस्याएं दिखने लगीं. मान लें कि B को इस तरह रीफ़ैक्टर किया गया था कि अब उसे C पर निर्भर रहने की ज़रूरत नहीं है. अगर C पर B की डिपेंडेंसी हटा दी गई है, तो A और अन्य B पर निर्भरता के ज़रिए C का इस्तेमाल करने वाला टारगेट काम नहीं करेगा. असल में, किसी टारगेट की डिपेंडेंसी, उसके सार्वजनिक कॉन्ट्रैक्ट का हिस्सा बन गईं और उन्हें कभी भी सुरक्षित तरीके से बदला नहीं जा सका. इसका मतलब है कि समय के साथ डिपेंडेंसी इकट्ठा होती है और Google धीमा होना शुरू हो गया है.
Google ने इस समस्या को हल करने के लिए, “स्ट्रिक्ट ट्रांज़िटिव” इस्तेमाल किया डिपेंडेंसी मोड” पर सेट करना होगा. इस मोड में, Basel को पता चलता है कि टारगेट सीधे निर्भर किए बिना किसी प्रतीक का संदर्भ देता है और, यदि है, तो इसके साथ विफल होता है और एक शेल कमांड का उपयोग किया जा सकता है, जिसका उपयोग निर्भर है. यह बदलाव Google के पूरे कोड बेस पर लागू होगा हम अपने लाखों बिल्ड टारगेट में से हर एक को ऑप्टिमाइज़ करते हैं, ताकि हम अपनी टारगेट ऑडियंस की डिपेंडेंसी के लिए कई सालों तक मेहनत करनी पड़ी, लेकिन यह मुमकिन था. टारगेट में ग़ैर-ज़रूरी डिपेंडेंसी कम होने की वजह से, अब हमारे बिल्ड तेज़ी से बनते हैं. साथ ही, इंजीनियर उन डिपेंडेंसी को हटा सकते हैं जिनकी ज़रूरत नहीं है. ऐसा करने पर, उन टारगेट पर असर नहीं पड़ता जिनमें उन डिपेंडेंसी का इस्तेमाल किया गया है.
हमेशा की तरह, सख्त ट्रांज़िटिव डिपेंडेंसी लागू करने के दौरान ट्रेड-ऑफ़ हुआ. इसने बनाया
ज़्यादा जानकारी वाली फ़ाइलें बनाने की ज़रूरत होती है, क्योंकि अक्सर इस्तेमाल की जाने वाली लाइब्रेरी को अब सूची में जोड़ने की ज़रूरत होती है
कई जगहों पर हो सकता है, जबकि अचानक ऐसा नहीं हो सकता, लेकिन इंजीनियर
BUILD
फ़ाइलों में डिपेंडेंसी जोड़ने में ज़्यादा मेहनत करनी पड़ी. हम तब से लेकर अब तक
हमने ऐसे टूल बनाए हैं जो किसी समस्या का पता लगाकर, उसे कम करने में मदद करते हैं.
डिपेंडेंसी और उन्हें बिना किसी डेवलपर के, BUILD
फ़ाइलों में जोड़ना
मदद की जा सकती है. हालांकि, कोडबेस के स्केल होने पर, हमें लगता है कि ऐसे टूल के बिना भी, यह बदलाव करना सही है: BUILD
फ़ाइल में साफ़ तौर पर डिपेंडेंसी जोड़ने पर, एक बार शुल्क देना पड़ता है. हालांकि, जब तक बिल्ड टारगेट मौजूद है, तब तक इनपुट के तौर पर इस्तेमाल होने वाली डिपेंडेंसी से जुड़ी समस्याएं बनी रह सकती हैं. बेज़ल
स्ट्रिक ट्रांज़िटिव डिपेंडेंसी लागू करता है
डिफ़ॉल्ट रूप से Java कोड पर सेट करें.
बाहरी डिपेंडेंसी
अगर कोई डिपेंडेंसी इंटरनल नहीं है, तो वह बाहरी होनी चाहिए. बाहरी डिपेंडेंसी, उन आर्टफ़ैक्ट पर होती हैं जिन्हें बिल्ड सिस्टम के बाहर बनाया और सेव किया जाता है. कॉन्टेंट बनाने डिपेंडेंसी को सीधे आर्टफ़ैक्ट डेटा स्टोर करने की जगह से इंपोर्ट किया जाता है (आम तौर पर, इसे ऐक्सेस किया जाता है का इस्तेमाल किया जाता है. इनमें से एक बाहरी और आंतरिक डिपेंडेंसी के बीच सबसे बड़ा अंतर यह है कि बाहरी डिपेंडेंसी के वर्शन होते हैं और वे वर्शन इनसे अलग होते हैं प्रोजेक्ट का सोर्स कोड है.
अपने-आप बनाम मैन्युअल डिपेंडेंसी मैनेजमेंट
बिल्ड सिस्टम की मदद से, बाहरी डिपेंडेंसी के वर्शन मैनेज किए जा सकते हैं
मैन्युअल तरीके से या अपने-आप. मैन्युअल तरीके से मैनेज किए जाने पर, बिल्डफ़ाइल में साफ़ तौर पर उस वर्शन की जानकारी होती है जिसे आर्टफ़ैक्ट रिपॉज़िटरी से डाउनलोड करना है. इसके लिए, अक्सर 1.1.4
जैसी सेमांटिक वर्शन स्ट्रिंग का इस्तेमाल किया जाता है. अपने-आप मैनेज होने पर, सोर्स फ़ाइल
की अनुमति है और बिल्ड सिस्टम हमेशा सबसे नया वर्शन डाउनलोड करता है. उदाहरण के लिए, Gradle की मदद से डिपेंडेंसी के वर्शन को “1.+” के तौर पर दिखाया जा सकता है. इससे यह पता चलता है कि डिपेंडेंसी का कोई भी मामूली या पैच वर्शन स्वीकार किया जा सकता है, बशर्ते उसका मुख्य वर्शन 1 हो.
अपने-आप मैनेज होने वाली डिपेंडेंसी, छोटे प्रोजेक्ट के लिए आसान हो सकती हैं. हालांकि, आम तौर पर, छोटी-छोटी चीज़ों के बड़े साइज़ वाले प्रोजेक्ट की आपदा की रेसिपी है या जिस पर एक से ज़्यादा इंजीनियर काम कर रहे हैं. अपने-आप मैनेज होने वाली डिपेंडेंसी की समस्या यह है कि आपके पास यह कंट्रोल करने का विकल्प नहीं होता कि वर्शन कब अपडेट किया जाए. इस बात की कोई गारंटी नहीं है कि बाहरी पक्ष, काम करने वाले वर्शन में बदलाव नहीं करेंगे. भले ही, वे सिमेंटिक वर्शनिंग का इस्तेमाल करने का दावा करते हों. इसलिए, हो सकता है कि जो बिल्ड एक दिन काम कर रहा था वह अगले दिन काम न करे. साथ ही, यह पता लगाना भी आसान नहीं होगा कि क्या बदलाव हुआ है या उसे फिर से काम करने की स्थिति में कैसे लाया जाए. भले ही, बिल्ड में कोई गड़बड़ी न हो, लेकिन व्यवहार या परफ़ॉर्मेंस में ऐसे बदलाव हो सकते हैं जिन्हें ट्रैक करना मुश्किल हो.
इसके उलट, मैन्युअल तरीके से मैनेज की जाने वाली डिपेंडेंसी के लिए सोर्स में बदलाव करना पड़ता है कंट्रोल करना मुमकिन है, तो उन्हें आसानी से खोजा और रोल बैक किया जा सकता है. साथ ही, पुरानी डिपेंडेंसी के साथ बनाने के लिए, रिपॉज़िटरी का पुराना वर्शन देखें. Basel की सभी डिपेंडेंसी के वर्शन मैन्युअल रूप से तय किए जाने चाहिए. यहां तक कि कम संख्या में वर्शन मैनेज करने पर भी, मैन्युअल तरीके से वर्शन मैनेज करने में लगने वाला समय, वर्शन को स्थिर रखने के लिए ज़रूरी है.
एक वर्शन वाला नियम
लाइब्रेरी के अलग-अलग वर्शन को आम तौर पर, अलग-अलग आर्टफ़ैक्ट के ज़रिए दिखाया जाता है. इसलिए, यह सिद्धांत है कि एक ही बाहरी वर्शन के अलग-अलग बिल्ड सिस्टम में डिपेंडेंसी का एलान अलग-अलग नामों से नहीं किया जा सकता. इस तरह, हर टारगेट यह चुन सकता था कि उसे डिपेंडेंसी के किस वर्शन का इस्तेमाल करना है. इससे, काम करने में कई समस्याएं आती हैं. इसलिए, Google अपने कोडबेस में तीसरे पक्ष की सभी डिपेंडेंसी के लिए, एक वर्शन का नियम लागू करता है.
एक से ज़्यादा वर्शन की अनुमति देने में सबसे बड़ी समस्या डायमंड डिपेंडेंसी है समस्या. मान लें कि टारगेट A, टारगेट B और किसी बाहरी लाइब्रेरी के v1 पर निर्भर करता है. अगर टारगेट B को बाद में इसी के v2 पर डिपेंडेंसी जोड़ने के लिए रीफ़ैक्ट किया जाता है बाहरी लाइब्रेरी, लक्ष्य A ब्रेक होगा, क्योंकि अब यह स्पष्ट रूप से दो पर निर्भर है एक ही लाइब्रेरी के अलग-अलग वर्शन हैं. असरदार तरीके से, इस कस्टम फ़ाइल को जोड़ना टारगेट से कई वर्शन वाली तीसरे पक्ष की किसी लाइब्रेरी पर नई निर्भरता, क्योंकि उस टारगेट का कोई भी उपयोगकर्ता पहले से ही एक अलग वर्शन है. एक वर्शन के नियम का पालन करने पर, यह समस्या नहीं होती—अगर कोई टारगेट तीसरे पक्ष की लाइब्रेरी पर डिपेंडेंसी जोड़ता है, तो मौजूदा डिपेंडेंसी पहले से ही उसी वर्शन पर होंगी, ताकि वे साथ-साथ काम कर सकें.
ट्रांज़िटिव एक्सटर्नल डिपेंडेंसी
किसी बाहरी डिपेंडेंसी की ट्रांज़िशन डिपेंडेंसी से निपटना खास तौर पर मुश्किल हो सकता है. Maven Central जैसी कई आर्टफ़ैक्ट रिपॉज़िटरी, आर्टफ़ैक्ट को रिपॉज़िटरी में मौजूद दूसरे आर्टफ़ैक्ट के खास वर्शन पर निर्भरता तय करने की अनुमति देती हैं. Maven या Gradle जैसे बिल्ड टूल, डिफ़ॉल्ट रूप से हर ट्रांज़िटिव डिपेंडेंसी को बार-बार डाउनलोड करते हैं. इसका मतलब है कि आपके प्रोजेक्ट में एक डिपेंडेंसी जोड़ने से, कुल मिलाकर दर्जनों आर्टफ़ैक्ट डाउनलोड हो सकते हैं.
यह बहुत सुविधाजनक है: किसी नई लाइब्रेरी पर निर्भरता जोड़ते समय, यह उस लाइब्रेरी की ट्रांज़िटिव डिपेंडेंसी में से हर एक को ट्रैक करने में बहुत परेशानी होती है और उन सभी को मैन्युअल तरीके से जोड़ें. हालांकि, इसका एक बड़ा नुकसान भी है: अलग-अलग लाइब्रेरी, तीसरे पक्ष की एक ही लाइब्रेरी के अलग-अलग वर्शन पर निर्भर हो सकती हैं. इसलिए, यह रणनीति 'एक वर्शन' नियम का उल्लंघन करती है और डायमंड डिपेंडेंसी की समस्या पैदा करती है. यदि आपका लक्ष्य दो ऐसी बाहरी लाइब्रेरी पर निर्भर है जो एक ही डिपेंडेंसी के अलग-अलग वर्शन हैं. इसलिए, यह नहीं बताया जा सकता कि आपको पाएं. इसका यह भी मतलब है कि किसी बाहरी डिपेंडेंसी को अपडेट करने पर, पूरे कोडबेस में गड़बड़ियां हो सकती हैं. ऐसा तब होता है, जब नया वर्शन अपनी कुछ डिपेंडेंसी के ऐसे वर्शन को इंपोर्ट करना शुरू कर देता है जो एक-दूसरे से मेल नहीं खाते.
इस वजह से, Bazel ट्रांज़िशनरी डिपेंडेंसी को अपने-आप डाउनलोड नहीं करता.
अफ़सोस की बात यह है कि इस तरह के और भी तरीके हो सकते हैं—बेज़ल का दूसरा विकल्प यह है कि
ग्लोबल फ़ाइल, जिसमें डेटा स्टोर करने की हर जगह के बाहरी हिस्से की सूची होती है
डिपेंडेंसी और उस डिपेंडेंसी के लिए इस्तेमाल किए गए एक साफ़ तौर पर दिए गए वर्शन का इस्तेमाल पूरे डेटा में
डेटा स्टोर करने की जगह. सौभाग्य से, Bazel ऐसे टूल उपलब्ध कराता है जो Maven आर्टफ़ैक्ट के सेट की ट्रांज़िशन डिपेंडेंसी वाली फ़ाइल को अपने-आप जनरेट कर सकते हैं. शुरुआती WORKSPACE
फ़ाइल जनरेट करने के लिए, इस टूल को एक बार चलाया जा सकता है
और फिर उस फ़ाइल को मैन्युअल रूप से अपडेट करके
पर लागू होती है.
यहां भी, आपको सुविधा और स्केल करने की सुविधा में से किसी एक को चुनना होगा. छोटा ऐसा हो सकता है कि प्रोजेक्ट को ट्रांज़िटिव डिपेंडेंसी को मैनेज करने की चिंता न करनी पड़े साथ ही, वे खुद को इस तरह से बना सकते हैं कि वे ऑटोमैटिक ट्रांज़िटिव इस्तेमाल कर सकें निर्भरता. संगठन और कोडबेस के बढ़ने के साथ-साथ, यह रणनीति कम और कम आकर्षक होती जाती है. साथ ही, इससे होने वाले विरोध और अनचाहे नतीजे भी ज़्यादा और ज़्यादा बार दिखने लगते हैं. बड़े पैमाने पर, डिपेंडेंसी को मैन्युअल तरीके से मैनेज करने की लागत, डिपेंडेंसी को अपने-आप मैनेज करने की वजह से होने वाली समस्याओं को हल करने की लागत से काफ़ी कम होती है.
बाहरी डिपेंडेंसी का इस्तेमाल करके, बिल्ड के नतीजों को कैश मेमोरी में सेव करना
बाहरी डिपेंडेंसी ज़्यादातर तीसरे पक्ष से मिलती हैं. ये पक्ष, लाइब्रेरी के स्थिर वर्शन रिलीज़ करते हैं. ऐसा हो सकता है कि वे सोर्स कोड उपलब्ध न कराएं. कुछ संगठन, अपने कुछ कोड को आर्टफ़ैक्ट के तौर पर उपलब्ध कराने का विकल्प भी चुन सकते हैं. इससे, दूसरे कोड के लिए, आंतरिक डिपेंडेंसी के बजाय, थर्ड पार्टी के तौर पर उनका इस्तेमाल किया जा सकता है. अगर आर्टफ़ैक्ट को बिल्ड करने में ज़्यादा समय लगता है, लेकिन डाउनलोड करने में कम, तो सैद्धांतिक तौर पर बिल्ड की प्रोसेस को तेज़ किया जा सकता है.
हालांकि, इसकी वजह से बहुत ज़्यादा काम करना पड़ता है और समस्याएं भी पैदा होती हैं: किसी को उन सभी आर्टफ़ैक्ट को बनाने और उन्हें डेटा स्टोर करने की जगह का इस्तेमाल कर सकते हैं और क्लाइंट को यह पक्का करना होगा कि वे सबसे नया वर्शन है. डीबग करना भी बहुत मुश्किल हो जाता है, क्योंकि सिस्टम के अलग-अलग हिस्सों को रिपॉज़िटरी के अलग-अलग पॉइंट से बनाया गया होगा. साथ ही, सोर्स ट्री का एक जैसा व्यू नहीं दिखता.
आर्टफ़ैक्ट को बनाने में लगने वाले समय की समस्या को हल करने का बेहतर तरीका यह है कि आप रिमोट कैश मेमोरी का इस्तेमाल करने वाले बिल्ड सिस्टम का इस्तेमाल करें. ऐसा बिल्ड सिस्टम, हर बिल्ड से मिले आर्टफ़ैक्ट को किसी जगह पर सेव करता है जिसे कई इंजीनियर के बीच शेयर किया जाता है. इसलिए, अगर डेवलपर ऐसे आर्टफ़ैक्ट पर हाल ही में किसी और ने बनाया था, तो बिल्ड सिस्टम अपने-आप उसे बनाने के बजाय उस पर सबसे ज़्यादा विचार करते हैं. इससे ऐप्लिकेशन की परफ़ॉर्मेंस के सभी फ़ायदे मिलते हैं यह सीधे तौर पर आर्टफ़ैक्ट पर निर्भर करता है. साथ ही, यह पक्का करता है कि बिल्ड ताकि उन्हें हमेशा एक ही सोर्स से बनाया गया हो. Google, अपने अंदरूनी कामों के लिए इसी रणनीति का इस्तेमाल करता है. साथ ही, Bazel को रिमोट कैश मेमोरी का इस्तेमाल करने के लिए कॉन्फ़िगर किया जा सकता है.
बाहरी डिपेंडेंसी की सुरक्षा और विश्वसनीयता
तीसरे पक्ष के सोर्स से मिले आर्टफ़ैक्ट के आधार पर, इसमें नुकसान हो सकता है. अगर तीसरे पक्ष का सोर्स (जैसे, आर्टफ़ैक्ट रिपॉज़िटरी) काम नहीं करता है, तो उपलब्धता का खतरा होता है. ऐसा इसलिए, क्योंकि अगर बाहरी डिपेंडेंसी डाउनलोड नहीं हो पाती है, तो आपका पूरा बिल्ड रुक सकता है. सुरक्षा जोखिम भी होता है: अगर तीसरे पक्ष के सिस्टम ने
किसी हमलावर ने छेड़छाड़ की है, तो हमलावर
अपने खुद के किसी डिज़ाइन वाले आर्टफ़ैक्ट की मदद से, आर्बिट्रेरी कोड को इंजेक्ट कर सकता है
आपके बिल्ड में इस्तेमाल हो सकता है. इन दोनों समस्याओं को कम करने के लिए, उन सभी आर्टफ़ैक्ट को अपने कंट्रोल वाले सर्वर पर मिरर करें जिन पर आपको निर्भर रहना है. साथ ही, अपने बिल्ड सिस्टम को Maven Central जैसे तीसरे पक्ष के आर्टफ़ैक्ट डेटा स्टोर को ऐक्सेस करने से रोकें. हालांकि, इनका रखरखाव करना आसान नहीं है. इसके लिए, समय और संसाधनों की ज़रूरत होती है. इसलिए, इनका इस्तेमाल करना या नहीं, यह प्रोजेक्ट के स्केल पर निर्भर करता है. सुरक्षा से जुड़ी समस्या को कम लागत में पूरी तरह से रोका जा सकता है. इसके लिए, सोर्स रिपॉज़िटरी में तीसरे पक्ष के हर आर्टफ़ैक्ट के हैश की ज़रूरत होती है. इससे, आर्टफ़ैक्ट में छेड़छाड़ होने पर बिल्ड पूरा नहीं हो पाता. इस समस्या से पूरी तरह बचने के लिए, अपने प्रोजेक्ट की डिपेंडेंसी को वेंडर के तौर पर इस्तेमाल करें. जब कोई प्रोजेक्ट अपनी डिपेंडेंसी को वेंडर करता है, तो वह उन्हें प्रोजेक्ट के सोर्स कोड के साथ सोर्स कंट्रोल में, सोर्स या बाइनरी के तौर पर जांचता है. इसका मतलब है कि प्रोजेक्ट की सभी बाहरी डिपेंडेंसी, अंदरूनी डिपेंडेंसी में बदल गई हैं. Google यह तरीका अंदरूनी तौर पर इस्तेमाल करता है और हर तीसरे पक्ष की जांच करता है
रूट पर एक third_party
डायरेक्ट्री में पूरे Google में रेफ़र की गई लाइब्रेरी
सोर्स ट्री में रखा जा सकता है. हालांकि, यह Google में केवल इसलिए काम करता है, क्योंकि Google का
सोर्स कंट्रोल सिस्टम को इस तरह से बनाया गया है कि वह बहुत बड़े मोनो रिपॉज़िटरी को मैनेज कर सके.
हो सकता है कि वेंडरिंग की सुविधा सभी संगठनों के लिए उपलब्ध न हो.