जैसे-जैसे डिजिटल परिदृश्य विकसित होता है, वैसे-वैसे आधुनिक वेबसाइटों की जटिलता भी बढ़ती जाती है। बेहतर उपयोगकर्ता अनुभव और उन्नत सुविधाओं की बढ़ती मांग के साथ, फ्रंटएंड डेवलपर्स को स्केलेबल, रखरखाव योग्य और कुशल आर्किटेक्चर बनाने की चुनौती का सामना करना पड़ता है।
फ्रंटएंड आर्किटेक्चर पर उपलब्ध लेखों और संसाधनों की अधिकता के बीच, एक महत्वपूर्ण संख्या क्लीन आर्किटेक्चर और इसके अनुकूलन पर केंद्रित है। वास्तव में, सर्वेक्षण किए गए लगभग 70 लेखों में से 50% से अधिक फ्रंट-एंड डेवलपमेंट के संदर्भ में क्लीन आर्किटेक्चर पर चर्चा करते हैं।
जानकारी की संपत्ति के बावजूद, एक स्पष्ट मुद्दा बना रहता है: कई प्रस्तावित वास्तुशिल्प विचारों को वास्तविक दुनिया के उत्पादन वातावरण में कभी भी लागू नहीं किया जा सकता है। यह व्यावहारिक परिदृश्यों में उनकी प्रभावशीलता और प्रयोज्यता के बारे में संदेह पैदा करता है।
इस चिंता से प्रेरित होकर, मैंने फ्रंटएंड पर क्लीन आर्किटेक्चर को लागू करने के लिए छह महीने की यात्रा शुरू की, जिससे मुझे इन विचारों की वास्तविकताओं का सामना करने और गेहूँ को फूस से अलग करने की अनुमति मिली।
इस लेख में, मैं इस यात्रा से अपने अनुभव और अंतर्दृष्टि साझा करूंगा, जिसमें एक व्यापक गाइड की पेशकश की जाएगी कि कैसे स्वच्छ वास्तुकला को सफलतापूर्वक लागू किया जाए।
चुनौतियों, सर्वोत्तम प्रथाओं और वास्तविक दुनिया के समाधानों पर प्रकाश डालते हुए, इस लेख का उद्देश्य फ्रंटएंड डेवलपर्स को वे उपकरण प्रदान करना है जिनकी उन्हें वेबसाइट विकास की निरंतर विकसित दुनिया को नेविगेट करने की आवश्यकता है।
आज के तेजी से विकसित हो रहे डिजिटल इकोसिस्टम में, जब फ्रंटएंड फ्रेमवर्क की बात आती है तो डेवलपर्स के पास पसंद के लिए खराब हो जाते हैं। विकल्पों की यह प्रचुरता कई समस्याओं का समाधान करती है और विकास प्रक्रिया को सरल बनाती है।
हालाँकि, यह डेवलपर्स के बीच अंतहीन बहस की ओर ले जाता है, प्रत्येक का दावा है कि उनका पसंदीदा ढांचा दूसरों से बेहतर है। सच तो यह है कि हमारी तेज़-तर्रार दुनिया में, नई जावास्क्रिप्ट लाइब्रेरी रोज़ाना उभरती हैं, और फ्रेमवर्क लगभग हर महीने पेश किए जाते हैं।
इस तरह के गतिशील वातावरण में लचीलेपन और अनुकूलनशीलता को बनाए रखने के लिए, हमें एक ऐसे आर्किटेक्चर की आवश्यकता है जो विशिष्ट रूपरेखाओं और तकनीकों से परे हो।
यह उत्पाद कंपनियों या लंबी अवधि के अनुबंधों के लिए विशेष रूप से महत्वपूर्ण है जिसमें रखरखाव शामिल है, जहां बदलते रुझान और तकनीकी प्रगति को समायोजित किया जाना चाहिए।
विवरणों से स्वतंत्र होने के नाते, जैसे कि रूपरेखाएँ, हमें उस उत्पाद पर ध्यान केंद्रित करने की अनुमति देती हैं जिस पर हम काम कर रहे हैं और इसके जीवनचक्र के दौरान होने वाले परिवर्तनों के लिए तैयार हो सकते हैं।
डर नहीं; इस लेख का उद्देश्य इस दुविधा का उत्तर प्रदान करना है।
फ्रंटएंड पर क्लीन आर्किटेक्चर को लागू करने की मेरी खोज में, मैंने यह सुनिश्चित करने के लिए कई फुलस्टैक और बैकएंड डेवलपर्स के साथ मिलकर काम किया कि आर्किटेक्चर कम से कम फ्रंटएंड अनुभव वाले लोगों के लिए भी बोधगम्य और बनाए रखने योग्य होगा।
इसलिए, हमारे आर्किटेक्चर की प्राथमिक आवश्यकताओं में से एक बैकएंड डेवलपर्स के लिए इसकी पहुंच है, जो फ्रंटएंड पेचीदगियों से अच्छी तरह वाकिफ नहीं हो सकते हैं, साथ ही फुलस्टैक डेवलपर्स जिनके पास व्यापक फ्रंटएंड विशेषज्ञता नहीं हो सकती है।
फ्रंटएंड और बैकएंड टीमों के बीच सहज सहयोग को बढ़ावा देकर, आर्किटेक्चर का उद्देश्य अंतर को पाटना और एकीकृत विकास अनुभव बनाना है।
दुर्भाग्य से, कुछ भयानक सामग्री बनाने के लिए, हमें कुछ पृष्ठभूमि की जानकारी प्राप्त करने की आवश्यकता है। अंतर्निहित सिद्धांतों की स्पष्ट समझ न केवल कार्यान्वयन प्रक्रिया को सुविधाजनक बनाएगी बल्कि यह भी सुनिश्चित करेगी कि आर्किटेक्चर सॉफ्टवेयर विकास में सर्वोत्तम प्रथाओं का पालन करता है।
इस खंड में, हम तीन प्रमुख अवधारणाओं को पेश करेंगे जो हमारे वास्तुशिल्प दृष्टिकोण का आधार बनते हैं: ठोस सिद्धांत , स्वच्छ वास्तुकला (जो वास्तव में ठोस सिद्धांतों से आता है), और परमाणु डिजाइन । यदि आप इन क्षेत्रों के बारे में दृढ़ता से महसूस करते हैं तो आप इस खंड को छोड़ सकते हैं।
SOLID पाँच डिज़ाइन सिद्धांतों का प्रतिनिधित्व करने वाला एक संक्षिप्त नाम है जो डेवलपर्स को स्केलेबल, रखरखाव योग्य और मॉड्यूलर सॉफ़्टवेयर बनाने में मार्गदर्शन करता है:
यदि आप इस विषय को और अधिक गहराई से एक्सप्लोर करना चाहते हैं, जिसे करने के लिए मैं आपको प्रोत्साहित करता हूं, तो कोई समस्या नहीं है। हालाँकि, अभी के लिए, मैंने जो प्रस्तुत किया है वह आगे जाने के लिए पर्याप्त है।
और इस लेख के संदर्भ में SOLID हमें क्या देता है?
ठोस सिद्धांतों और विभिन्न अनुप्रयोगों के विकास में अपने व्यापक अनुभव के आधार पर रॉबर्ट सी मार्टिन ने स्वच्छ वास्तुकला की अवधारणा का प्रस्ताव रखा। इस अवधारणा पर चर्चा करते समय, नीचे दिए गए आरेख को अक्सर इसकी संरचना को नेत्रहीन रूप से दर्शाने के लिए संदर्भित किया जाता है:
इसलिए, स्वच्छ वास्तुकला कोई नई अवधारणा नहीं है; कार्यात्मक प्रोग्रामिंग और बैकएंड विकास सहित विभिन्न प्रोग्रामिंग प्रतिमानों में इसका व्यापक रूप से उपयोग किया गया है।
लोडाश और कई बैकएंड फ्रेमवर्क जैसे पुस्तकालयों ने इस वास्तु दृष्टिकोण को अपनाया है, जो कि ठोस सिद्धांतों में निहित है।
स्वच्छ वास्तुकला चिंताओं को अलग करने और एक आवेदन के भीतर स्वतंत्र, परीक्षण योग्य परतों के निर्माण पर जोर देती है, सिस्टम को समझने, बनाए रखने और संशोधित करने में आसान बनाने के प्राथमिक लक्ष्य के साथ।
वास्तुकला संकेंद्रित हलकों या परतों में व्यवस्थित है; प्रत्येक की स्पष्ट सीमाएँ, निर्भरताएँ और उत्तरदायित्व हैं:
क्लीन आर्किटेक्चर बाहरी परतों से आंतरिक परतों तक निर्भरता के प्रवाह को बढ़ावा देता है, यह सुनिश्चित करता है कि मुख्य व्यावसायिक तर्क विशिष्ट तकनीकों या उपयोग की जाने वाली रूपरेखाओं से स्वतंत्र रहता है।
इसका परिणाम एक लचीला, बनाए रखने योग्य और परीक्षण योग्य कोडबेस होता है जो आसानी से बदलती आवश्यकताओं या प्रौद्योगिकी ढेर के अनुकूल हो सकता है।
परमाणु डिजाइन एक पद्धति है जो यूआई घटकों को उनके सबसे बुनियादी तत्वों में इंटरफेस को तोड़कर और फिर उन्हें अधिक जटिल संरचनाओं में पुन: संयोजन करके व्यवस्थित करती है। ब्रैड फ्रॉस्ट ने पहली बार 2008 में "परमाणु डिजाइन पद्धति" नामक एक लेख में अवधारणा पेश की।
यहाँ एक ग्राफिक है जो परमाणु डिजाइन की अवधारणा को दर्शाता है:
इसमें पाँच अलग-अलग स्तर होते हैं:
एटॉमिक डिज़ाइन को अपनाने से, डेवलपर्स कई लाभ प्राप्त कर सकते हैं, जैसे कि मॉड्युलैरिटी, पुन: प्रयोज्यता और UI घटकों के लिए एक स्पष्ट संरचना, क्योंकि इसके लिए हमें डिज़ाइन सिस्टम दृष्टिकोण का पालन करने की आवश्यकता होती है, लेकिन यह इस लेख का विषय नहीं है, इसलिए आगे बढ़ें।
दृश्यपटल के विकास के लिए स्वच्छ वास्तुकला पर एक सुविचारित परिप्रेक्ष्य विकसित करने के लिए, मैंने एक एप्लिकेशन बनाने की यात्रा शुरू की। छह महीने की अवधि में, मैंने इस परियोजना पर काम करते हुए मूल्यवान अंतर्दृष्टि और अनुभव प्राप्त किया।
नतीजतन, इस लेख में प्रदान किए गए उदाहरण आवेदन के साथ मेरे व्यावहारिक अनुभव से आते हैं। पारदर्शिता बनाए रखने के लिए, सभी उदाहरण सार्वजनिक रूप से सुलभ कोड से लिए गए हैं।
आप रिपॉजिटरी में जाकर अंतिम परिणाम देख सकते हैं
जैसा कि पहले उल्लेख किया गया है, स्वच्छ वास्तुकला के कई कार्यान्वयन ऑनलाइन उपलब्ध हैं। हालाँकि, इन कार्यान्वयनों में कुछ सामान्य तत्वों की पहचान की जा सकती है:
इन समानताओं को समझकर, हम स्वच्छ वास्तुकला की मूलभूत संरचना की सराहना कर सकते हैं और इसे अपनी विशिष्ट आवश्यकताओं के अनुकूल बना सकते हैं।
हमारे आवेदन के मुख्य भाग में शामिल हैं:
उपयोग के मामले : उपयोग के मामले डेटा को सहेजने, अपडेट करने और लाने जैसे विभिन्न कार्यों के लिए व्यावसायिक नियमों का वर्णन करते हैं। उदाहरण के लिए, उपयोग के मामले में धारणा से शब्दों की सूची प्राप्त करना या सीखे गए शब्दों के लिए उपयोगकर्ता की दैनिक लकीर को बढ़ाना शामिल हो सकता है।
अनिवार्य रूप से, उपयोग के मामले व्यावसायिक दृष्टिकोण से एप्लिकेशन के कार्यों और प्रक्रियाओं को संभालते हैं, यह सुनिश्चित करते हुए कि सिस्टम वांछित उद्देश्यों के अनुसार कार्य करता है।
मॉडल : मॉडल एप्लिकेशन के भीतर व्यावसायिक संस्थाओं का प्रतिनिधित्व करते हैं। इन्हें टाइपस्क्रिप्ट इंटरफेस का उपयोग करके परिभाषित किया जा सकता है, यह सुनिश्चित करते हुए कि वे जरूरतों और व्यावसायिक आवश्यकताओं के साथ संरेखित हों।
उदाहरण के लिए, यदि उपयोग के मामले में धारणा से शब्दों की एक सूची प्राप्त करना शामिल है, तो आपको उस सूची के लिए डेटा संरचना का सटीक वर्णन करने के लिए एक मॉडल की आवश्यकता होगी, जो उचित व्यावसायिक नियमों और बाधाओं का पालन करे।
संचालन : कभी-कभी, कुछ कार्यों को उपयोग मामलों के रूप में परिभाषित करना संभव नहीं हो सकता है, या आप पुन: प्रयोज्य कार्यों को बनाना चाहते हैं जिन्हें आपके डोमेन के कई हिस्सों में नियोजित किया जा सकता है। उदाहरण के लिए, यदि आपको किसी धारणा शब्द को नाम से खोजने के लिए एक फ़ंक्शन लिखने की आवश्यकता है, तो यह वह जगह है जहां ऐसे ऑपरेशन मौजूद होने चाहिए।
ऑपरेशंस डोमेन-विशिष्ट लॉजिक को एनकैप्सुलेट करने के लिए उपयोगी होते हैं जिन्हें एप्लिकेशन के भीतर विभिन्न संदर्भों में साझा और उपयोग किया जा सकता है।
रिपॉजिटरी इंटरफेस : उपयोग के मामलों में डेटा तक पहुंचने के साधन की आवश्यकता होती है। निर्भरता व्युत्क्रम सिद्धांत के अनुसार, डोमेन परत को किसी अन्य परत पर निर्भर नहीं होना चाहिए (जबकि अन्य परतें इस पर निर्भर करती हैं); इसलिए, यह परत रिपॉजिटरी के लिए इंटरफेस को परिभाषित करती है।
यह ध्यान रखना महत्वपूर्ण है कि यह इंटरफेस निर्दिष्ट करता है, कार्यान्वयन विवरण नहीं। रिपॉजिटरी स्वयं रिपॉजिटरी पैटर्न का उपयोग करते हैं जो वास्तविक डेटा स्रोत के लिए अज्ञेयवादी है और उन स्रोतों से डेटा लाने या भेजने के लिए तर्क पर जोर देता है।
यह उल्लेख करना महत्वपूर्ण है कि एक रिपॉजिटरी कई एपीआई लागू कर सकता है, और एक एकल उपयोग मामला कई रिपॉजिटरी का उपयोग कर सकता है।
यह परत डेटा एक्सेस के लिए जिम्मेदार है और आवश्यकतानुसार विभिन्न स्रोतों से संचार कर सकती है। यह देखते हुए कि हम एक फ्रंटएंड एप्लिकेशन विकसित कर रहे हैं, यह परत मुख्य रूप से ब्राउज़र एपीआई के लिए आवरण के रूप में काम करेगी।
इसमें REST, लोकल स्टोरेज, IndexedDB, स्पीच सिंथेसिस और बहुत कुछ के लिए API शामिल हैं।
यह नोट करना महत्वपूर्ण है कि यदि आप OpenAPI प्रकार और HTTP क्लाइंट उत्पन्न करना चाहते हैं, तो उन्हें रखने के लिए API परत आदर्श स्थान है। इस परत के भीतर, हमारे पास है:
एपीआई एडॉप्टर : एपीआई एडेप्टर हमारे एप्लिकेशन में उपयोग किए जाने वाले ब्राउज़र एपीआई के लिए एक विशेष एडेप्टर है। यह घटक ऐप की मेमोरी या आपके द्वारा उपयोग किए जाने वाले किसी अन्य डेटा स्रोत के साथ REST कॉल और संचार का प्रबंधन करता है।
आप चाहें तो अपना खुद का ऑब्जेक्ट स्टोरेज सिस्टम भी बना और लागू कर सकते हैं। एक समर्पित एपीआई एडेप्टर होने से, आप विभिन्न डेटा स्रोतों के साथ बातचीत करने के लिए एक सुसंगत इंटरफ़ेस बनाए रख सकते हैं, जिससे उन्हें आवश्यकतानुसार अपडेट करना या बदलना आसान हो जाता है।
रिपॉजिटरी परत कई एपीआई के एकीकरण का प्रबंधन करके, एपीआई-विशिष्ट प्रकारों को डोमेन प्रकारों में मैप करने और डेटा बदलने के लिए संचालन को शामिल करके एप्लिकेशन के आर्किटेक्चर में महत्वपूर्ण भूमिका निभाती है।
यदि आप भाषण संश्लेषण एपीआई को स्थानीय भंडारण के साथ जोड़ना चाहते हैं, उदाहरण के लिए, ऐसा करने के लिए यह सही जगह है। इस परत में शामिल हैं:
एडॉप्टर लेयर इन लेयर्स के बीच इंटरेक्शन को ऑर्केस्ट्रेट करने और उन्हें एक साथ बांधने के लिए जिम्मेदार है। इस परत में केवल इसके लिए जिम्मेदार मॉड्यूल होते हैं:
प्रेजेंटेशन लेयर यूजर इंटरफेस (यूआई) को रेंडर करने और एप्लिकेशन के साथ यूजर इंटरैक्शन को संभालने के लिए प्रभारी है। यह कार्यात्मक और इंटरैक्टिव यूआई बनाने के लिए एडॉप्टर, डोमेन और साझा परतों का लाभ उठाता है।
प्रस्तुति परत अपने घटकों को व्यवस्थित करने के लिए परमाणु डिजाइन पद्धति को नियोजित करती है, जिसके परिणामस्वरूप एक स्केलेबल और रखरखाव योग्य अनुप्रयोग होता है। हालाँकि, यह परत इस लेख का प्राथमिक फोकस नहीं होगी, क्योंकि यह क्लीन आर्किटेक्चर कार्यान्वयन के संदर्भ में मुख्य विषय नहीं है।
केंद्रीकृत उपयोगिताओं, कॉन्फ़िगरेशन और साझा तर्क जैसे सभी सामान्य तत्वों के लिए एक निर्दिष्ट स्थान आवश्यक है। हालाँकि, हम इस लेख में इस परत में बहुत गहराई से नहीं जाएंगे।
सामान्य घटकों को कैसे प्रबंधित किया जाता है और पूरे एप्लिकेशन में साझा किया जाता है, इसकी समझ प्रदान करने के लिए केवल उल्लेख करना उचित है।
अब, कोडिंग में गोता लगाने से पहले, परीक्षण पर चर्चा करना आवश्यक है। आपके आवेदन की विश्वसनीयता और शुद्धता सुनिश्चित करना महत्वपूर्ण है, और आर्किटेक्चर की प्रत्येक परत के लिए एक मजबूत परीक्षण रणनीति लागू करना महत्वपूर्ण है।
आर्किटेक्चर की प्रत्येक परत के लिए एक व्यापक परीक्षण रणनीति लागू करके, आप विकास के दौरान बगों को पेश करने की संभावना को कम करते हुए अपने आवेदन की विश्वसनीयता, शुद्धता और रखरखाव सुनिश्चित कर सकते हैं।
हालाँकि, यदि आप एक छोटा अनुप्रयोग बना रहे हैं, तो एडेप्टर परत पर एकीकरण परीक्षण पर्याप्त होना चाहिए।
ठीक है, अब जब आपको क्लीन आर्किटेक्चर की ठोस समझ हो गई है और शायद आपने इस पर अपनी राय भी बना ली है, तो चलिए थोड़ा और गहराई में जाते हैं और कुछ वास्तविक कोड तलाशते हैं।
ध्यान रखें कि मैं यहाँ केवल एक सरल उदाहरण प्रस्तुत कर रहा हूँ; हालाँकि, यदि आप अधिक विस्तृत उदाहरणों में रुचि रखते हैं, तो इस लेख की शुरुआत में उल्लिखित मेरे GitHub रिपॉजिटरी को बेझिझक एक्सप्लोर करें।
"वास्तविक जीवन" में, स्वच्छ वास्तुकला वास्तव में बड़े, उद्यम-स्तर के अनुप्रयोगों में चमकती है, जबकि यह छोटी परियोजनाओं के लिए अधिक हो सकती है। इसके साथ ही कहा, चलिए मुद्दे पर आते हैं।
एक उदाहरण के रूप में अपने आवेदन का उपयोग करके, मैं दिखाऊंगा कि किसी दिए गए शब्द के लिए शब्दकोश सुझाव लाने के लिए एपीआई कॉल कैसे करें। यह विशेष एपीआई समापन बिंदु दो वेबसाइटों को वेब स्क्रैप करके अर्थों और उदाहरणों की एक सूची प्राप्त करता है।
व्यावसायिक दृष्टिकोण से, यह समापन बिंदु "फाइंड वर्ड" दृश्य के लिए महत्वपूर्ण है, जो उपयोगकर्ताओं को एक विशिष्ट शब्द की खोज करने की अनुमति देता है। एक बार जब उपयोगकर्ता शब्द ढूंढ लेता है और लॉग इन कर लेता है, तो वे वेब-स्क्रैप की गई जानकारी को अपने नोशन डेटाबेस में जोड़ सकते हैं।
आरंभ करने के लिए, हमें एक फ़ोल्डर संरचना स्थापित करनी चाहिए जो उन परतों को सटीक रूप से दर्शाती है जिनकी हमने पहले चर्चा की थी। संरचना निम्नलिखित के समान होनी चाहिए:
client ├── adapter ├── api ├── domain ├── presentation ├── repository └── shared
क्लाइंट निर्देशिका कई परियोजनाओं में "src" फ़ोल्डर के समान उद्देश्य प्रदान करती है। इस विशिष्ट नेक्स्ट.जेएस प्रोजेक्ट में, मैंने फ्रंटएंड फोल्डर को "क्लाइंट" और बैकएंड फोल्डर को "सर्वर" नाम देने की परंपरा को अपनाया है।
यह दृष्टिकोण एप्लिकेशन के दो मुख्य घटकों के बीच स्पष्ट अंतर की अनुमति देता है।
आपकी परियोजना के लिए सही फ़ोल्डर संरचना का चयन करना वास्तव में एक महत्वपूर्ण निर्णय है जिसे विकास प्रक्रिया की शुरुआत में किया जाना चाहिए। जब संसाधनों को व्यवस्थित करने की बात आती है तो विभिन्न डेवलपर्स की अपनी प्राथमिकताएं और दृष्टिकोण होते हैं।
कुछ पृष्ठ नामों के आधार पर संसाधनों को समूहित कर सकते हैं, अन्य OpenAPI द्वारा उत्पन्न उपनिर्देशिका नामकरण परंपराओं का पालन कर सकते हैं, और फिर भी, दूसरों का मानना हो सकता है कि उनका आवेदन उन समाधानों में से किसी एक को वारंट करने के लिए बहुत छोटा है।
कुंजी एक ऐसी संरचना का चयन करना है जो संसाधनों के स्पष्ट और बनाए रखने योग्य संगठन को बनाए रखते हुए आपकी परियोजना की विशिष्ट आवश्यकताओं और पैमाने के अनुकूल हो।
मैं तीसरे समूह में हूँ, इसलिए मेरी संरचना इस तरह दिखती है:
client ├── adapter │ ├── local-storage │ ├── rest │ ├── speech-synthesis │ └── supabase ├── api │ ├── local-storage │ ├── rest │ ├── speech-synthesis │ └── supabase ├── domain │ ├── local-storage │ ├── rest │ ├── speech-synthesis │ ├── supabase └── repository ├── local-storage ├── rest ├── speech-synthesis └── supabase
मैंने इस लेख में साझा और प्रस्तुति परतों को छोड़ने का फैसला किया है, क्योंकि मेरा मानना है कि जो लोग अधिक गहराई में जाना चाहते हैं, वे अधिक जानकारी के लिए मेरे रिपॉजिटरी का संदर्भ ले सकते हैं। अब, कुछ कोड उदाहरणों के साथ आगे बढ़ते हैं, यह समझाने के लिए कि कैसे स्वच्छ वास्तुकला को एक दृश्यपटल अनुप्रयोग में लागू किया जा सकता है।
आइए हमारी आवश्यकताओं पर विचार करें। एक उपयोगकर्ता के रूप में, मैं उनके अर्थ और उदाहरणों सहित सुझावों की एक सूची प्राप्त करना चाहूंगा। इसलिए, एक एकल शब्दकोश सुझाव को निम्नानुसार प्रतिरूपित किया जा सकता है:
interface DictionarySuggestion { example: string; meaning: string; }
अब जब हमने एक शब्दकोश सुझाव का वर्णन किया है, तो यह उल्लेख करना महत्वपूर्ण है कि कभी-कभी वेब स्क्रैपिंग के माध्यम से प्राप्त शब्द भिन्न होता है या उपयोगकर्ता द्वारा टाइप किए जाने की तुलना में सही किया जाता है। इसे समायोजित करने के लिए, हम बाद में अपने ऐप में सही संस्करण का उपयोग करेंगे।
नतीजतन, हमें एक इंटरफ़ेस परिभाषित करने की आवश्यकता है जिसमें शब्दकोश सुझावों और शब्द सुधारों की एक सूची शामिल हो। अंतिम इंटरफ़ेस इस तरह दिखता है:
export interface DictionarySuggestions { suggestions: DictionarySuggestion[]; word: string; }
हम इस इंटरफ़ेस को निर्यात कर रहे हैं, इसलिए export
कीवर्ड शामिल किया गया है।
हमारे पास अपना मॉडल है, और अब इसे इस्तेमाल करने का समय आ गया है।
import { DictionarySuggestions } from './rest.models'; export interface RestRepository { getDictionarySuggestions: (word: string) => Promise<DictionarySuggestions | null>; }
इस बिंदु पर, सब कुछ स्पष्ट होना चाहिए। यह ध्यान रखना महत्वपूर्ण है कि हम यहां एपीआई पर चर्चा नहीं कर रहे हैं! रिपॉजिटरी की संरचना अपने आप में काफी सरल है: बस कुछ विधियों के साथ एक वस्तु, जहाँ प्रत्येक विधि एक विशिष्ट प्रकार के डेटा को अतुल्यकालिक रूप से लौटाती है।
कृपया ध्यान रखें कि रिपॉजिटरी हमेशा डोमेन मॉडल प्रारूप में डेटा लौटाती है।
अब, हमारे व्यापार नियम को उपयोग के मामले के रूप में परिभाषित करते हैं। कोड इस तरह दिखता है:
export type GetDictionarySuggestionsUseCaseUseCase = UseCaseWithSingleParamAndPromiseResult< string, DictionarySuggestions | null >; export const getDictionarySuggestionsUseCase = ( restRepository: RestRepository, ): GetDictionarySuggestionsUseCaseUseCase => ({ execute: (word) => restRepository.getDictionarySuggestions(word), });
नोट करने वाली पहली बात उपयोग के मामलों को परिभाषित करने के लिए उपयोग किए जाने वाले सामान्य प्रकारों की सूची है। इसे प्राप्त करने के लिए, मैंने डोमेन निर्देशिका में एक use-cases.types.ts
फ़ाइल बनाई:
domain ├── local-storage ├── rest ├── speech-synthesis ├── supabase └── use-cases.types.ts
यह मुझे मेरी उपनिर्देशिकाओं के बीच उपयोग के मामलों के प्रकारों को आसानी से साझा करने की अनुमति देता है। UseCaseWithSingleParamAndPromiseResult
की परिभाषा इस तरह दिखती है:
export interface UseCaseWithSingleParamAndPromiseResult<TParam, TResult> { execute: (param: TParam) => Promise<TResult>; }
यह दृष्टिकोण डोमेन स्तर पर उपयोग के मामलों की निरंतरता और पुन: प्रयोज्यता को बनाए रखने में मदद करता है।
आप सोच रहे होंगे कि हमें execute
कार्य की आवश्यकता क्यों है। यहां, हमारे पास एक कारखाना है जो वास्तविक उपयोग के मामले को लौटाता है।
यह डिज़ाइन पसंद इस तथ्य के कारण है कि हम रिपॉजिटरी कार्यान्वयन को सीधे उपयोग केस कोड में संदर्भित नहीं करना चाहते हैं, न ही हम चाहते हैं कि रेपो का उपयोग आयात द्वारा किया जाए। यह दृष्टिकोण हमें बाद में निर्भरता इंजेक्शन को आसानी से लागू करने की अनुमति देता है।
फ़ैक्टरी पैटर्न और execute
फ़ंक्शन का उपयोग करके, हम रिपॉजिटरी के कार्यान्वयन विवरण को उपयोग केस कोड से अलग रख सकते हैं, जिससे एप्लिकेशन की प्रतिरूपकता और रखरखाव में सुधार होता है।
यह दृष्टिकोण निर्भरता व्युत्क्रम सिद्धांत का अनुसरण करता है, जहां डोमेन परत किसी अन्य परत पर निर्भर नहीं होती है, और यह विभिन्न रिपॉजिटरी कार्यान्वयनों की अदला-बदली करने या एप्लिकेशन के आर्किटेक्चर को संशोधित करने के लिए अधिक लचीलेपन को सक्षम करती है।
सबसे पहले, आइए अपने इंटरफ़ेस को परिभाषित करें:
export interface RestApi { getDictionarySuggestions: (word: string) => Promise<AxiosResponse<DictionarySuggestions>>; }
जैसा कि आप देख सकते हैं, इंटरफ़ेस में इस फ़ंक्शन की परिभाषा रिपॉजिटरी में बारीकी से मिलती जुलती है। चूंकि डोमेन प्रकार पहले से ही प्रतिक्रिया का वर्णन करता है, उसी प्रकार को फिर से बनाने की कोई आवश्यकता नहीं है।
यह ध्यान रखना महत्वपूर्ण है कि हमारा एपीआई कच्चा डेटा लौटाता है, यही वजह है कि हम पूरा AxiosResponse<DictionarySuggestions>
लौटाते हैं। ऐसा करके, हम एपीआई और डोमेन परतों के बीच एक स्पष्ट अलगाव बनाए रखते हैं, जिससे डेटा प्रबंधन और परिवर्तन में अधिक लचीलेपन की अनुमति मिलती है।
इस एपीआई का कार्यान्वयन इस तरह दिखता है:
export const getRestApi = (axiosInstance: AxiosInstance): RestApi => ({ getDictionarySuggestions: async (word: string) => { const encodedCurrentDate = encodeURIComponent(word); const response = await axiosInstance.get( `${RestEndpoints.GET_DICTIONARY_SUGGESTIONS}?word=${encodedCurrentDate}`, ); return response; } });
इस बिंदु पर, चीजें और अधिक दिलचस्प हो जाती हैं। चर्चा करने वाला पहला महत्वपूर्ण पहलू हमारे axiosInstance
का इंजेक्शन है। यह हमारे कोड को बहुत लचीला बनाता है और हमें आसानी से ठोस परीक्षण करने में सक्षम बनाता है। यह वह स्थान भी है जहां हम क्वेरी पैरामीटर के एन्कोडिंग या पार्सिंग को हैंडल करते हैं।
हालाँकि, आप यहाँ अन्य क्रियाएँ भी कर सकते हैं, जैसे कि इनपुट स्ट्रिंग को ट्रिम करना। axiosInstance
को इंजेक्ट करके, हम चिंताओं का स्पष्ट पृथक्करण बनाए रखते हैं और यह सुनिश्चित करते हैं कि API कार्यान्वयन विभिन्न परिदृश्यों या बाहरी सेवाओं में परिवर्तनों के अनुकूल है।
जैसा कि हमारा इंटरफ़ेस पहले से ही डोमेन द्वारा परिभाषित किया गया है, हमें बस इतना करना है कि हम अपने रिपॉजिटरी को लागू करें। तो, अंतिम कार्यान्वयन इस तरह दिखता है:
export const getRestRepository = (restApi: RestApi): RestRepository => ({ getDictionarySuggestions: async (word) => { const { data } = await restApi.getDictionarySuggestions(word); if (!data?.suggestions?.length) { return null; } return formatDictionarySuggestions(data); } });
उल्लेख करने के लिए एक महत्वपूर्ण पहलू एपीआई से संबंधित है। हमारा getRestRepository
हमें पहले से परिभाषित restApi
पास करने की अनुमति देता है। यह फायदेमंद है क्योंकि, जैसा कि पहले उल्लेख किया गया है, यह आसान परीक्षण की अनुमति देता है। हम संक्षेप में formatDictionarySuggestions
जांच कर सकते हैं:
export const formatDictionarySuggestions = ({ suggestions, word, }: DictionarySuggestions): DictionarySuggestions => { const cleanedWord = cleanUpString(word); const cleanedSuggestions = suggestions.map((_suggestion) => { const cleanedMeaning = cleanUpString(_suggestion.meaning); const cleanedExample = cleanUpString(_suggestion.example); return { meaning: cleanedMeaning, example: cleanedExample, }; }); return { word: cleanedWord, suggestions: cleanedSuggestions, }; };
यह ऑपरेशन हमारे डोमेन DictionarySuggestions
मॉडल को एक तर्क के रूप में लेता है और एक स्ट्रिंग क्लीनअप करता है, जिसका अर्थ है अनावश्यक रिक्त स्थान, लाइन ब्रेक, टैब और कैपिटलाइज़ेशन को हटाना। यह बहुत सीधा है, जिसमें कोई छिपी हुई जटिलता नहीं है।
ध्यान देने वाली एक महत्वपूर्ण बात यह है कि इस बिंदु पर आपको अपने एपीआई कार्यान्वयन के बारे में चिंता करने की आवश्यकता नहीं है। एक अनुस्मारक के रूप में, रिपॉजिटरी हमेशा डोमेन मॉडल में डेटा लौटाती है! यह अन्यथा नहीं हो सकता क्योंकि ऐसा करने से निर्भरता व्युत्क्रम का सिद्धांत टूट जाएगा।
और अभी के लिए, हमारी डोमेन परत इसके बाहर परिभाषित किसी भी चीज़ पर निर्भर नहीं करती है।
इस बिंदु पर, सब कुछ लागू किया जाना चाहिए और निर्भरता इंजेक्शन के लिए तैयार होना चाहिए। यहाँ बाकी मॉड्यूल का अंतिम कार्यान्वयन है:
import { getRestRepository } from '@repository/rest/rest.repository'; import { getRestApi } from '@api/rest/rest.api'; import { getDictionarySuggestionsUseCase } from '@domain/rest/rest.use-cases'; import { axiosInstance } from '@shared/axios.instance'; const restApi = getRestApi(axiosInstance); const restRepository = getRestRepository(restApi); export const restModule = { getDictionarySuggestions: getDictionarySuggestionsUseCase(restRepository).execute, };
यह सही है! हम किसी विशिष्ट ढांचे से बंधे बिना स्वच्छ वास्तुकला सिद्धांतों को लागू करने की प्रक्रिया से गुजरे हैं। यह दृष्टिकोण सुनिश्चित करता है कि हमारा कोड अनुकूलनीय है, जिससे जरूरत पड़ने पर फ्रेमवर्क या लाइब्रेरी को बदलना आसान हो जाता है।
जब परीक्षण की बात आती है, तो रिपॉजिटरी की जाँच करना यह समझने का एक शानदार तरीका है कि इस आर्किटेक्चर में परीक्षण कैसे लागू और व्यवस्थित किए जाते हैं।
क्लीन आर्किटेक्चर में एक ठोस नींव के साथ, आप व्यापक परीक्षण लिख सकते हैं जो विभिन्न परिदृश्यों को कवर करते हैं, जिससे आपका एप्लिकेशन अधिक मजबूत और विश्वसनीय हो जाता है।
जैसा कि प्रदर्शित किया गया है, स्वच्छ वास्तुकला सिद्धांतों का पालन करना और चिंताओं को अलग करना एक बनाए रखने योग्य, मापनीय और परीक्षण योग्य अनुप्रयोग संरचना की ओर ले जाता है।
यह दृष्टिकोण अंततः आपके आवेदन की दीर्घकालिक सफलता सुनिश्चित करते हुए, नई सुविधाओं, रिफैक्टर कोड को जोड़ना और एक परियोजना पर एक टीम के साथ काम करना आसान बनाता है।
उदाहरण एप्लिकेशन में, प्रस्तुति परत के लिए रिएक्ट का उपयोग किया जाता है। एडॉप्टर डायरेक्टरी में, एक अतिरिक्त फाइल होती है, जिसे hooks.ts
कहा जाता है, जो बाकी मॉड्यूल के साथ इंटरेक्शन को हैंडल करती है। इस फ़ाइल की सामग्री इस प्रकार है:
import { restModule } from '@adapter/rest/rest.module'; import { useAxios } from '@shared/hooks'; export const useDictionarySuggestions = () => { const { data, error, isLoading, mutate } = useAxios(restModule.getDictionarySuggestions); return { dictionarySuggestions: data, getDictionarySuggestions: mutate, dictionarySuggestionsError: error, isDictionarySuggestionsLoading: isLoading, }; };
यह कार्यान्वयन प्रस्तुति परत के साथ काम करना अविश्वसनीय रूप से आसान बनाता है। useDictionarySuggestions
हुक का उपयोग करके, प्रस्तुति परत को डेटा मैपिंग या अन्य जिम्मेदारियों के प्रबंधन के बारे में चिंता करने की ज़रूरत नहीं है जो इसके प्राथमिक कार्य से संबंधित नहीं हैं।
चिंताओं का यह पृथक्करण स्वच्छ वास्तुकला के सिद्धांतों को बनाए रखने में मदद करता है, जिससे अधिक प्रबंधनीय और रखरखाव योग्य कोड प्राप्त होता है।
सबसे पहले और सबसे महत्वपूर्ण, मैं आपको प्रदान किए गए GitHub रेपो से कोड में गोता लगाने और इसकी संरचना का पता लगाने के लिए प्रोत्साहित करता हूं।
इसके अलावा आप क्या कर सकते हैं? आसमान की हद! यह सब आपकी विशिष्ट डिजाइन आवश्यकताओं पर निर्भर करता है। उदाहरण के लिए, आप डेटा स्टोर (Redux, MobX, या यहां तक कि कुछ कस्टम - इससे कोई फर्क नहीं पड़ता) को शामिल करके डेटा स्तर को लागू करने पर विचार कर सकते हैं।
वैकल्पिक रूप से, आप परतों के बीच विभिन्न संचार विधियों के साथ प्रयोग कर सकते हैं, जैसे बैकएंड के साथ अतुल्यकालिक संचार को संभालने के लिए RxJS का उपयोग करना, जिसमें मतदान, पुश सूचनाएँ, या सॉकेट शामिल हो सकते हैं (अनिवार्य रूप से, किसी भी डेटा स्रोत के लिए तैयार किया जा रहा है)।
संक्षेप में, जब तक आप स्तरित वास्तुकला को बनाए रखते हैं और उलटा निर्भरता के सिद्धांत का पालन करते हैं, तब तक कृपया अन्वेषण और प्रयोग करने के लिए स्वतंत्र महसूस करें। हमेशा सुनिश्चित करें कि डोमेन आपके डिजाइन के मूल में है।
ऐसा करके, आप एक लचीली और अनुरक्षणीय अनुप्रयोग संरचना तैयार करेंगे जो विभिन्न परिदृश्यों और आवश्यकताओं के अनुकूल हो सकती है।
इस लेख में, हमने रिएक्ट का उपयोग करके निर्मित भाषा-शिक्षण एप्लिकेशन के संदर्भ में स्वच्छ वास्तुकला की अवधारणा में तल्लीन किया है।
हमने एक स्तरित वास्तुकला को बनाए रखने और उलटा निर्भरता के सिद्धांत का पालन करने के साथ-साथ चिंताओं को अलग करने के लाभों पर प्रकाश डाला।
क्लीन आर्किटेक्चर का एक महत्वपूर्ण लाभ इसकी क्षमता है जो आपको किसी विशिष्ट ढांचे से बंधे बिना आपके आवेदन के इंजीनियरिंग पहलू पर ध्यान केंद्रित करने देता है। यह लचीलापन आपको अपने एप्लिकेशन को विभिन्न परिदृश्यों और आवश्यकताओं के अनुकूल बनाने की अनुमति देता है।
हालाँकि, इस दृष्टिकोण में कुछ कमियाँ हैं। कुछ मामलों में, एक सख्त वास्तुशिल्प पैटर्न का पालन करने से बॉयलरप्लेट कोड में वृद्धि हो सकती है या परियोजना संरचना में अतिरिक्त जटिलता हो सकती है।
इसके अतिरिक्त, दस्तावेज़ीकरण पर कम निर्भर होना लाभ और हानि दोनों हो सकता है - जबकि यह अधिक स्वतंत्रता और रचनात्मकता की अनुमति देता है, इसके परिणामस्वरूप टीम के सदस्यों के बीच भ्रम या गलत संचार भी हो सकता है।
इन संभावित चुनौतियों के बावजूद, क्लीन आर्किटेक्चर को लागू करना अत्यधिक फायदेमंद हो सकता है, विशेष रूप से रिएक्ट के संदर्भ में, जहां सार्वभौमिक रूप से स्वीकृत आर्किटेक्चरल पैटर्न नहीं है।
वर्षों के संघर्ष के बाद इसे संबोधित करने के बजाय किसी परियोजना की शुरुआत में अपनी वास्तुकला पर विचार करना आवश्यक है।
कार्यशील स्वच्छ वास्तुकला के वास्तविक जीवन के उदाहरण का पता लगाने के लिए, बेझिझक मेरी रिपॉजिटरी को देखें
वाह, यह शायद मेरे द्वारा लिखा गया अब तक का सबसे लंबा लेख है। यह अविश्वसनीय लगता है!