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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন