برنامه نویس موبایل (فلاتر ، اندروید ، یونیتی ، iOS)
اصل پنجم پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter
“اصل معکوس سازی وابستگی“ که آنرا “اصل وارونگی وابستگی” هم می نامند برگرفته از عبارات لاتین (Dependency Inversion Principle) یا به طور خلاصه (DIP) ، پنجمین اصل از SOLID است و می گوید که: “ماژولهای سطح بالا نباید به ماژولهای سطح پایین وابسته باشند” .
در واقع، ماژول ها به جای دسترسی مستقیم به منابعی که وابستگی ایجاد می کنند (مثلا کلاس ها) ، باید از طریق interface ها، به آنها دسترسی داشته باشند. در این صورت تغییرات کلاس های ما ، توسط interface ها به درون خود کلاس ها محدود می شود و لایه های بالاتر را درگیر تغییر نمی کنند.
در وصف اصل وارونگی وابستگی ، گفته می شود که : اصل وارونگی وابستگی، ترکیبی ناب ، از اصل باز/بسته و اصل جایگزینی لیسکوف است.
برای اینکه مفهوم را در مثال عملی کاملتر متوجه شویم آن را به دو شیوه صحیح و غلط آن پیاده سازی میکنیم.
۱- مثال زیر DIP را نقض می کند.
فرض کنیم که قرار است برای یک فروشگاه کتاب نرم افزاری کتابخوان بسازیم . از ما خواسته شده برای کاربری امکانات زیر را فراهم کنیم:
۱- بخشی از کتاب مدنظر را ببیند.
۲-از نظر سایر کاربران درباره کتاب مطلع شود.
۳- اگر مایل بود، آن کتاب را به لیست کتابهای موجود در کتابخانه خود اضافه کند.
برای شروع کلاس کتاب و کلاس کتابخانه را به صورت زیر پیاده سازی می کنیم:
class Book {
void seeReviews() {
// logic book reviews
}
void readSample() {
// logic read book-sample
}
}
class Library {
late Book book;
void addBook(Book book) {
// logic add book
}
}
همانطور که مشاهده می کنید کلاس Book به ما اجازه خواندن sample و مشاهده review های کتاب را می دهد. همینطور کلاس Library برای ما امکان افزودن کتاب جدید را فراهم کرده است.
به ظاهر کار تمام است اما مشکلی وجود دارد.
کلاس سطح بالا (Library) به کلاسی سطح پایین (Book) وابسطه شده است. به این ترتیب اصل وارونگی وابستگی نقض می شود.
علاوه بر این اگر فروشگاه از ما بخواهد برای کاربران علاوه بر کتاب امکان استفاده از کتاب صوتی را نیز فراهم کنیم به وضوح اصل دیگری از SOLID را هم نقض کرده ایم.( اصل باز/بسته )
class AudioBook {
void seeReviews() {
// logic audio-book reviews
}
void listenSample() {
// logic listen audio-book-sample
}
}
اکنون بیایید این بار با رعایت اصل اصل وارونگی وابستگی ، ایرادات برنامه فوق را برطرف کنیم.
۲- مثال زیر DIP را رعایت می کند.
برای حل مشکل، یک interface برای کلاس های سطح پایین (کتاب و کتاب صوتی) ایجاد می کنیم. بدین منظور از یک interface به نام Product استفاده می کنیم، که باید هر دو کلاس آن را ایمپلمنت کنند.
برای درک بهتر کد زیر را دنبال کنید:
abstract class Product {
void seeReviews();
void getSample();
}
class Book implements Product {
@override
void seeReviews() {
// logic book reviews
}
@override
void getSample() {
// logic book-sample
}
}
class AudioBook implements Product {
@override
void seeReviews() {
// logic audio-book reviews
}
@override
void getSample() {
// logic audio-book-sample
}
}
همانطور که کد ریفکتور شده کتابخانه را در ادامه خواهید دید، در کلاس Library به جای ارجاع مستقیم به Book و AudioBook از اینترفیس Product استفاده می کنیم. به این صورت امکان افزودن محصولات جدیدی (مثلا مجله و .. ) نیز فراهم می شود و کاربران می توانند آنها را به کتابخانه خود اضافه کنند.
class Library {
late Product product;
void addProduct(Product product) {
// logic add product (can be book or audio-book)
}
}
کد بالا از اصل جایگزینی Liskov نیز پیروی می کند، چون Product را می توان با هر دو زیرشاخه آن بدون شکستن برنامه جایگزین کرد. همزمان، ما اصل وارونگی وابستگی را نیز پیادهسازی کردهایم، زیرا در کد ریفکتور شده ، کلاسهای سطح بالا به کلاسهای سطح پایین وابسته نیستند.
در مقالات بعدی جزئیات پیاده سازی هر بخش رو با کدهای دارت، با همدیگر بررسی می کنیم.
توضیح اصل اول : Single Responsibility Principle
توضیح اصل دوم : Open Closed Principle
توضیح اصل سوم : Liskov Substitution Principle
توضیح اصل چهارم : Interface Segregation Principle
توضیح اصل پنجم : Dependency Inversion Principle
مطلبی دیگر از این انتشارات
استفاده از FutureBuilder در فلاتر
مطلبی دیگر از این انتشارات
چرا من عاشق Flutter شدم ؟
مطلبی دیگر از این انتشارات
در باب factory constructor و static method در dart