paint-brush
ऐप आर्किटेक्चर आरेखों को स्वचालित करना: मैंने स्रोत से कोडबेस को मैप करने के लिए एक टूल कैसे बनायाद्वारा@vladimirf
29,410 रीडिंग
29,410 रीडिंग

ऐप आर्किटेक्चर आरेखों को स्वचालित करना: मैंने स्रोत से कोडबेस को मैप करने के लिए एक टूल कैसे बनाया

द्वारा Vladimir Filipchenko6m2024/07/30
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

क्या आपने कभी सोचा है कि कोई ऐसा टूल हो जो आपके कोड को तुरंत एक स्पष्ट, विज़ुअल डायग्राम में बदल सके? खैर, NoReDraw बिल्कुल यही करता है! एक सॉफ़्टवेयर इंजीनियर की हताशा से पैदा हुआ यह टूल आर्टिफैक्ट और कॉन्फ़िगरेशन जैसे प्रमुख घटकों की पहचान करता है, और उन्हें एक व्यापक आर्किटेक्चर डायग्राम बनाने के लिए एक साथ जोड़ता है। इसे सुपर कस्टमाइज़ करने योग्य और आसानी से विस्तार योग्य होने के लिए डिज़ाइन किया गया है, यह सुनिश्चित करता है कि हर बार कुछ बदलाव होने पर डायग्राम को फिर से बनाने की परेशानी के बिना आपका दस्तावेज़ अद्यतित रहे।
featured image - ऐप आर्किटेक्चर आरेखों को स्वचालित करना: मैंने स्रोत से कोडबेस को मैप करने के लिए एक टूल कैसे बनाया
Vladimir Filipchenko HackerNoon profile picture
0-item

क्योंकि जीवन आरेखों को पुनः बनाने के लिए बहुत छोटा है


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


यह उपकरण कोडबेस की समीक्षा करेगा और मुख्य पहलुओं पर प्रकाश डालते हुए एक एप्लिकेशन आर्किटेक्चर आरेख बनाएगा। एक नया इंजीनियर आरेख को देखकर कह सकता है, "आह, ठीक है, यह इस तरह काम करता है।"


सबसे पहली बात

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


सबसे पहले, मैंने Gradle, Docker और Terraform के साथ एक सैंपल Java ऐप बनाया। GitHub एक्शन पाइपलाइन ऐप को Amazon Elastic Container Service पर तैनात करती है। यह रेपो उस टूल का स्रोत होगा जिसे मैं बनाऊँगा (कोड यहाँ है)।


दूसरा, मैंने एक बहुत ही उच्च-स्तरीय आरेख बनाया जो मैं परिणाम के रूप में देखना चाहता था:



मैंने निर्णय लिया कि दो प्रकार के संसाधन होंगे:

अवशेष

मुझे आर्टिफैक्ट शब्द बहुत ज़्यादा भारी लगा, इसलिए मैंने रेलिक चुना। तो रेलिक क्या है? यह 90% ऐसी चीज़ है जिसे आप देखना चाहते हैं। इसमें शामिल हैं, लेकिन इन्हीं तक सीमित नहीं:

  • कलाकृतियाँ (योजना पर नीले बक्से, यानी, जार, डॉकर छवियाँ),
  • टेराफॉर्म संसाधनों को कॉन्फ़िगर करता है (योजना पर गुलाबी बॉक्स, यानी, EC2 इंस्टेंस, ECS, SQS कतारें),
  • कुबेरनेट्स संसाधन,
  • और भी बहुत कुछ


हर रेलिक का एक नाम होता है (जैसे, my-shiny-app), वैकल्पिक प्रकार (जैसे, Jar), और कुंजी → मान युग्मों का एक सेट (जैसे, पथ → /build/libs/my-shiny-app.jar) जो रेलिक का पूरी तरह से वर्णन करता है। उन्हें परिभाषाएँ कहा जाता है। रेलिक में जितनी अधिक परिभाषाएँ होंगी - उतना ही बेहतर होगा।

स्रोत

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


अवशेष और स्रोत का संबंध अनेक-से-अनेक है।


फूट डालो और राज करो

कोड के हर हिस्से को कवर करना असंभव है। आधुनिक ऐप्स में कई फ्रेमवर्क, टूल या क्लाउड घटक हो सकते हैं। अकेले AWS के पास टेराफ़ॉर्म के लिए लगभग 950 संसाधन और डेटा स्रोत हैं! टूल को आसानी से विस्तार योग्य और डिज़ाइन द्वारा अलग किया जाना चाहिए ताकि अन्य लोग या कंपनियाँ योगदान दे सकें।


जबकि मैं अविश्वसनीय रूप से प्लग करने योग्य टेराफॉर्म प्रदाताओं की वास्तुकला का बहुत बड़ा प्रशंसक हूं, मैंने इसे सरलीकृत करने के बावजूद इसे बनाने का फैसला किया:

प्रदाताओं


प्रदाता की एक स्पष्ट जिम्मेदारी है: अनुरोधित स्रोत फ़ाइलों के आधार पर अवशेष बनाना। उदाहरण के लिए, GradleProvider *.gradle फ़ाइलों को पढ़ता है और Jar , War , या Gz अवशेष लौटाता है। प्रत्येक प्रदाता उन प्रकारों के अवशेष बनाता है जिनके बारे में वे जानते हैं। प्रदाता अवशेषों के बीच बातचीत की परवाह नहीं करते हैं। वे अवशेषों को घोषणात्मक रूप से बनाते हैं, एक दूसरे से पूरी तरह से अलग।


इस दृष्टिकोण के साथ, आप जितना चाहें उतना गहराई से जा सकते हैं। GitHub Actions इसका एक अच्छा उदाहरण है। एक सामान्य वर्कफ़्लो YAML फ़ाइल में दर्जनों चरण होते हैं, जो शिथिल युग्मित घटकों और सेवाओं का उपयोग करते हैं। एक वर्कफ़्लो एक JAR, फिर एक Docker छवि बना सकता है, और इसे पर्यावरण में तैनात कर सकता है। वर्कफ़्लो में हर एक चरण को उसके प्रदाता द्वारा कवर किया जा सकता है। इसलिए, मान लीजिए, Docker Actions के डेवलपर्स केवल उन चरणों से संबंधित एक प्रदाता बनाते हैं जिनकी उन्हें परवाह है।


यह दृष्टिकोण किसी भी संख्या में लोगों को समानांतर रूप से काम करने की अनुमति देता है, जिससे टूल में अधिक तर्क जुड़ जाता है। अंतिम उपयोगकर्ता अपने प्रदाताओं को भी जल्दी से लागू कर सकते हैं (कुछ मालिकाना तकनीक के मामले में)। नीचे अनुकूलन के अंतर्गत अधिक देखें।


विलय करना या न करना

सबसे रोचक भाग में जाने से पहले आइए अगले जाल पर नज़र डालें। दो प्रदाता, जिनमें से प्रत्येक एक अवशेष बनाता है। यह ठीक है। लेकिन क्या होगा अगर इनमें से दो अवशेष दो स्थानों पर परिभाषित एक ही घटक का प्रतिनिधित्व करते हैं? यहाँ एक उदाहरण है।


AmazonECSProvider टास्क डेफ़िनेशन JSON को पार्स करता है और AmazonECSTask प्रकार के साथ एक Relic तैयार करता है। GitHub एक्शन वर्कफ़्लो में ECS से संबंधित चरण भी है, इसलिए दूसरा प्रदाता AmazonECSTaskDeployment Relic बनाता है। अब, हमारे पास डुप्लिकेट हैं क्योंकि दोनों प्रदाता एक दूसरे के बारे में कुछ नहीं जानते हैं। इसके अलावा, उनमें से किसी के लिए यह मान लेना गलत है कि दूसरे ने पहले ही एक Relic बना लिया है। फिर क्या?


अवशेषों का विलय


