JavaScript में SOLID सिद्धांत: सिद्धांत से Node.js पर व्यवहार तक
SOLID — रॉबर्ट मार्टिन (अंकल बॉब) द्वारा प्रतिपादित ऑब्जेक्ट-ओरिएंटेड डिज़ाइन के पाँच मूलभूत सिद्धांत हैं। ये सिद्धांत लचीला, रखरखाव योग्य और स्केलेबल कोड बनाने में मदद करते हैं। हालाँकि कई लोग SOLID को क्लासिकल OOP भाषाओं (Java, C#) से जोड़ते हैं, लेकिन ये JavaScript में भी पूरी तरह से लागू होते हैं, विशेषकर Node.js पर विकास करते समय। इस लेख में हम प्रत्येक सिद्धांत को विशिष्ट उदाहरणों के साथ समझेंगे।
एकल उत्तरदायित्व सिद्धांत (Single Responsibility Principle, SRP)
SRP कहता है: “एक क्लास (या मॉड्यूल) में बदलाव का केवल एक ही कारण होना चाहिए”। इसका मतलब है कि प्रत्येक मॉड्यूल एक विशिष्ट कार्य के लिए जिम्मेदार है।
खराब उदाहरण (SRP का उल्लंघन):
class UserService { createUser(data) { /* उपयोगकर्ता बनाने का तर्क */ } sendWelcomeEmail(email) { /* ईमेल भेजना */ } logActivity(action) { /* लॉगिंग */ }}यहाँ एक क्लास उपयोगकर्ताओं के साथ काम करने, ईमेल भेजने और लॉगिंग के लिए जिम्मेदार है। यदि लॉग का प्रारूप बदलता है, तो UserService को बदलना होगा — जबकि इसका मुख्य कार्य नहीं बदला।
अच्छा उदाहरण (SRP का पालन):
class UserRepository { createUser(data) { /* केवल DB के साथ काम */ }}
class EmailService { sendWelcomeEmail(email) { /* केवल भेजना */ }}
class Logger { logActivity(action) { /* केवल लॉगिंग */ }}
class UserService { constructor(userRepo, emailService, logger) { this.userRepo = userRepo; this.emailService = emailService; this.logger = logger; } createUser(data) { const user = this.userRepo.createUser(data); this.emailService.sendWelcomeEmail(user.email); this.logger.logActivity('User created'); return user; }}अब प्रत्येक क्लास अपने जिम्मेदारी के क्षेत्र के लिए जिम्मेदार है। उन्हें UserService में संयोजित करके, हम लचीलापन और परिवर्तनों का अलगाव प्राप्त करते हैं।
खुला/बंद सिद्धांत (Open/Closed Principle, OCP)
OCP कहता है: “सॉफ़्टवेयर संस्थाएँ विस्तार के लिए खुली होनी चाहिए, लेकिन संशोधन के लिए बंद होनी चाहिए”। यानी हमें मौजूदा कोड को बदले बिना नई कार्यक्षमता जोड़ने में सक्षम होना चाहिए।
खराब उदाहरण (OCP का उल्लंघन):
class PaymentProcessor { processPayment(type, amount) { if (type === 'card') { /* कार्ड प्रोसेसिंग */ } else if (type === 'paypal') { /* PayPal प्रोसेसिंग */ } // नया प्रकार जोड़ने पर — इस विधि को बदलना होगा }}अच्छा उदाहरण (OCP का पालन):
class PaymentStrategy { pay(amount) { throw new Error('Must be implemented'); }}
class CardPayment extends PaymentStrategy { pay(amount) { console.log(`Paid ${amount} via Card`); }}
class PayPalPayment extends PaymentStrategy { pay(amount) { console.log(`Paid ${amount} via PayPal`); }}
class PaymentProcessor { constructor(strategy) { this.strategy = strategy; } processPayment(amount) { this.strategy.pay(amount); }}
// उपयोगconst cardPayment = new PaymentProcessor(new CardPayment());cardPayment.processPayment(100);
const paypalPayment = new PaymentProcessor(new PayPalPayment());paypalPayment.processPayment(200);अब भुगतान का नया तरीका जोड़ने के लिए, बस PaymentStrategy से विरासत में मिली एक नई क्लास बनाएँ और इसे PaymentProcessor में पास करें। मूल कोड नहीं बदलता।
बारबरा लिस्कोव प्रतिस्थापन सिद्धांत (Liskov Substitution Principle, LSP)
LSP कहता है: “प्रोग्राम में ऑब्जेक्ट्स को उनके उपप्रकारों के उदाहरणों से प्रतिस्थापित किया जा सकना चाहिए, बिना प्रोग्राम के निष्पादन की शुद्धता को बदले”। दूसरे शब्दों में, यदि आपके पास एक आधार है