۲ دیدگاه نظر زهرا فرحمند
اصل تفکیک Interface در SOLID
اصل تفکیک Interface در SOLID

اصل تفکیک Interface در SOLID : معمولا برنامه نویسان تازه کار در اوایل دوران برنامه نویسی خود، دچار مشکلاتی می‌شوند. کدها در یک جای کار به بن بست می‌خورند. اوایل کار، برنامه نویس نامبرده (!) شروع به حل مسئله با روش‌های خلاقانه مخصوص خود می‌کند! تا جایی که یک جای پروسه این روش‌های خلاقانه به هم پیچ می‌خورند! در بهترین حالت حتی با رفع پیچ خوردگی‌ها و تحویل پروژه، یک جای کار می‌لنگد: تغییر در کدها به یک کابوس شبانه شده است! برنامه نویس تازه کار با خود فکر می‌کند که همه راه را درست رفته. پس مشکل از کجاست؟ در این وضعیت برنامه نویسان تازه کار به دو دسته تقسیم می‌شوند:

  • آدم‌های عاقلی که به سراغ یک حرفه کم دردسرتر می‌روند
  • آدم‌های سمجی که در مورد کد تمیز (Clean Code) مطالعه می‌کنند!

مسلما این مطلب را برای دسته دوم نوشته ایم! یکی از اصول مهمی که برای دستیابی به کد تمیز مطرح است به اصول SOLID مشهور است. SOLID بر اساس این پنج اصل در طراحی کد (Code Design) تعریف می‌شود:

  1. Single Responsibility Principle یا اصل تک وظیفگی (SRP)
  2. Open/Closed Principle یا اصل باز و بسته بودن (OCP)
  3. Liskov Substitution Principle یا اصل جانشینی لیسکف (LSP)
  4. Interface Segregation Principle یا اصل تفکیک Interface (ISP)
  5. Dependency Inversion Principle یا اصل وارونه کردن وابستگی (DIP)

در این مطلب به معرفی اصل چهارم یعنی اصل تفکیک Interface می‌پردازیم.

اصل تفکیک Interface چیست

بر اساس اصل تفکیک Interface ما نباید از Interface هایی استفاده کنیم که بیش از حد چاق هستند! رابرت مارتین (Robert Martin) مشهور به عمو باب در این باره می‌گوید:

کاربران نباید مجبور به استفاده از Interface هایی شوند که از آن‌ها استفاده نمی‌کنند.

برای رسیدن به این هدف هر Interface باید تنها یک کار را انجام دهد. حتی در ایده آل‌ترین حالت ممکن، بهتر است هر Interface تنها از یک متد ابسترکت (abstract) تشکیل شده باشد. در صورتی که یک Interface اصطلاحا چاق باشد (Fat Interface) کلاس‌های پیاده کننده را مجبور به پیاده سازی تعداد زیادی متد می‌کند که قرار نیست استفاده ای از آن‌ها بشود.

Interface Segregation چیست

ممکن است تصور کنید که این همان اصل اول از اصول SOLID یعنی همان اصل تک وظیفگی (Single Responsibility Principle) است. در مورد کارایی حق با شماست! اما در مورد کاربرد، این دو اصل یک تفاوت کوچک دارند. اصل تک وظیفگی در مورد همه ماژول‌های برنامه شامل کلاس ها، متد‌ها و... صحبت می‌کند. وظیفه اصل اول ایجاد انسجام در واحدهای سازنده برنامه است. اما اصل چهارم در مورد Interface‌ها و دردسرهای پیاده سازی آن‌ها صحبت می‌کند.

مثالی از اصل تفکیک Interface

فرض کنید یک Interface با عنوان ماشین یا Car نوشته ایم. تمام انواع کلاس‌های ماشین مثل GasCar یا ElectricCar باید این Interface را پیاده سازی یا Implement کنند. Interface ماشین را به این صورت می‌نویسیم:

interface Car {
    public function getFuel();
    public function shiftGear();
    public function steer();
}

در مورد کلاس GasCar همه چیز به درستی پیش می‌رود. چون یک ماشین با سوخت گازی می‌تواند سوخت گیری کند، دنده عوض کند و رانده شود:

class GasCar implements Car {
    public function getFuel()
    {
        // getting fuel code
    }
    public function shiftGear()
    {
        // shifting gear code
    }
    public function steer()
    {
        // steering code
    }
}

اما اگر بخواهیم یک کلاس ElectricCar داشته باشیم قضیه کمی فرق می‌کند. ماشین الکتریکی احتیاجی به سوخت گیری ندارد. بنابراین به متد getFuel() احتیاجی نیست. متد getFuel() باید یا مقدار null را بازگرداند، یا خطایی ارسال کند. بنابراین در این مثال اصل تفکیک Interface را نقض کرده ایم. برای حل ماجرا کافی است کمی Interface ماشینمان را لاغر کنیم! بنابراین این Interface چاق را به دو اینترفیس خوش تیپ می‌شکنیم:

  • Interface ماشین سوختی با نام FuelCar
  • Interface راندن ماشین با نام RideCar

ضمنا در مورد ماشین هایی که علاوه بر وظیفه سوخت گیری به رانده شدن هم علاقه دارند نگران نباشید! در شی گرایی می‌توان به راحتی چندین Interface را توسط یک کلاس پیاده سازی کرد. بنابراین Interface‌ها را دوباره به این صورت می‌نویسیم:

interface FuelCar {
    public function getFuel();
}
interface RideCar {
    public function shiftGear();
    public function steer();
}

در شی گرایی هر کلاس می‌تواند چندین Interface را پیاده سازی کند.

حال دو کلاس GasCar و ElectricCar به این صورت در می‌آیند:

class GasCar implements FuelCar,RideCar {
   // methods: getFuel(), shiftGear() and steer()
}
class ElectricCar implements RideCar {
   // methods: shiftGear() and steer()
}

اگر می‌خواهید بیشتر بدانید : 

نتیجه گیری

در این مطلب به معرفی اصل تفکیک Interface یا ISP پرداختیم. همانطور که دیدیم این اصل می‌تواند از میزان کدهای اضافی کم کند و حجم کد را کاهش دهد. بر اساس این اصل Interface‌های چاق همه منظوره باید به Interface‌های کوچک تک منظوره شکسته شوند. آیا شما با رعایت نکردن این اصل به مشکل بر خورده اید؟ از خواندن نظرات شما خوشحال می‌شویم!

۲ دیدگاه
ما همه سوالات و دیدگاه‌ها رو می‌خونیم و پاسخ میدیم
محمد نقلانی ۲۴ اردیبهشت ۱۳۹۸، ۰۸:۰۵

این مقاله خیلی بدر بخور بود . خواهشا بقیه اصل هارو هم تو برنامه داشته باشید و یه پیشنهاد امکانش هست که منابع رو در انتهای مقالات ذکر کنید که بشه به صورت مستقیم هم به منابع دسترسی داشت ( البته میدنم هم میشه سرچ کرد ولی ذکر منابع خیلی کمک بیشتری میکنه چون از صحت و کامل بودنش اطمینان کامل داریم )

زهرا فرحمند ۲۸ اردیبهشت ۱۳۹۸، ۰۵:۵۵

با تشکر جناب نقلانی عزیز. در صورتی که مقاله ای ترجمه مستقیم و خالص باشه منبع حتما ذکر میشه :)

  • اصل تفکیک Interface چیست
  • نتیجه گیری
اشتراک گذاری مقاله در :