🎉 سال نو، مهارت نو، مشاوره رایگان نقشه راه برنامه نویسی (آفر ویژه ثبت نام قبل از افزایش قیمت 🔥)
۰ ثانیه
۰ دقیقه
۰ ساعت
۳ علی
کاهش وابستگی با اصل Dependency Inversion
جامعه پی اچ پی ایجاد شده در ۰۲ مرداد ۱۴۰۰

سلام

 

اصل Dependency Inversion صرفا باعث کاهش وابستگی‌ها میشه و وابستگی رو به صفر نمیرسونه درسته؟

 

مثلا ماژول سطح بالا به یک انتزاعی وابسته هست و ماژول‌های سطح پایین هم میان اون انتزاع رو implements میکنن و جزئیات رو پیاده سازی می‌کنن

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

درود

 

این اصل به ما میگه که کدهای ما باید به abstraction وابسته باشن ن concreate یا همون پیاده سازی، به طور کلی ینی اینکه کلاس‌های رده بالا یا پدر نباید به کلاس‌های فرزند وابستگی داشته باشند و این قضیه باید کاملا برعکس باشه و کلاس‌های فرزند باید به abstraction وابسته باشند

interface MailDriverInterface
{
    public function send();
}
class SMTPMailDriver implements MailDriverInterface
{
    public function send()
    {
        return 'use php mail() method';
    }
}
class SendWelcomeEmail
{
    private $mailDriver;
    public function __construct(MailDriverInterface $mailDriver)
    {
        $this->mailDriver = $mailDriver;
    }
    public function send()
    {
    	$this->mailDriver->send();
}
}

MailDriverInterface  یک interfaceی هستش که میگه هر کلاس که بخواد من رو پیاده سازی کنه باید حتما باید متد send رو پیاده سازی کنه و همین باعث میشه که تمامی کلاس‌های فرزند این interface از تمامی متدهاش پیروی کنند و پیاده سازیش کنن که دقیقا کلاس SMTPMailDriver اومده همچین کاری رو کرده

مزیتش چیه؟ میزیتش اینکه ما اگه بخواهیم بعدا نوع دیگه ای از ارسال ایمیل رو اضافه کنیم دیگه میدونیم که باید داخلش متد send رو داشته باشیه و ما کاری به نوع پیاده سازیش نداریم چون فقط برای ما مهمه که اون کلاس یک ایمیل رو send کنه

حالا اگه داخل کلاس SendWelcomeEmail یا هر کلاس دیگه ای نیاز بود یک ایمیلی ارسال کنیم میایم به سادگی از طریق constract اون کلاس وابستگی رو تزریق میکنیم و داخل یکی از متدهای کلاس خیلی ساده چون میدونیم قراردادی وجود داره که باید همه درایورهای ارسال ایمیل متد send رو داشته باشیند با خیال راحت متد Send رو صدا میزنیم

 

 

امیر صالحی ۰۲ مرداد ۱۴۰۰، ۱۸:۳۱

ممنون از پاسختون

 

« ینی اینکه کلاس‌های رده بالا یا پدر نباید به کلاس‌های فرزند وابستگی داشته باشند » این بخش بنظرم اشتباه هست کلاس سطح بالا کلاسی هست که عملی رو با استفاده از یک ابزار انجام میده و کلاس سطح پایین کلاسی ابزاری هست که برای اجرای عملی موردنیاز هست 

 

داخل همین مثالی که خودتون زدید کلاس SendWelcomeEmail  یک کلاس سطح بالاست که برای ارسال email از کلاس سطح پایین SMTPMailDriver استفاده میکنه

 

بعدش مزیت Dependency Inversion اینه که اگه بخواهیم بعدا نوع دیگه ای از ارسال ایمیل رو اضافه کنیم دیگه میدونیم که باید داخلش متد send رو داشته باشه ؟!

 

یا اینکه Dependency Inversion این مزیت رو به ما میده تا با تعریف یک interface وابستگی کلاس سطح بالا به کلاس‌های سطح پایین رو کاهش بدیم اینطوری کلاس سطح بالامون میتونه براحتی با هر کلاسی که interface ما رو پیاده سازی کرده کار کنه

 

علی ۰۲ مرداد ۱۴۰۰، ۱۹:۰۳

موردی که شما بهش اشاره کردید هم dependency inversion و هم dependency injection رو درگیر میکنه، حالا ینی چی

 

ما توی dependency inversion میگیم این وابستگی نباید به صورت وارونه از سمت فرزند به پدر باشه بلکه باید از پدر به فرزند باشه، مثل آبشار بهش نگاه کنید که آبشار همون کلاس پدر ماست که داره به رودخونه پایینش که کلاس فرزند میشه آب میرسونه

 

و توی dependency injection به صورت که تزریق وابستگی باید جوری باشه که فرزند تعیین نکنه که دقیقا چی میخواد ما باید بهش چیزی که نیاز داره رو بدیم، ینی اگه قراره کلاسی داخل کلاس فرزند new بشه بهتره که از طریق construct بهش object کلاسی رو پاس بدیم به جای اینکه خود فرزند بیاد کلاسی رو داخل خودش new کنه

 

سر همین دو اصل مهم ما توی لاراول چیزی به اسم IOC رو داریم که اومده به شکل کامل این مبحث رو توی هسته لاراول پیاده سازی کرده

 

من این دوتا مورد رو خیلی بیشتر با مثال داخل این تاپیک توضیخ دادم و گفتم که ico چیه https://7learn.ac/community/ioc-%D8%AF%D9%82%DB%8C%D9%82%D8%A7-%DA%86%DB%8C%D9%87--2LPKL

امیر صالحی ۰۳ مرداد ۱۴۰۰، ۱۷:۱۳