हम किसी भी डुप्लिकेट को नहीं हटा सकते क्योंकि उनमें से प्रत्येक की अपनी परिभाषाएँ (विशेषताएँ) हैं। एकमात्र तरीका उन्हें मर्ज करना है। डिफ़ॉल्ट रूप से, अगला तर्क मर्जिंग निर्णय को परिभाषित करता है:


 relic1.name() == relic2.name() && relic1.source() != relic2.source()


हम दो अवशेषों को मर्ज करते हैं यदि उनके नाम समान हैं, लेकिन वे विभिन्न स्रोतों में परिभाषित हैं (जैसे हमारे उदाहरण में, रिपो में JSON और कार्य परिभाषा संदर्भ गिटहब क्रियाओं में है)।


जब हम विलय करते हैं, तो हम:

  1. एकल नाम चुनें
  2. सभी परिभाषाएँ (कुंजी → मान युग्म) मर्ज करें
  3. दोनों मूल स्रोतों का संदर्भ देते हुए एक संयुक्त स्रोत बनाएं


एक रेखा खींचो

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


याद है जब मैंने कहा था कि प्रदाताओं को अन्य प्रदाताओं द्वारा बनाए गए अवशेषों के बारे में कोई जानकारी नहीं है? यह अभी भी सच है। हालाँकि, एक प्रदाता एक अवशेष के लिए एक मिलानकर्ता को परिभाषित करता है। दूसरे शब्दों में, यह परिणामी आरेख पर दो बक्सों के बीच एक तीर के एक तरफ का प्रतिनिधित्व करता है।


अवशेष मिलान


उदाहरण. Dockerfile में एक ENTRYPOINT निर्देश है.


 ENTRYPOINT java -jar /app/arch-diagram-sample.jar


कुछ हद तक निश्चितता के साथ, हम कह सकते हैं कि Docker ENTRYPOINT के अंतर्गत निर्दिष्ट की गई हर चीज़ को कंटेनराइज़ करता है । इसलिए, Dockerfile Relic में एक सरल Matcher फ़ंक्शन है: entrypointInstruction.contains(anotherRelicsDefinition) . सबसे अधिक संभावना है कि परिभाषाओं में arch-diagram-sample.jar वाले कुछ Jar Relics इससे मेल खाएँगे। यदि हाँ, तो Dockerfile और Jar Relics के बीच एक तीर दिखाई देता है।


मैचर परिभाषित होने के साथ, लिंकिंग प्रक्रिया बहुत सरल लगती है। लिंकिंग सेवा सभी अवशेषों पर पुनरावृत्ति करती है और उनके मैचर के फ़ंक्शन को कॉल करती है। क्या अवशेष A, अवशेष B की किसी परिभाषा से मेल खाता है? हाँ? परिणामी ग्राफ़ में उन अवशेषों के बीच एक किनारा जोड़ें। किनारे को नाम भी दिया जा सकता है।


VISUALIZATION

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


नमूना रिपो का अंतिम आरेख इस प्रकार दिखता है:

अंतिम आरेख


अनुकूलन

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


किया

स्रोत कोड के आधार पर आरेख तैयार करने से संभवतः गति मिलेगी। और विशेष रूप से NoReDraw टूल (हाँ, यह उस टूल का नाम है जिसके बारे में मैं बात कर रहा था)। योगदानकर्ताओं का स्वागत है !


सबसे उल्लेखनीय लाभ (जो नाम से आता है) यह है कि घटकों के बदलने पर आरेख को फिर से बनाने की आवश्यकता नहीं होती है। इंजीनियरिंग ध्यान की कमी के कारण सामान्य रूप से दस्तावेज़ीकरण (और विशेष रूप से आरेख) पुराना हो जाता है। NoReDraw जैसे उपकरणों के साथ, यह अब कोई समस्या नहीं होनी चाहिए क्योंकि यह किसी भी PR/CI पाइपलाइन में आसानी से प्लग करने योग्य है। याद रखें, आरेखों को फिर से बनाने के लिए जीवन बहुत छोटा है 😉