SRP (Single Responsibility Principle) — SOLID کا پہلا اصول، جو طے کرتا ہے: ہر کلاس یا ماڈیول میں تبدیلی کی صرف ایک وجہ ہونی چاہیے۔ یہ اصول رابرٹ مارٹن نے کتاب Clean Architecture (2017) میں ترتیب دیا تھا اور ماڈیولر ڈیزائن کی بنیاد بن گیا۔ اس کتاب کے مطابق، SRP کا اطلاق براہ راست اجزاء کے اتصال کو کم کرتا ہے اور فنکشن میں ترمیم کے دوران سلسلہ وار تبدیلیوں کو ختم کرتا ہے۔
اہم نکات
SRP (Single Responsibility Principle) واحد ذمہ داری کا اصول ہے، جو کہتا ہے: ہر کلاس یا ماڈیول میں تبدیلی کی صرف ایک وجہ ہونی چاہیے۔ اس کا مطلب یہ نہیں ہے کہ ایک کلاس کو صرف ایک کارروائی کرنی چاہیے۔ یہ ایک اکٹر کے حوالے سے ایک ذمہ داری میں متحد متعلقہ افعال کے گروپ کی بات کر رہا ہے۔
رابرٹ مارٹن نے SRP کو اکٹروں کے حوالے سے دوبارہ ترتیب دیا: ایک کلاس کو صرف ایک ستاک ہولڈر یا لوگوں کے ایک گروپ کی درخواست پر ہی تبدیل ہونا چاہیے۔ اگر دو مختلف اکٹر ایک ہی کلاس میں تبدیلیوں کا مطالبہ کرتے ہیں، تو ذمہ داری غلط طریقے سے تقسیم کی گئی ہے۔
مثال کے طور پر، ایک Employee کلاس جو تنخواہ کا حساب (محاسبہ شعبہ کی درخواست) اور ریپورٹس تیار کرنا (منیجمنٹ کی درخواست) ایک ساتھ کرتی ہے، SRP کی خلاف ورزی کرتی ہے۔ حساب کے قوانین میں تبدیلی ریپورٹ تیاری کو متاثر کر سکتی ہے اور اس کا الٹ بھی ہو سکتا ہے۔
ایک ماڈیول میں تبدیلی کی ایک اور صرف ایک وجہ ہونی چاہیے۔ تبدیلی کی وجہ ایک اکٹر کے ذریعہ مقرر کی جاتی ہے — وہ شخص یا سسٹم جو ضرورت کا آغاز کرتا ہے۔ اگر مختلف اکٹروں کی ضروریات ایک ماڈیول میں تبدیلی کا سبب بنتی ہیں، تو ماڈیول SRP کی خلاف ورزی کر رہا ہے۔
اکٹر کا تصور SRP کو ایک تجریدی سفارش کے بجائے آرکیٹیکچرل تجزیہ کا ایک عملی اوزار بناتا ہے۔ سسٹم ڈیزائن کرتے وقت، صرف پوچھیں: “اس کوڈ کو کون تبدیل کرنے کے لیے کہے گا?” — اگر جواب میں ایک سے زائد استاک ہولڈر ہیں، تو ذمہ داری کو تقسیم کیا جانا چاہیے۔
واحد ذمہ داری کو ان طریقوں کو گروپ کرکے نفذ کیا جاتا ہے جو ایک وجہ سے تبدیل ہوتی ہیں۔ ایک کلاس ہر موقع کے لیے کسی بہرترین چاکو کے بجائے متعلق منطق کا ایک اختزاری مقام بن جاتی ہے۔ یہ کوڈ کی سمجھ کو آسان بناتا ہے: ڈیویلپر کلاس دیکھتا ہے اور فوراں اس کا مقصد سمجھ لیتا ہے۔
SRP کا مسؤولیہ ایک تبدیلی کے محور کے اصول پر مبنی ہے۔ اگر کوئی فنکشن آزادانہ وجوہات سے تبدیل ہو سکتا ہے، تو اسے علاحد کلاسوں میں نکالا جانا چاہیے۔ ان کلاسوں کے درمیان رابطے composition یا دیلیگیشن کے ذریعہ قائم کیے جاتے ہیں۔
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 ریفیکٹرنگ آرکیٹیکچر کو پیچیدہ نہیں کرتا — یہ ذمہ داری کو دوبارہ تقسیم کرتا ہے۔ دوھراو کو ختم کرکے کوڈ کی مقدار کم بھی ہو سکتی ہے۔ ہر نئی کلاس کا ایک واضح مقصد ہے اور آزادانہ ترقی کی جا سکتی ہے۔
Composition وہاں 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 انحصارات کو منع نہیں کرتا۔ ایک ذمہ داری والی کلاس composition کے ذریعہ دیگر کلاسوں کو کچھ کام دیلیگیٹ کر سکتی ہے۔ اہم بات یہ ہے که یہ دیلیگیٹ کیے گئے کام اسی ذمہ داری کا حصہ ہوں، ازاد تبدیلی کی وجہ نہیں۔
یہ سوال پوچھیں: “کون سے اکٹر اس کلاس میں تبدیلیوں کا مطالبہ کر سکتے ہیں?” اگر جواب میں ایک سے زیادہ اکٹر ہوں، تو SRP کی خلاف ورزی ہوئی ہے۔ مزید: کلاس کے مقصد کو “اور” کے بغیر ایک جملے میں بیان کرنے کی کوشش کریں۔ اگر نہیں کر سکتے، تو کلاس بہت زیادہ کر رہی ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں