मैं NestJS जैसे बड़े फ्रेमवर्क का बड़ा प्रशंसक नहीं हूं; मुझे अपने सॉफ़्टवेयर को हल्के ढंग से तय की गई संरचना के साथ अपनी इच्छानुसार बनाने की स्वतंत्रता हमेशा पसंद रही है। लेकिन NestJS का परीक्षण करते समय जो चीज़ मुझे पसंद आई वह थी डिपेंडेंसी इंजेक्शन।
निर्भरता इंजेक्शन (डीआई) एक डिजाइन पैटर्न है जो हमें अपनी कक्षाओं से निर्भरता बनाने और प्रबंधित करने की जिम्मेदारी को हटाकर शिथिल युग्मित कोड विकसित करने की अनुमति देता है। यह पैटर्न रखरखाव योग्य, परीक्षण योग्य और स्केलेबल एप्लिकेशन लिखने के लिए महत्वपूर्ण है। टाइपस्क्रिप्ट इकोसिस्टम में, टीएसिरिंज एक शक्तिशाली और हल्के निर्भरता इंजेक्शन कंटेनर के रूप में सामने आता है जो इस प्रक्रिया को सरल बनाता है।
TSyringe टाइपस्क्रिप्ट/जावास्क्रिप्ट अनुप्रयोगों के लिए एक हल्का निर्भरता इंजेक्शन कंटेनर है। Microsoft द्वारा अपने GitHub (https://github.com/microsoft/tsyringe) पर बनाए रखा गया, यह कंस्ट्रक्टर इंजेक्शन करने के लिए डेकोरेटर का उपयोग करता है। फिर, यह एक टोकन के आधार पर निर्भरता को संग्रहीत करने के लिए कंट्रोल कंटेनर के व्युत्क्रम का उपयोग करता है जिसे आप किसी उदाहरण या मूल्य के लिए विनिमय कर सकते हैं।
टीएसिरिंज में गोता लगाने से पहले, आइए संक्षेप में जानें कि निर्भरता इंजेक्शन क्या है और यह महत्वपूर्ण क्यों है।
निर्भरता इंजेक्शन एक ऐसी तकनीक है जहां कोई वस्तु अपनी निर्भरताएं स्वयं बनाने के बजाय बाहरी स्रोतों से प्राप्त करती है। यह दृष्टिकोण कई लाभ प्रदान करता है:
सबसे पहले, आइए आपके टाइपस्क्रिप्ट प्रोजेक्ट में TSyringe सेट करें:
npm install tsyringe reflect-metadata
अपने tsconfig.json में, सुनिश्चित करें कि आपके पास निम्नलिखित विकल्प हैं:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
अपने एप्लिकेशन के प्रवेश बिंदु पर प्रतिबिंबित-मेटाडेटा आयात करें:
import "reflect-metadata";
उदाहरण के लिए, आपके एप्लिकेशन का प्रवेश बिंदु Next.js 13 पर रूट लेआउट है, या यह एक छोटे एक्सप्रेस एप्लिकेशन में मुख्य फ़ाइल हो सकता है।
आइए परिचय से उदाहरण लें और टीएसिरिंज चीनी जोड़ें:
आइए एडॉप्टर से शुरू करते हैं।
// @/adapters/userAdapter.ts import { injectable } from "tsyringe" @injectable() class UserAdapter { constructor(...) {...} async fetchByUUID(uuid) {...} }
@injectable() डेकोरेटर पर ध्यान दें? टीएसिरिंज को यह बताना है कि इस क्लास को रनटाइम पर इंजेक्ट किया जा सकता है।
इसलिए मेरी सेवा हमारे द्वारा अभी बनाए गए एडाप्टर का उपयोग कर रही है। आइए उस एडॉप्टर को मेरी सेवा में इंजेक्ट करें।
// @/core/user/user.service.ts import { injectable, inject } from "tsyringe" ... @injectable() class UserService { constructor(@inject('UserAdapter') private readonly userAdapter: UserAdapter) {} async fetchByUUID(uuid: string) { ... const { data, error } = await this.userAdapter.fetchByUUID(uuid); ... } }
यहां मैंने @इंजेक्टेबल डेकोरेटर का भी उपयोग किया है क्योंकि सेवा को मेरे कमांड क्लास में इंजेक्ट किया जाएगा, लेकिन मैंने कंस्ट्रक्टर पैराम्स में @इंजेक्ट डेकोरेटर भी जोड़ा है। यह डेकोरेटर टीएसरिंज को रनटाइम पर यूजरएडाप्टर प्रॉपर्टी के लिए टोकन यूजरएडाप्टर का उदाहरण या मूल्य देने के लिए कहता है।
और अंतिम लेकिन महत्वपूर्ण बात, मेरे कोर की जड़: कमांड क्लास (अक्सर गलत तरीके से यूज़केस कहा जाता है)।
// @/core/user/user.commands.ts import { inject } from "tsyringe" ... @injectable() class UserCommands { constructor(@inject('UserService') private readonly userService: UserService) {} async fetchByUUID(uuid) { ... const { data, error } = this.userService.fetchByUUID(uuid); ... } }
इस बिंदु पर, हमने टीएसिरिंज को बताया है कि क्या इंजेक्ट किया जाएगा और कंस्ट्रक्टर में क्या इंजेक्ट किया जाएगा। लेकिन हमने अभी भी निर्भरता को संग्रहीत करने के लिए अपने कंटेनर नहीं बनाए हैं। हम इसे दो तरीकों से कर सकते हैं:
हम अपनी निर्भरता इंजेक्शन रजिस्ट्री के साथ एक फ़ाइल बना सकते हैं:
// @/core/user/user.dependencies.ts import { container } from "tsyringe" ... container.register("UserService", {useClass: UserService}) // associate the UserService with the token "UserService" container.register("UserAdapter", {useClass: UserAdapter}) // associate the UserAdapter with the token "UserAdapter" export { container }
लेकिन हम @registry डेकोरेटर का भी उपयोग कर सकते हैं।
// @/core/user/user.commands.ts import { inject, registry, injectable } from "tsyringe" ... @injectable() @registry([ { token: 'UserService', useClass: UserService }, { token: 'UserAdapter', useClass: UserAdapter }, ]) export class UserCommands { constructor(@inject('UserService') private readonly userService: UserService) {} async fetchByUUID(uuid) { ... const { data, error } = this.userService.fetchByUUID(uuid); ... } } container.register("UserCommands", { useClass: UserCommands}) export { container }
दोनों तरीकों के फायदे और नुकसान हैं, लेकिन दिन के अंत में, यह स्वाद का मामला है।
अब जब हमारा कंटेनर हमारी निर्भरताओं से भर गया है, तो हम कंटेनर की रिज़ॉल्यूशन विधि का उपयोग करके आवश्यकतानुसार उन्हें कंटेनर से प्राप्त कर सकते हैं।
import { container, UserCommands } from "@/core/user/user.commands" ... const userCommands = container.resolve("UserCommands") await userCommands.fetchByUUID(uuid) ...
यह उदाहरण बहुत सरल है क्योंकि प्रत्येक वर्ग केवल दूसरे पर निर्भर करता है, लेकिन हमारी सेवाएं कई पर निर्भर हो सकती हैं, और निर्भरता इंजेक्शन वास्तव में सब कुछ व्यवस्थित रखने में मदद करेगा।
पर रुको! मुझे ऐसे मत छोड़ो! परीक्षणों के बारे में क्या ख्याल है?
हमारे इंजेक्शन नकली वस्तुओं को सीधे हमारी निर्भरता में भेजकर हमारे कोड का परीक्षण करने में भी हमारी मदद कर सकते हैं। आइए एक कोड उदाहरण देखें:
import { container, UserCommands } from "@/core/user/user.commands" describe("test ftw", () => { let userAdapterMock: UserAdapterMock let userCommands: UserCommands beforeEach(() => { userAdapterMock = new UserAdapter() container.registerInstance("UserAdapter", userAdapter) userCommands = container.resolve ("UserCommands") }); ... });
अब UserAdapter टोकन में एक मॉक शामिल है जिसे आश्रित वर्गों में इंजेक्ट किया जाएगा।
नामकरण के लिए टोकन का उपयोग करें: इंजेक्शन टोकन के लिए स्ट्रिंग अक्षर का उपयोग करने के बजाय, निरंतर टोकन बनाएं:
export const USER_REPOSITORY_TOKEN = Symbol("UserRepository");
स्कोप्ड कंटेनर: वेब अनुप्रयोगों में अनुरोध-स्कोप्ड निर्भरता के लिए स्कोप्ड कंटेनर का उपयोग करें।
DI का अत्यधिक उपयोग न करें: हर चीज को इंजेक्ट करने की जरूरत नहीं है। क्रॉस-कटिंग चिंताओं और कॉन्फ़िगर करने योग्य निर्भरताओं के लिए DI का उपयोग करें।
यदि आप यहां तक आए हैं, तो मैं आपको पढ़ने के लिए धन्यवाद कहना चाहता हूं। मुझे आशा है कि आपको यह लेख शिक्षाप्रद लगा होगा। निर्भरता इंजेक्शन और वास्तुशिल्प पैटर्न लागू करते समय हमेशा अपने प्रोजेक्ट की विशिष्ट आवश्यकताओं पर विचार करना याद रखें।
पसंद और टिप्पणी प्रतिक्रिया सुधार करने के सर्वोत्तम तरीके हैं।
हैप्पी कोडिंग!
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3