قوانین-پنج‌گانهٔ-SOLID-در-برنامه-نویسی-شی-گرا

قوانین پنج‌گانهٔ SOLID در برنامه نویسی شی گرا

SOLID دربرگیرندهٔ اصولی در برنامه‌نویسی شییٔ‌گرایی است که در اوایل سال 2000 توسط مهندسی به نام Robert Martin ابداع شد که تحت عنوان Uncle Bob یا «عمو باب» نیز شناخته می‌شود. وقتی این اصول به درستی در کنار یکدیگر به کار گرفته شوند، این امکان را به برنامه‌نویس یا توسعه‌دهنده می‌دهند تا با سهولت بیشتری دست به توسعهٔ نرم‌افزار بزند مضاف بر اینکه به‌کارگیریِ این اصول امکانی را به برنامه‌نویسان خواهد داد تا با رویکردی چابک به توسعهٔ نرم‌افزارهای خود پرداخته، از مرتکب شدن اشتباهات کوچک جلوگیری کنند و در صورت نیاز هم به سادگی اقدام به بازنویسی کدهای خود کنند (در فصل آینده، با مفهوم برنامه‌نویسی چابک بیشتر آشنا خواهیم شد.) به طور کلی، SOLID مخفف اصطلاحات زیر است:

  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Single Responsibility Principle
این قانون که به طور خلاصه SRP نیز نامیده می‌شود، حاکی از آن است که یک کلاس باید صرفاً یک وظیفه بیشتر نداشته باشد که در این صورت، کلاس‌ها فقط و فقط به خاطر ایجاد تغییر در وظیفه‌ای که انجام می‌دهند دستخوش تغییر خواهند شد نه چیز دیگر! کلاس‌ها می‌توانند فیچرهای مختلفی داشته باشند اما تمامی آن‌ها باید مربوط به یک حوزه بوده و مرتبط به هم باشند که در نهایت با محترم شمردن چنین قانونی، برنامه‌نویسان دیگر قادر نخواهند بود تا کلاس‌های اصطلاحاً همه‌فن‌حریف بنویسند.

Open-Closed Principle
هر کلاسی باید برای توسعه یافتن قابلیت‌هایش اصطلاحاً Open بوده و دست برنامه‌نویس برای افزودن فیچرهای جدید به آن باز باشد اما اگر وی خواست تا تغییری در کلاس ایجاد کند، چنین امکان باید Closed بوده و او اجازهٔ چنین کاری را نداشته باشد. فرض کنیم نرم‌افزاری نوشته‌ایم که دارای چندین کلاس مختلف است و نیازهای اپلیکیشن‌مان را مرتفع می‌سازند اما به جایی رسیده‌ایم که نیاز داریم قابلیت‌های جدید به برنامهٔ خود بیفزاییم. بر اساس این قانون، دست‌مان برای تغییر یا بهتر بگوییم افزودن فیچرهای جدید به کلاس مد نظر باز است در حالی که این قابلیت‌های جدید باید در قالب افزودن کدهای جدید صورت پذیرد نه ریفکتور کردن و تغییر کدهای قبلی!

برای روشن‌تر شدن این مسأله مثالی می‌زنیم. پیش از این با مفهوم وراثت در برنامه‌نویسی آشنا شدیم. فرض کنیم کلاسی داریم تحت عنوان BankAccount که دو کلاس دیگر تحت عناوین SavingAccount و InverstmentAccount از آن ارث‌بری می‌کنند و قصد داریم کلاس جدیدی تحت عنوان CurrentAccount ایجاد کنیم که از BankAccount ارث‌بری می‌کند اما این کلاس جدید دارای یکسری قابلیت‌هایی است که در کلاس والد دیده نشده‌اند که در چنین شرایطی به جای آنکه قابلیت‌های مد نظر جدید را به کلاس والد بیفزاییم، نیاز خود را از طریق افزودن قابلیت‌های جدید در همان کلاس فرزند عملی می‌کنیم. به عبارتی، هرگز دست به تغییر کدهای موجود نزده و قانون Open/Closed را هم به رسمیت شناخته‌ایم به طوری که کلاس مد نظرمان برای توسعه باز است اما برای اِعمال هر گونه تغییری بسته است.

Liskov Substitution Principle
این اصل حاکی از آن است که کلاس‌های فرزند باید آن‌قدر کامل و جامع از کلاس والد خود ارث‌بری کرده باشند که به سادگی بتوان همان رفتاری که با کلاس والد می‌کنیم را با کلاس‌های فرزند نیز داشته باشیم به طوری که اگر در شرایطی قرار گرفتید که با خود گفتید کلاس فرزند می‌تواند تمامی کارهای کلاس والدش را انجام دهد به جزء برخی موارد خاص، اینجا است که این اصل از SOLID را نقض کرده‌اید.

Interface Segregation Principle
پیش از این هم گفتیم که اینترفیس‌ها فقط مشخص می‌کنند که یک کلاس از چه متدهایی حتماً باید برخوردار باشد. در همین راستا و بر اساس این قانون، چندین اینترفیس تک‌منظوره به مراتب بهتر است از یک اینترفیس چندمنظوره است به طوری که اگر یک اینترفیس چندمنظورهٔ کامل و جامع داشته باشیم و سایر کلاس‌های ما از آن اصطلاحاً implementsکنند،‌ در چنین صورتی ممکن است برخی خصوصیات، متدها و رفتارها را به برخی کلاس‌هایی که اصلاً نیازی به آن‌ها ندارند تحمیل کنیم اما اگر از چندین اینترفیس تخصصی استفاده کنیم، به سادگی می‌توانیم از هر اینترفیسی که نیاز داشته باشیم در کلاس‌های مد نظر خود استفاده نماییم و در صورتی هم کلاسی وجود داشت که نیاز به استفاده از چندین اینترفیس مختلف داشت، دست ما باز خواهد بود تا آن کلاس را از چندین اینترفیس implements کنیم.

Dependency Inversion Principle
درک این اصل از اصول پنج‌گانهٔ SOLID کمی دشوارتر به نظر می‌رسد و برخی تازه‌کارها آن را با Dependency Injection اشتباه می‌گیرند. به طور خلاصه، در OOP باید تمام تلاش خود را به کار بندیم تا Dependency (وابستگی) را مابین کلاس‌ها، ماژول‌ها و آبجکت‌های سطح بالا با ماژول‌های سطح پایین به حداقل برسانیم که با این کار، اِعمال تغییرات در آینده به مراتب راحت‌تر صورت خواهد پذیرفت.


برچسب ها :


اشتراک گذاری :