বাংলায় Solid ডিজাইন প্রিন্সিপালস

বাংলায় Solid ডিজাইন প্রিন্সিপালস

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 ইত্যাদি, শুধুমাত্র ইন্টারফেস ইমপ্লিমেন্ট করে।