اصل Liskov Substitution Principle در SOLID چیست؟
شاید برایتان اتفاق افتاده باشد که شرکتی از شما خواسته کدهای برنامه نویس دیگری را تکمیل کنید. اگر شرکت در قبال تمیزی و طراحی کدهای توسعه دهندگان سابق خود حساسیت نداشته باشد، احتمالا از آن تجربه به عنوان یکی از خاطرات تلخ خود یاد خواهید کرد! کدهای کثیف، پر از بوی بد (Bad Smell) در همه جای خود است! البته اینجا شما با یک غذای گندیده مواجه نیستید!
بوی بد در برنامه نویسی اصطلاحا به اشتباهاتی گفته میشود که بعدها باعث بروز مشکلات بزرگتر در کد میشوند. وقتی از عبارت طراحی کد خوب استفاده میکنیم، منظورمان کدی است که بوی بد نداشته باشد (یا حداقل به میزان قابل تحملی بوی بد داشته باشد)!
برای دستیابی به یک کد خوشبو باید اصول طراحی کد خوب را رعایت کنیم. یکی از مجموعه اصولی که برای طراحی کد خوب باید آنها را مد نظر قرار دهیم به اصول SOLID معروف اند. اصول SOLID (بخوانید سالید) عبارت اند از:
- Single Responsibility Principle یا اصل تک وظیفگی (SRP)
- Open/Closed Principle یا اصل باز و بسته بودن (OCP)
- Liskov Substitution Principle یا اصل جانشینی لیسکف (LSP)
- Interface Segregation Principle یا اصل تفکیک Interface (ISP)
- Dependency Inversion Principle یا اصل وارونه کردن وابستگی (DIP)
در این مطلب به معرفی اصل سوم یعنی اصل جانشینی لیسکف (Liskov Substitution Principle) میپردازیم. اصل جانشینی به یکی از مشکلترین اصول SOLID معروف است اما به هر حال ما در این مقاله آن را به سادهترین شکل ممکن به شما یاد میدهیم. پس نگران نباشید و تا آخر مقاله به دقت همراهمان باشید!
Liskov Substitution Principle
اصل جانشینی Liskov اولین بار در سال ۱۹۸۷ توسط خانم باربارا لیسکف در کنفرانسش با عنوان “انتزاع (Abstraction) داده” معرفی شد. او بعدها در مقاله ای که به همراه خانم ژانت وینگ منتشر کرد، اصل جانشینی را اینطور تعریف کرد:
اگر کمی صادقانه صحبت کنیم، تعریف بالا بیشتر شبیه یک جور قاعده آزاردهنده جبری سخت است! اما به زبان ساده میتوانیم آن را اینگونه بیان کنیم:
نکته :
اصل جانشینی Liskov میگوید: آبجکتهای کلاسهای والد و فرزند، باید بتوانند بدون به وجود آمدن هیچ مشکلی در کدها به جای هم استفاده شوند.
چرا باید از اصل جانشینی استفاده کنیم
در ابتدای یادگیری برنامه نویسی شی گرا احتمالا همیشه به شما گفته شده هر زمان که رابطه بین دو موجودیت از نوع is-A باشد، نشانه آن است که باید از وراثت یا Inheritance استفاده کنید. اما واقعیت این است که این موضوع در همه مسائل درست از آب در نمیآید و استفاده همیشگی آن در بعضی موارد مشکلاتی به همراه دارد. اصل جانشینی برای این استفاده میشود که مطمئن شویم وراثت همیشه به درستی به کار رفته است.
برای درک بهتر موضوع اجازه بدهید یک مثال ساده بزنیم. فرض کنید در برنامه یک کلاس مستطیل و یک کلاس مربع داریم. به نظر شما رابطه بین این دو کلاس باید چگونه باشد؟ همانطور که میدانید مربع یک نوع مستطیل است. بنابراین با یک رابطه از نوع is-A مواجهیم. اما احتمالا چون به تازگی در یک مقاله بدبینانه مثل این یکی، خوانده اید که استفاده همیشگی از وراثت در این موارد بوی بد تولید میکند، از این که جواب بدهید وراثت میترسید!
اما فرض کنید یک برنامه نویس بی دقت برای حل این مسئله به سرعت از وراثت استفاده کرده باشد. میخواهیم متدی داشته باشیم که مساحت شکل را با استفاده از اتریبیوت طول و عرض آبجکت شکل محاسبه کند. اما مشکل اینجاست که مربع بر خلاف مستطیل برای محاسبه مساحت تنها به عرض احتیاج دارد. حال یا باید به کلاس مستطیل دست بریم و آن را برای قبول عذر مربعها سازگار کنیم و یا برنامه بخاطر بی مقدار ماندن اتریبیوت عرض در متد محاسبه مساحت با Exception مواجه شود. با اعمال روش اول اصل Open/Closed در SOLID را نقض کرده ایم و با اعمال روش دوم برنامه دارای اشکال است.
نتیجه گیری
در این نوشته با اصل سوم از اصول SOLID در طراحی کد آشنا شدید. اصول SOLID مجموعه ای از پنج اصل پایه ای در شیوههای درست برنامه نویسی است. اصول SOLID به شما کمک میکنند از بوهای بد کد یا Code Smells اجنتاب کنید! با رعایت این اصول میتوانید کدهایی تمیز (Clean Code) بنویسید. تغییر در کدها و گسترش آنها با رعایت SOLID ساده، و هزینههای مالی و زمانی آن کاهش مییابد. پس میبینید که یادگیری تک تک این اصول برای یک برنامه نویس تا چه حد حیاتی است.