برنامه نویسی و طراحی وب

اصل تفکیک رابط‌ها در اصول SOLID

اصول SOLID در برنامه نویسی شئ‌گرا چیست؟
اصل تک مسئولیتی (Single Responsibility Principle)
اصل باز – بسته (Open/Closed Principle)
اصل جایگزینی لیسکوف (Liskov Substitution Principle)
اصل تفکیک رابط‌ها (Interface Segregation Principle)
اصل وارونگی وابستگی (Dependency Inversion Principle)

اصل Interface Segregation Principle در اصول SOLID چیست؟

Interface Segregation Principle یا به اختصار ISP که در فارسی به آن «اصل تفکیک رابط‌ها» یا «اصل تفکیک اینترفیس‌ها» یا «اصل جداسازی واسط‌ها» هم گفته می‌شود، یک اصل مهندسی نرم‌افزار و اصل چهارم از اصول طراحی SOLID است.

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

اصل ISP ایجاد چندین رابط کوچکتر و خاص را به جای داشتن یک رابط همه منظوره تشویق می‌کند. زیرا یک رابط همه منظوره می‌تواند منجر به پیچیدگی‌ها و وابستگی‌های ناخواسته شود.

ایده کلیدی پشت ISP این است که یک کلاس فقط باید متدهایی را داشته باشد که مربوط به آن کلاس است و به آنها نیاز داشته باشد. پیاده سازی متدهایی که به آن کلاس مربوط نیست می‌تواند موجب پیچیدگی و کاهش خوانایی کدها شود.

به طور خلاصه، ISP بر اهمیت طراحی رابط‌های انعطاف‌پذیر و ماژولار تأکید می‌کند که به شدت بر نیازهای خاص کلاس‌ها متمرکز شده و وابستگی‌ها را کمتر می‌کند.

یک مثال از اصل تفکیک رابط‌ها در دنیای واقعی

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

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

پس بهتر است این ابزار فقط سوکت یا سوکت‌هایی را داشته باشد که واقعا به آنها احتیاج دارد و سایر سوکت‌ها را حذف کند یا در ابزار‌های جداگانه توسعه داده بدهد.

یک مثال از اصل تفکیک رابط‌ها در زبان برنامه نویسی

حالا اصل تفکیک رابط‌ها را در برنامه‌نویسی مثال می‌زنم تا آن را بهتر درک کنیم.

در این مثال، ما اصل ISP را با استفاده از حیوانات به عنوان سناریو نشان می‌دهیم.

در اینجا یک رابط Animal برای حیوانات داریم که دو متد دارد: متد makeSound() برای صدای حیوانات و متد move() برای حرکت حیوانات است.

interface Animal {
  public function makeSound();
  public function move();
}

در مرحله بعد، دو رابط اضافی SwimmableAnimal برای حیواناتی که شنا می‌کنند و FlyableAnimal برای حیواناتی که پرواز می‌کنند، تعریف می‌کنیم که رابط Animal را گسترش می‌دهند.

interface SwimmableAnimal extends Animal {
  public function swim();
}

interface FlyableAnimal extends Animal {
  public function fly();
}

رابط SwimmableAnimal یک متد swim() را تعریف می‌کند که نشان دهنده توانایی شنا کردن است. به طور مشابه، رابط FlyableAnimal یک متد fly() را تعریف می‌کند که نشان دهنده توانایی پرواز است.

سپس سه کلاس Dog برای «سگ»، Fish برای «ماهی» و Bird برای «پرنده» ایجاد می‌کنیم که نشان دهنده گونه‌های مختلف حیوانات است.

class Dog implements Animal {
  public function makeSound() {
    echo "Bark";
  }
  
  public function move() {
    echo "Walking";
  }
}

کلاس Dog رابط Animal را پیاده سازی می‌کند و تمام متدهای تعریف شده در رابط Animal را پیاده‌سازی می‌کند. یعنی کلاس Dog «توانایی ایجاد صدا» و «توانایی حرکت کردن»» را دارد.

class Fish implements SwimmableAnimal {
  public function makeSound() {
    echo "Blub";
  }
  
  public function move() {
    echo "Swimming";
  }
  
  public function swim() {
    echo "Swimming";
  }
}

کلاس Fish رابط SwimmableAnimal را پیاده‌سازی می‌کند که رابط Animal را گسترش می دهد. این به این معنی است که کلاس ماهی «توانایی ایجاد صدا» و «توانایی حرکت کردن» را دارد. اما علاوه بر این دو متد، یک متد هم برای «توانایی شنا کردن» دارد.

