اصول SOLID

سه شنبه 31 خرداد 1401 توسط Reganto

SOLID «سالید» کلمه‌ای مخفف برای پنج اصل است که معمولا در طراحی شی‌گرا اعمال می‌شوند. این اصول کمک می‌کنند تا برنامه‌ها قابل درک‌تر، منعطف‌ترو قابلیت نگه‌داری آسان‌تری داشته باشند. اصول سالید برای مدیریت وابستگی‌ها استفاده می‌شوند. این اصول مستقل از هم نیستند و نقض هر کدام «احتمالا» منجر به نقض بقیه خواهد شد.

ارتباط میان SOLID و Design Patterns

الگوهای طراحی «Design Patterns» راه‌حل‌هایی امتحان شده و قابل اطمینان برای مسائل رایج هستند. الگوهای طراحی به صورت ضمنی SOLID را نیز تحت پوشش قرار می‌دهند.

اصل اول: Single Responsibility Principle «اصل تک مسئولیتی»

اصل SRP بیان می‌دارد که هر موجودیت در برنامه شی‌گرا اعم از کلاس،‌متد یا تابع بایستی تنها یک وظیفه برای انجام داشته باشد و در این صورت است که موجودیت مفروض ما اگر نیاز به تغییر داشته باشد،‌ باید تنها به یک دلیل تغییر کند. تک مسئولیتی بودن هر بخش از کد بخشی از فلسفه یونیکس هم هست

اگر موجودیتی چندین مسئولیت برای انجام داشته باشد اصطلاحا به آن god object می‌گویند

مثال

کلاس زیر را در نظر بگیرید

class Student:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        # get student name
        return self.name

    @name.setter
    def name(self, nm):
        # set student name
        if nm is not None:
            self.name = name

    def insert_to_db(self):
        # Database logic written here
        pass

    def generate_report(self):
        # Report formatting
        pass

همانطور که می‌بینید در کلاس Student چندین متد وجود دارد و هر متد وظیفه خاص و غیرمرتبط با متد‌های دیگر دارد. این شیوه پیاده‌سازی ناقض اصل SRP است. برای پیروی از SRP دو متد آخر را در دو کلاس جداگانه قرار می‌دهیم.

class Student:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        # get student name
        return self.name

    @name.setter
    def name(self, nm):
        # set student name
        if nm is not None:
            self.name = name

class StudentDB:
    def retrieve(self, id):
        # Retrieve data from DB
        pass

    def insert(self, obj):
        # Insert obj to DB
        pass

Class StudentLog:
    def generate_report(self):
        # Report formatting
        pass

در این حالت هر کلاس تنها یک وظیفه برای انجام برعهده دارد و اگر بنابر تغییر یکی از این کلاس‌ها داشته باشیم تنها به یک دلیل کلاس مورد نظر را تغییر خواهیم داد. اصل SRP برای توابع و متد‌ها نیز می‌تواند موضوعیت داشته باشد. به عنوان مثال به فانکشن زیر توجه کنید:

def insert():
    # Create connection
    # Prepare params for insertion
    # Execute insertion
    # Return result
    pass    

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

def db_connection():
    # Return a connection to DB
    pass

def get_params():
    # Prepare params
    pass

def insert():
    connection = db_connection()
    params = get_params()
    # Insert data to DB
    # Return result
    pass

اصل دوم

اصل سوم

اصل چهارم

اصل پنجم

منابع:

  • Clean Code in Python by Mariano Anaya