آموزش Dependency Inversion Principle در SOLID

  • خانه
  • آموزش Dependency Inversion Principle در SOLID
Image تحقیقات

آموزش Dependency Inversion Principle در SOLID

سلام خدمت شما دوستان عزیز

در ادامه مبحث SOLID نوبت میرسه به معرفی یک اصل دیگر یه نام Dependency Inversion Principle که به صورت کوتاه DIP هم می گویند.(اگر با مفهوم SOLID آشنایی ندارین پیشنهاد میکنم اول این پست را مطالعه کنید)

تعریف را اینگونه بیان کرده اند :

Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions.

 

DIP مخفف Dependency Inversion Principle و مفهومی است که وابستگی مستقیم کلاس های سطح بالا را به کلاس های سطح پایین منع میکند. به این منظور که اگر کلاس خاصی(high-level) که از کلاس های دیگر(low-level) استفاده می کند وابستگی مستقیمی با کلاس های low-level داشته باشد سبب بروز این مشکل خواهد شد که اگر کلاس low-level دیگری به مجموعه افزوده شود اجبارا کلاس high-level نیز بایستی تغییر کند. DIP برای حل این مشکل به وجود آمده است.

خب شروع کنیم به مثال :

class PasswordReminder {
    private $dbConnection;

    public function __construct(MySQLConnection $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
}

فرض کنید یک کلاس داریم به اسم PasswordReminder که برای ارسال پسورد مجدد به کاربر می باشد . هماطور که می بینید در تابع سازنده ی , به کلاس MySQLConnection وابسته شده و در واقع dependency injection است  و از این کلاس داخل کلاس PasswordReminder برای اتصال به دیتابیس و داستان های بعدیش استفاده می کنیم .

در این مثال MySQLConnection کلاس سطح پایین یا low-level ما است و کلاس PasswordReminder  کلاس سطح بالا یا high-level می باشد .

حالا اگر شما قرار شد که دیتابیس انجین خودتون را عوض کنید مثلا از Mongo استفاده کنید ابتدا باید یک کلاس به اسمMongoConnection ایجاد کنید و کدهای لازمه را داخل اش قرار دهید سپس باید در کلاس PasswordReminder  هم تغییری لحاظ کنید و اون تغیر این است که به جای MySQLConnection کلاس MongoConnection  را در تابع سازنده injection نماید که این کار دقیقا با اصل Dependency Inversion Principle در تضاد است زیرا  این اصل تاکید دارد هیچ وابستگی ای بین کلاس های سطح بالا و سطح پایین نباشد .

در واقع PasswordReminder نیازی ندارد بداند از کدام دیتابیس داریم استفاده می کنیم .

خب راه حل چیست ؟؟؟ راه حل دقیقا استفاده از اصل Dependency Inversion Principle می باشد .

یک اینترفیس به نام DBConnectionInterface می سازیم و از این به بعد در کلاس PasswordReminder داخل تابع سازنده , اینترفیس DBConnectionInterface را injection می کنیم  و در  اصل به جای انیکه به کلاس های مربوط به دیتابیس وابسته باشیم به این اینترفیس وابسته هستیم که تغییری نمی کند.

interface DBConnectionInterface {
    public function connect();
}

سپس کلاس های دیتابیس امون هم باید از این اینترفیس implements کنند.

class MySQLConnection implements DBConnectionInterface {
    public function connect() {
        return "Database connection";
    }
}

class PasswordReminder {
    private $dbConnection;

    public function __construct(DBConnectionInterface $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
}

مشکل حل شد و به وسیله ی این انترفیس میانی از وابستگی کلاس های سطح بالا به کلاس های سطح پایین جلوگیری کردیم و کلاس های سطح پایین هر منطقی داشته باشند مهم نیست فقط باید از اینترفیس مورد نظر طبعییت کنند.

خب این اصل هم تمام شد امیدوارم با آن آشنا شده باشید .