SOLID ডিজাইন প্রিন্সিপালস হলো ৫টি ডিজাইন নীতির সমষ্টি যা অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP) এ ভালো কোড করার নিয়ম হিসেবে বিবেচিত। এগুলোর উদ্দেশ্য হলো কোডকে সহজে বোধগম্য, মডিফাই এবং মেইনটেইন করা। নিচে প্রতিটি প্রিন্সিপাল এর বাংলা ব্যাখ্যা এবং কোড উদাহরণ দেওয়া হলো:
1. S - Single Responsibility Principle (SRP)
প্রত্যেক ক্লাসের একটি মাত্র কাজ থাকা উচিত। অর্থাৎ, একটি ক্লাস পরিবর্তনের একটি মাত্র কারণ থাকা উচিত।
উদাহরণ:
একটি ক্লাস ইউজার অথেন্টিকেশন এবং ইমেল পাঠানোর কাজ করছে, যা SRP নিয়ম লঙ্ঘন করে:
class User {
public function login() {
// Login logic
}
public function sendEmail() {
// Email sending logic
}
}
SRP অনুসারে, আমরা এই কাজ দুটি আলাদা ক্লাসে ভাগ করবো:
class User {
public function login() {
// Login logic
}
}
class EmailService {
public function sendEmail() {
// Email sending logic
}
}
এখন User
ক্লাসের শুধু একটি দায়িত্ব আছে: লগইন প্রসেস করা।
2. O - Open/Closed Principle (OCP)
ক্লাস বা মডিউলগুলো পরিবর্তন না করে তাদের এক্সটেন্ড করা উচিত, অর্থাৎ নতুন ফিচার যোগ করা সম্ভব হওয়া উচিত।
উদাহরণ:
ধরা যাক, আমাদের একটি ক্লাস আছে যা পেমেন্ট প্রসেস করছে:
class Payment {
public function processPayment($type) {
if ($type == 'credit_card') {
// Process credit card payment
} elseif ($type == 'paypal') {
// Process PayPal payment
}
}
}
এটি OCP নিয়ম লঙ্ঘন করছে কারণ নতুন পেমেন্ট টাইপ যোগ করতে হলে কোড পরিবর্তন করতে হবে। আমরা একে ঠিক করতে নিচের মত করতে পারি:
interface PaymentMethod {
public function process();
}
class CreditCardPayment implements PaymentMethod {
public function process() {
// Process credit card payment
}
}
class PayPalPayment implements PaymentMethod {
public function process() {
// Process PayPal payment
}
}
class Payment {
public function processPayment(PaymentMethod $paymentMethod) {
$paymentMethod->process();
}
}
এখন নতুন পেমেন্ট টাইপ যোগ করার জন্য শুধু নতুন ক্লাস তৈরি করতে হবে, মেইন ক্লাস পরিবর্তন করতে হবে না।
3. L - Liskov Substitution Principle (LSP)
সুপারক্লাসের অবজেক্টগুলোর বদলে সাবক্লাসের অবজেক্ট ব্যবহার করা উচিত, এবং এটি প্রোগ্রামের আচরণকে পরিবর্তন করবে না।
উদাহরণ:
একটি Bird
ক্লাস থেকে Penguin
ক্লাস ইনহেরিট করা হয়েছে, কিন্তু পেঙ্গুইন উড়তে পারে না, যা LSP নিয়ম লঙ্ঘন করছে:
class Bird {
public function fly() {
// Fly logic
}
}
class Penguin extends Bird {
public function fly() {
throw new Exception("Penguins can't fly");
}
}
এটি LSP নিয়ম অনুসারে সঠিক নয়। একে ঠিক করার জন্য আমরা হায়ারার্কি পরিবর্তন করতে পারি:
class Bird {
// Bird-related properties and methods
}
class FlyingBird extends Bird {
public function fly() {
// Fly logic
}
}
class Penguin extends Bird {
// No fly method here because penguins don't fly
}
4. I - Interface Segregation Principle (ISP)
ক্লায়েন্টদের এমন ইন্টারফেসে নির্ভরশীল হতে বাধ্য করা উচিত নয় যা তারা ব্যবহার করে না। অর্থাৎ, বড় ইন্টারফেসগুলোকে ছোট ছোট স্পেসিফিক ইন্টারফেসে ভাঙা উচিত।
উদাহরণ:
একটি বড় ইন্টারফেসের সব মেথড একসাথে ব্যবহার করা হচ্ছে:
interface Animal {
public function run();
public function fly();
public function swim();
}
যেখানে কিছু ক্লাস হয়ত কেবল একটি মেথড ব্যবহার করবে। একে ঠিক করতে আমরা ইন্টারফেসগুলো ভাগ করতে পারি:
interface Runnable {
public function run();
}
interface Flyable {
public function fly();
}
interface Swimmable {
public function swim();
}
class Dog implements Runnable {
public function run() {
// Dog running logic
}
}
class Bird implements Runnable, Flyable {
public function run() {
// Bird running logic
}
public function fly() {
// Bird flying logic
}
}
এখন প্রত্যেক ক্লাস তার প্রয়োজনীয় ইন্টারফেসগুলো ব্যবহার করবে।
5. D - Dependency Inversion Principle (DIP)
উচ্চ-লেভেলের মডিউলগুলোকে নিম্ন-লেভেলের মডিউলগুলোর উপর নির্ভরশীল হওয়া উচিত নয়; উভয়ই অ্যাবস্ট্রাকশন (ইন্টারফেস) এর উপর নির্ভরশীল হওয়া উচিত।
উদাহরণ:
একটি ক্লাস সরাসরি নির্দিষ্ট ডাটাবেজ ইমপ্লিমেন্টেশনের উপর নির্ভরশীল, যা DIP নিয়ম লঙ্ঘন করছে:
class MySQLDatabase {
public function connect() {
// MySQL connection logic
}
}
class User {
private $db;
public function __construct() {
$this->db = new MySQLDatabase();
}
}
DIP নিয়ম অনুযায়ী, এটি অ্যাবস্ট্রাকশন এর উপর নির্ভরশীল হওয়া উচিত:
interface Database {
public function connect();
}
class MySQLDatabase implements Database {
public function connect() {
// MySQL connection logic
}
}
class User {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
}
এখন আপনি কোনো ডাটাবেজ ইমপ্লিমেন্টেশন ব্যবহার করতে পারেন যেমন PostgreSQL, MongoDB ইত্যাদি, শুধুমাত্র ইন্টারফেস ইমপ্লিমেন্ট করে।