class Bird implements FlyableAnimal {
  public function makeSound() {
    echo "Chirp";
  }
  
  public function move() {
    echo "Flying";
  }
  
  public function fly() {
    echo "Flying";
  }
}

کلاس Bird رابط FlyableAnimal را پیاده‌سازی می‌کند که رابط Animal را گسترش می‌دهد. این بدان معناست که کلاس Bird «توانایی ایجاد صدا» و «توانایی حرکت کردن» را دارد. اما علاوه بر این دو متد، یک متد هم برای «توانایی پرواز کردن» دارد.

با پیروی از اصل جداسازی رابط (ISP)، ما در اینجا به جای داشتن یک رابط واحد که همه ویژگی‌ها را برای همه حیوانات داشته باشد، چندین رابط ایجاد کرده‌ایم که ویژگی‌های خاص انواع مختلف حیوانات را تعریف می‌کند.

به این ترتیب، کلاسی که فقط رابط Animal را پیاده‌سازی می‌کند، تنها نیاز به پیاده‌سازی ویژگی‌های اساسی دارد که همه حیوانات دارند، در حالی که کلاسی که SwimmableAnimal یا FlyableAnimal را پیاده‌سازی می‌کند، می‌تواند ویژگی‌های اضافی مخصوص آن حیوانات را پیاده‌سازی کند.

در نهایت کد ما به صورت کد زیر می‌شود:

interface Animal {
  public function makeSound();
  public function move();
}

interface SwimmableAnimal extends Animal {
  public function swim();
}

interface FlyableAnimal extends Animal {
  public function fly();
}

class Dog implements Animal {
  public function makeSound() {
    echo "Bark";
  }
  
  public function move() {
    echo "Walking";
  }
}

class Fish implements SwimmableAnimal {
  public function makeSound() {
    echo "Blub";
  }
  
  public function move() {
    echo "Swimming";
  }
  
  public function swim() {
    echo "Swimming";
  }
}

class Bird implements FlyableAnimal {
  public function makeSound() {
    echo "Chirp";
  }
  
  public function move() {
    echo "Flying";
  }
  
  public function fly() {
    echo "Flying";
  }
}

این اصل موجب می‌شود که نیازی به نوشتن کدهای اضافه نداشته باشیم و می‌تواند پیاده سازی کدها را ساده‌تر و قابل درک‌تر کند که باعث ایجاد اتصال بین اجزا می‌شود.

سیدرضا بازیار

من مهندس فناوری اطلاعات و توسعه دهنده Back end هستم. حس کنجکاوی، تمایل به کشف دنیاهای جدید و علاقه زیادی به حل چالش‌های گوناگون در زمینه‌های مختلف داشتم باعث شد وارد حرفه‌ی پرچالش و عمیق برنامه‌نویسی بشوم و هر روز بیشتر در این دنیای بزرگ غرق می‌شوم. در حال حاضر با مهارت هایی نرم مانند کار تیمی، قدرت مذاکره، خوش برخوردی، پرورش ایده و مهارت های سخت مانند PHP, OOP, Clean Code, Design Patterns و ... با علاقه مشغول به فعالیت در جامعه متن‌باز هستم. معتقدم هر روز بیشتر از دیروز، عمده کارهای انسان‌ها توسط ربات‌ها انجام خواهد شد، به همین دلیل سعی میکنم اسکریپت‌های زیادی با PHP ، Shell Scripting و Bash Scripting بنویسم و سعی می‌کنم کارهایی که برای انسان‌ها سخت و زمانبر هستند،‌ با ربات‌ها در سریعترین زمان و کمترین هزینه ممکن انجام بدهم. در این مسیر با زبان‌های برنامه نویسی مانند C++ و پایتون هم کمی کار کرده‌ام و با سیستم های مدیریت محتوای زیادی مانند وردپرس، جوملا، ویبولتین و... هم به صورت حرفه‌ای درگیر بوده‌ام. گهگاهی سعی میکنم ربات‌هایی طراحی کنم که اطلاعات عظیمی را از طریق اسکرپینگ به دیتابیس های مختلف منتقل میکنند و از طریق API در پلتفرم های مختلف پردازش می‌شوند. در 10 سال گذشته سابقه زیادی در طراحی سایت و فروشگاه‌های اینترنتی، سئو و بهینه سازی، تست امنیت وب‌سایت‌ها، دیجیتال مارکتینگ و... داشته‌ام. خوشحال میشم بتونم تجربیات خودم رو از طریق این وبلاگ در اختیار همه شما عزیزان قرار بدهم.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *