परिचय: कोड की कठोर युग्मन की समस्या
\n\nप्रत्येक Node.js डेवलपर को देर-सबेर ऐसी स्थिति का सामना करना पड़ता है जहाँ एक मॉड्यूल में बदलाव दर्जनों अन्य मॉड्यूल में संशोधनों की श्रृंखला खींच लाता है। यह विशेष रूप से यूनिट टेस्ट लिखते समय स्पष्ट होता है: एक सेवा का परीक्षण करने के लिए, डेटाबेस, बाहरी API और कैश को शुरू करना पड़ता है। समस्या की जड़ है कठोर युग्मन (tight coupling)।
\n\nडिपेंडेंसी इंजेक्शन (DI) एक डिज़ाइन पैटर्न है जो इस समस्या को हल करता है। क्लास या फ़ंक्शन द्वारा अपनी डिपेंडेंसी स्वयं बनाने के बजाय, वे उन्हें बाहर से प्राप्त करते हैं। यह कोड को लचीला, परीक्षण योग्य और SOLID के डिपेंडेंसी इनवर्ज़न प्रिंसिपल (Dependency Inversion Principle) के अनुरूप बनाता है।
\n\nइस लेख में, हम व्यवहार में DI को समझेंगे: सरल मैन्युअल इंजेक्शन से लेकर Node.js में पेशेवर कंटेनरों के उपयोग तक।
\n\n1. मैन्युअल डिपेंडेंसी इंजेक्शन: पहला कदम
\n\nखराब दृष्टिकोण: कठोर युग्मन
\nईमेल भेजने के लिए एक विशिष्ट सेवा उदाहरण पर विचार करें:
\n\n// userService.js\nconst emailService = require('./emailService');\n\nclass UserService {\n async registerUser(email) {\n // विशिष्ट कार्यान्वयन पर कठोर निर्भरता\n await emailService.sendWelcomeEmail(email);\n console.log('उपयोगकर्ता पंजीकृत');\n }\n}\n\nmodule.exports = UserService;\n\nसमस्या: UserService का परीक्षण करते समय emailService को मॉक से बदलना असंभव है। proxyquire या jest.mock जैसे जटिल उपकरणों का उपयोग करना होगा।
अच्छा दृष्टिकोण: कंस्ट्रक्टर के माध्यम से इंजेक्शन
\nसेवा को फिर से लिखें, कंस्ट्रक्टर के माध्यम से डिपेंडेंसी पास करें:
\n\n// userService.js\nclass UserService {\n constructor(emailService) {\n this.emailService = emailService;\n }\n\n async registerUser(email) {\n await this.emailService.sendWelcomeEmail(email);\n console.log('उपयोगकर्ता पंजीकृत');\n }\n}\n\nmodule.exports = UserService;\n\nअब हम आसानी से सेवा का परीक्षण कर सकते हैं:
\n\n// userService.test.js\nconst UserService = require('./userService');\n\nconst mockEmailService = {\n sendWelcomeEmail: jest.fn().mockResolvedValue(true)\n};\n\ntest('स्वागत ईमेल भेजना चाहिए', async () => {\n const service = new UserService(mockEmailService);\n await service.registerUser('test@test.com');\n expect(mockEmailService.sendWelcomeEmail).toHaveBeenCalledWith('test@test.com');\n});\n\n2. JavaScript में डिपेंडेंसी इंजेक्शन के प्रकार
\n\nJavaScript/Node.js में डिपेंडेंसी इंजेक्ट करने के तीन मुख्य तरीके हैं:
\n\n2.1. कंस्ट्रक्टर के माध्यम से इंजेक्शन
\nसबसे सामान्य और पूर्वानुमानित तरीका। ऑब्जेक्ट बनाते समय डिपेंडेंसी पास की जाती हैं:
\n\nclass DatabaseService {\n constructor(connection) {\n this.connection = connection;\n }\n\n async query(sql) {\n return this.connection.execute(sql);\n }\n}\n\n// उपयोग\nconst db = new DatabaseService(new MySQLConnection());\n\n2.2. सेटर के माध्यम से इंजेक्शन
\nतब उपयुक्त जब ऑब्जेक्ट के संचालन के दौरान डिपेंडेंसी बदली जा सकती है:
\n\nclass LoggerService {\n setLogger(logger) {\n this.logger = logger;\n }\n\n log(message) {\n this.logger.write(`[${new Date().toISOString()}] ${message}`);\n }\n}\n\nconst logger = new LoggerService();\nlogger.setLogger(new ConsoleLogger());\nlogger.log('एप्लिकेशन शुरू');\n\n2.3. फ़ंक्शन पैरामीटर के माध्यम से इंजेक्शन
\nकार्यात्मक दृष्टिकोण और उपयोगिताओं के लिए आदर्श:
\n\nfunction sendNotification(user, emailService, smsService) {\n emailService.send(user.email, 'सूचना');\n smsService.send(user.phone, 'सूचना');\n}\n\n// परीक्षण\nconst mockEmail = { send: jest.fn() };\nconst mockSms = { send: jest.fn() };\nsendNotification({ email: 'a@b.com', phone: '123' }, mockEmail, mockSms);\n\n