SRP (Single Responsibility Principle) — SOLID का पहला सिद्धांत, जो बताता है: प्रत्येक क्लास या मॉड्यूल में बदलाव का ठीक एक ही कारण होना चाहिए। यह सिद्धांत रॉबर्ट मार्टिन ने पुस्तक Clean Architecture (2017) में तैयार किया और मॉड्यूलर डिजाइन की नींव बन गया। इस पुस्तक के अनुसार, SRP लागू करना सीधे घटकों के युग्मन को कम करता है और कार्यक्षमता में बदलाव करते समय श्रृंखलागत परिवर्तनों को समाप्त करता है।
मुख्य मुद्दे
SRP (Single Responsibility Principle) एकल जिम्मेदारी का सिद्धांत है, जो बताता है: प्रत्येक क्लास या मॉड्यूल में बदलाव का ठीक एक ही कारण होना चाहिए। इसका मतलब यह नहीं है कि एक क्लास को ठीक एक ही संचालन करना चाहिए। यह एक अक्टर के प्रति एक जिम्मेदारी में एकजुट संबंधित कार्रवाइयों के समूह के बारे में है।
रॉबर्ट मार्टिन ने SRP को अक्टर के संदर्भ में पुनर्निर्मित किया: एक क्लास को केवल एक हितधारी या व्यक्तियों के एक समूह के अनुरोध पर ही बदलना चाहिए। यदि दो अलग-अलग अक्टर एक ही क्लास में बदलाव की मांग करते हैं, तो जिम्मेदारी गलत ढंग से विभाजित है।
उदाहरण के लिए, एक Employee क्लास जो एक साथ वेतन की गणना (लेखा विभाग का अनुरोध) और रिपोर्ट निर्माण (प्रबंधन का अनुरोध) करता है, SRP का उल्लंघन करता है। गणना नियमों में बदलाव रिपोर्ट निर्माण को प्रभावित कर सकता है और इसके विपरीत भी।
एक मॉड्यूल में बदलाव का एक और केवल एक ही कारण होना चाहिए। बदलाव का कारण एक अक्टर द्वारा निर्धारित किया जाता है — एक व्यक्ति या प्रणाली जो आवश्यकता की शुरुआत करती है। यदि अलग-अलग अक्टरों की आवश्यकताएं एक मॉड्यूल में परिवर्तन का कारण बनती हैं, तो मॉड्यूल SRP का उल्लंघन करता है।
अक्टर की अवधारणा SRP को एक अमूर्त अनुशंसा के बजाय आर्किटेक्चरल विश्लेषण का एक व्यावहारिक उपकरण बनाती है। सिस्टम डिजाइन करते समय, बस पूछें: “यह कोड कौन बदलने के लिए कहेगा?” — यदि जवाब में एक से अधिक हितधारी हैं, तो जिम्मेदारी को अलग किया जाना चाहिए।
एकल जिम्मेदारी उन विधियों को समूहीकृत करके लागू की जाती है जो एक कारण से बदलते हैं। एक क्लास सभी अवसरों के लिए एक छुरी के बजाय संबंधित तर्क का एक संग्रह बिंदु बन जाता है। यह कोड समझ को सरल बनाता है: डिवेलपर क्लास देखता है और तुरंत इसका उद्देश्य समझ जाता है।
SRP का तंत्र एकल परिवर्तन अक्ष नियम पर आधारित है। यदि कार्यक्षमता स्वतंत्र कारणों से बदल सकती है, तो इसे अलग क्लासों में निकाला जाना चाहिए। इन क्लासों के बीच के संबंध कंपोजीशन या डिलीगेशन के माध्यम से बनाए जाते हैं।
SRP का उल्लंघन गॉड ऑब्जेक्ट्स में प्रगट होता है — ऐसी क्लासें जिनमें दर्जनों विधियाँ होती हैं जो विभिन्न डेटा के साथ काम करती हैं। ऐसी क्लास का परीक्षण करना मुश्किल है — एक विधि का परीक्षण करने के लिए अन्य सभी के लिए वातावरण सेट करना होता है। एक जिम्मेदारी को बदलने से दूसरी टूट सकती है, जिससे कोड नाज़ुक हो जाता है।
व्यावहारिक रूप से, SRP डिवेलपर्स को “यह कोड कहाँ है?” प्रश्न का उत्तर देने में मदद करता है। यदि प्रत्येक जिम्मेदारी अपने क्लास में अलग है, तो सही फ़ाइल ढूंढने में सेकंड लगते हैं। MVVM आर्किटेक्चर वाले Android प्रोजेक्ट में, इसका मतलब है कि UserViewModel केवल उपयोगकर्ता स्क्रीन स्थिति के लिए जिम्मेदार है, और UserRepository डेटा प्राप्ति के लिए। कैशिंग तर्क की तलाश करने वाला डिवेलपर UserCacheRepository में जाता है, ViewModel में नहीं। ऐसा कोड संगठन टीम के नए सदस्यों को जल्दी शामिल करता है और रिफैक्टरिंग के दौरान त्रुटियों की संख्या कम करता है।
मोबाइल विकास कोड मॉड्यूलेरिटी पर विशेष मांग रखता है। Android Fragment या iOS ViewController अक्सर तर्क का एक चुम्बक बन जाता है: टैप हैंडलिंग, API कॉल, रिस्पंस पार्सिंग, UI अपडेट — सब एक ही क्लास में। SRP को इन जिम्मेदारियों को अलग करने की आवश्यकता है।
Android आर्किटेक्चर में, SRP Jetpack पर Google की सिफारिशों में शामिल है: ViewModel स्क्रीन स्थिति के लिए जिम्मेदार है, Repository डेटा के लिए, UseCase बिजनेस लॉजिक के लिए। iOS विकास में, MVVM और Coordinator पैटर्न उसी तर्क का पालन करते हैं।
मोबाइल परियोजनाओं में SRP का पालन करने से मापनीय लाभ मिलता है: क्लास का आकार 40-60% कम होना, कोड समीक्षा में कम समय और नई कार्यक्षमता जोड़ते समय कम रिग्रेशन बग्स। पृथक मॉड्यूल यूनिट टेस्ट से कवर करने और अन्य स्क्रीन्स में पुनः उपयोग करने में आसान हैं।
SRP का पालन करने वाली क्लासें के यूनिट टेस्टिंग में कम mock ऑब्जेक्ट और कम कंफ़िगरेशन की आवश्यकता होती है। यदि एक क्लास की एक जिम्मेदारी है, तो उसकी निर्भरताएँ सीमित हैं। टेस्ट एक व्यवहार की जाँच करता है, कई असंबंधित परिदृश्यों का संयोजन नहीं।
Google Testing Blog (2023) की रिपोर्ट के अनुसार, एकल जिम्मेदारी वाली क्लासें एकत्रीकरण क्लासों की तुलना में 35% अधिक टेस्ट कवरेज दिखाती हैं। डिवेलपर छोटे, समझने में आसान मॉड्यूल्स के लिए अधिक तेयार होते हैं।
चलिए एक सामान्य Android क्लास देखते हैं जो SRP का उल्लंघन करता है — यह डेटा लोड करता है, रिस्पंस पार्स करता है, और UI अपडेट करता है। रिफैक्टरिंग के बाद, प्रत्येक जिम्मेदारी अपने घटक में अलग होती है।
// SRP का उल्लंघन: एक क्लास सब कुछ करती है
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// HTTP अनुरोध
// JSON पार्सिंग
// UI अपडेट
// डेटाबेस में सहेजना
}
}
// SRP लागू करने के बाद
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
iOS Swift में नेटवर्क लेयर और डिस्प्ले के अलगाव का एक समान उदाहरण:
// SRP का उल्लंघन: ViewController डेटा और UI प्रबंधित करता है
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// URLSession अनुरोध
// JSON डिकोड करें
// label अपडेट करें
}
}
// SRP लागू करने के बाद
protocol UserServiceProtocol {
func fetchUser(id: Int) async throws -> User
}
class ProfileViewModel {
private let service: UserServiceProtocol
func loadProfile(id: Int) { }
}
class ProfileViewController: UIViewController {
func display(user: User) { }
}
SRP रिफैक्टरिंग आर्किटेक्चर को जटिल नहीं बनाती — यह जिम्मेदारी को पुनर्वितरित करता है। डुप्लिकेशन को हटाने से कोड की मात्रा कम भी हो सकती है। प्रत्येक नए क्लास का एक स्पष्ट उद्देश्य है और इसे स्वतंत्र रूप से विकसित किया जा सकता है।
कंपोजीशन वहाँ SRP का पालन करने में मदद करता है जहाँ वर्सन अनावश्यक युग्मन बनाता है। दर्जनों विधियों वाले सुपरक्लास के बजाय, एक उपक्लास कंस्ट्रक्टर के माध्यम से विशेषज्ञ ऑब्जेक्ट्स का एक सेट प्राप्त करता है। प्रत्येक ऑब्जेक्ट अपनी कार्यक्षमता के लिए जिम्मेदार है।
Android विकास में, Decorator पैटर्न मूल क्लास को बदले बिना जिम्मेदारियाँ जोड़ने की अनुमति देता है। iOS में, नेटवर्किंग लेयर में Middleware चैन लॉगिंग, कैशिंग और प्रमाणीकरण को अलग-अलग मॉड्यूल्स में अलग करती है।
सबसे सामान्य उल्लंघन गॉड क्लास है: एक ऐसी क्लास जो डेटाबेस का प्रबंधन करती है, नोटिफिकेशन भेजती है, रिपोर्ट जनरेट करती है और यूजर इनपुट प्रोसेस करती है। ऐसी क्लास परियोजना की अड़चन बन जाती है: किसी भी बदलाव के लिए पूर्ण रिग्रेशन टेस्टिंग की आवश्यकता होती है।
मोबाइल विकास में, Activity, Fragment या ViewController में बिजनेस लॉजिक और UI लॉजिक के मिश्रण से SRP का उल्लंघन होता है। जब एक onClickListener एक साथ डेटा मान्य करता है, API कॉल करता है और बटन दृश्यता अपडेट करता है — यह एकल जिम्मेदारी के सिद्धांत का सीधा उल्लंघन है।
SRP के उल्लंघन के परिणामों में शामिल हैं: समान्तर विकास में कठिनाई (एक फ़ाइल में विरोध), यूनिट टेस्टिंग में बाधा, बदलाव की उच्च लागत और कम कोड पठनीयता। SRP के व्यवस्थित उल्लंघन वाले परियोजनाओं को नई कार्यक्षमता जोड़ने में 2-3 गुना अधिक समय लगता है।
SRP के उल्लंघन को अप्रत्यक्ष संकेतों से पहचाना जा सकता है: क्लास 200 लाइनों से अधिक है, अलग-अलग एप्लिकेशन लेयर्स (UI + network + database) से मॉड्यूल इम्पोर्ट करती है, अलग-अलग विषयों पर 5 से अधिक सार्वजनिक विधियाँ हैं। संसञ्जनता मैट्रिक एक सांख्यिकीय संकेतक है: क्लास के अंदर विधियों की कम संसञ्जनता SRP के उल्लंघन की ओर संकेत करती है।
SRP के उल्लंघन का पता लगाने के लिए, स्थिर विश्लेषण उपकरणों का उपयोग करें: Android के लिए Detekt के साथ TooManyFunctions नियम, iOS के लिए SwiftLint के साथ file_length नियम। ये उपकरण आकार और जटिलता की सीमाओं से अधिक क्लासों को उजागर करते हैं।
SRP का उल्लंघन करने वाली क्लासों का रिफैक्टरिंग Extract Class या Extract Delegate के माध्यम से किया जाता है: संबंधित विधियों के एक समूह को एक अलग क्लास में निकाला जाता है, और मूल क्लास उन्हें कॉल डिलीगेट करती है। इन रिफैक्टरिंग्स का क्रमशः अनुप्रयोग गॉड क्लास को ढीले युग्मित मॉड्यूल्स के एक सेट में बदल देता है, प्रत्येक की एक ही जिम्मेदारी होती है। यह दृष्टिकोण विकास को रोके बिना आर्किटेक्चर में सुधार करने की अनुमति देता है — रिफैक्टरिंग पुनरावृत्तिक रूप से, एक बार में एक मॉड्यूल की जाती है।
अक्सर पूछे जाने वाले प्रश्न
नहीं। SRP विधियों की संख्या के बारे में नहीं है, बल्कि परिवर्तन के कारणों की संख्या के बारे में है। एक क्लास में दर्जनों विधियाँ हो सकती हैं यदि वे सभी एक अक्टर के प्रति एक जिम्मेदारी निभाते हैं। एक विधि विपरीत चरम है जो अत्यधिक कोड विखंडन का कारण बनती है।
यह एक ही सिद्धांत है। Single Responsibility Principle का अनुवाद एकल जिम्मेदारी और एकल कर्तव्य दोनों ही रूपों में किया जाता है। जिम्मेदारी शब्द सार को बेहतर ढंग से दर्शाता है: यह एक अक्टर के प्रति जिम्मेदारी के बारे में है, न कि एक तकनीकी फ़ंक्शन के बारे में।
Repository डेटा लेयर पर SRP लागू करने का सीधा परिणाम है। ViewModel या UseCase में डेटा एक्सेस तर्क को फैलाने के बजाय, Repository एक ही जिम्मेदारी लेता है: स्रोत एब्सट्रैक्शन के साथ डेटा प्रदान करना। यह मोबाइल आर्किटेक्चर में SRP का एक क्लासिक कार्यान्वयन है।
हाँ, SRP निर्भरताओं को प्रतिबंधित नहीं करता है। एक जिम्मेदारी वाला क्लास कंपोजीशन के माध्यम से कुछ काम दूसरी क्लासों को सौंप सकता है। महत्वपूर्ण यह है कि ये सौंपे गए कार्य उसी जिम्मेदारी का हिस्सा हैं, न कि परिवर्तन का एक स्वतंत्र कारण।
यह प्रश्न पूछें: “कौन से अक्टर इस क्लास में बदलाव की मांग कर सकते हैं?” यदि उत्तर में एक से अधिक अक्टर हैं, तो SRP का उल्लंघन होता है। अतिरिक्त: क्लास के उद्देश्य को एक वाक्य में “और” के बिना बताने का प्रयास करें। यदि नहीं बता सकते, तो क्लास बहुत ज्यादा कर रही है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें