اصل لسکو (Liskov Substitution Principle - LSP): پایه‌ای ترین اصل SOLID در معماری نرم‌افزار

اصل لسکو (Liskov Substitution Principle - LSP): پایه‌ای ترین اصل SOLID در معماری نرم‌افزار

اصل لسکو (LSP) که به نام باربارا لسکو، دانشمند کامپیوتر MIT نامگذاری شده است، سومین اصل از اصول SOLID در مهندسی نرم‌افزار محسوب می‌شود. این اصل در سال 1987 مطرح شد و امروزه به عنوان اساس طراحی رابط‌ها و وراثت در برنامه‌نویسی شیءگرا شناخته می‌شود.

💡 تعریف فنی اصل لسکو:
"اگر S زیرنوع T باشد، آنگاه اشیاء از نوع T باید بتوانند با اشیاء از نوع S جایگزین شوند، بدون اینکه ویژگی‌های مطلوب برنامه تغییر کند."

🔍 چرا اصل لسکو مهم است؟

  • جلوگیری از خطاهای غیرمنتظره در زمان اجرا

  • ایجاد قابلیت نگهداری بهتر کد

  • تسهیل توسعه پذیری سیستم

  • کاهش وابستگی‌های ناخواسته بین کامپوننت‌ها

⚠️ نقض اصل لسکو: مثال کلاسیک مستطیل-مربع


class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

class Square(Rectangle):
    def __init__(self, size):
        super().__init__(size, size)
    
    # نقض LSP: تغییر رفتار ست‌کننده‌های والد
    @property
    def width(self):
        return self._width
    
    @width.setter
    def width(self, value):
        self._width = value
        self._height = value  # رفتار غیرمنتظره!

مشکل: وقتی Square جایگزین Rectangle شود، تغییر عرض باعث تغییر ارتفاع می‌شود (رفتاری که از Rectangle انتظار نمی‌رود).

✅ پیاده‌سازی صحیح با رعایت LSP


from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

class Square(Shape):
    def __init__(self, size):
        self.size = size
    
    def area(self):
        return self.size ** 2

🛠️ نشانه‌های نقض LSP

  1. Override کردن متدها با رفتار کاملاً متفاوت

  2. پرتاب Exceptionهای جدید در زیرکلاس

  3. برگشت دادن مقادیر با نوع متفاوت از والد

  4. تغییر حالت داخلی شیء به روشی غیرمنتظره

💡 بهترین روش‌ها برای رعایت LSP

  1. از اینترفیس‌ها به جای وراثت بتنی استفاده کنید

  2. قراردادهای رفتاری را به دقت مستند کنید

  3. از Design by Contract پیروی کنید:

    • Preconditions نباید در زیرکلاس تقویت شوند

    • Postconditions نباید در زیرکلاس تضعیف شوند

    • Invariants باید حفظ شوند

🌐 کاربردهای واقعی LSP

  1. پلاگین‌های سیستم: هر پلاگین باید بدون شکستن سیستم اصلی جایگزین شود

  2. ماژول‌های پرداخت: تمام درگاه‌های پرداخت باید از یک قرارداد واحد پیروی کنند

  3. ذخیره‌سازی داده: جایگزینی دیتابیس واقعی با Mock در تست‌ها

java


// مثال در جاوا - سیستم پرداخت
interface PaymentProcessor {
    void processPayment(double amount);
}

class PayPalProcessor implements PaymentProcessor {
    public void processPayment(double amount) {
        // پیاده‌سازی خاص PayPal
    }
}

class StripeProcessor implements PaymentProcessor {
    public void processPayment(double amount) {
        // پیاده‌سازی خاص Stripe
    }
}

📊 تأثیر LSP بر کیفیت کد

معیار بدون LSP با LSP
قابلیت تست ❌ ضعیف ✅ عالی
قابلیت استفاده مجدد ❌ محدود ✅ بالا
وابستگی‌ها ❌ زیاد ✅ کم
خطاهای زمان اجرا ❌ متعدد ✅ نادر

🚀 نتیجه‌گیری: LSP در دنیای مدرن

اصل لسکو امروزه بیش از هر زمان دیگری اهمیت دارد، به ویژه در:

  • معماری‌های میکروسرویس

  • توسعه مبتنی بر کامپوننت

  • سیستم‌های Plugin-Based

رعایت این اصل مانع از ایجاد شگفتی‌های ناخواسته در کد می‌شود و به شما کمک می‌کند سیستم‌هایی انعطاف‌پذیر و قابل نگهداری بسازید.

Avatar

نویسنده

سیدهادی موسوی

تعداد لایک‌ها: 7

Tags: #تئوری #برنامه_نویسی #مقاله

ارسال نظر

نظرات