شاید برایتان اتفاق افتاده باشد که شرکتی از شما خواسته کدهای برنامه نویس دیگری را تکمیل کنید. اگر شرکت در قبال تمیزی و طراحی کدهای توسعه دهندگان سابق خود حساسیت نداشته باشد، احتمالا از آن تجربه به عنوان یکی از خاطرات تلخ خود یاد خواهید کرد! کدهای کثیف، پر از بوی بد (Bad Smell) در همه جای خود است! البته اینجا شما با یک غذای گندیده مواجه نیستید!
بوی بد در برنامه نویسی اصطلاحا به اشتباهاتی گفته میشود که بعدها باعث بروز مشکلات بزرگتر در کد میشوند. وقتی از عبارت طراحی کد خوب استفاده میکنیم، منظورمان کدی است که بوی بد نداشته باشد (یا حداقل به میزان قابل تحملی بوی بد داشته باشد)!
برای دستیابی به یک کد خوشبو باید اصول طراحی کد خوب را رعایت کنیم. یکی از مجموعه اصولی که برای طراحی کد خوب باید آنها را مد نظر قرار دهیم به اصول SOLID معروف اند. اصول SOLID (بخوانید سالید) عبارت اند از:
در این مطلب به معرفی اصل سوم یعنی اصل جانشینی لیسکف (Liskov Substitution Principle) میپردازیم. اصل جانشینی به یکی از مشکلترین اصول SOLID معروف است اما به هر حال ما در این مقاله آن را به سادهترین شکل ممکن به شما یاد میدهیم. پس نگران نباشید و تا آخر مقاله به دقت همراهمان باشید!
اصل جانشینی لیسکف اولین بار در سال 1987 توسط خانم باربارا لیسکف در کنفرانسش با عنوان “انتزاع (Abstraction) داده” معرفی شد. او بعدها در مقاله ای که به همراه خانم ژانت وینگ منتشر کرد، اصل جانشینی را اینطور تعریف کرد:
“فرض کنید Φ(x) یک خاصیت آبجکت x از نوع کلاس T باشد. در این صورت با فرض اینکه S یک زیر مجموعه از نوع T باشد،Φ(y) باید برای آبجکت یا آبجکتهای y از نوع کلاس S به درستی عمل کند.“
اگر کمی صادقانه صحبت کنیم، تعریف بالا بیشتر شبیه یک جور قاعده آزاردهنده جبری سخت است! اما به زبان ساده میتوانیم آن را اینگونه بیان کنیم:
نقض کردن این قانون درست مثل این است که بخوایم گربه ای را به جای شیر جا بزنیم! گربه نمیتواند غرش کند و شیر نمیتواند میو میو کند. بنابراین وراثت کلاس گربه از شیر احتمالا خیلی به آرمانهای اصل جانشینی نزدیک نیست!
در ابتدای یادگیری برنامه نویسی شی گرا احتمالا همیشه به شما گفته شده هر زمان که رابطه بین دو موجودیت از نوع is-A باشد، نشانه آن است که باید از وراثت یا Inheritance استفاده کنید. اما واقعیت این است که این موضوع در همه مسائل درست از آب در نمیآید و استفاده همیشگی آن در بعضی موارد مشکلاتی به همراه دارد. اصل جانشینی برای این استفاده میشود که مطمئن شویم وراثت همیشه به درستی به کار رفته است.
برای درک بهتر موضوع اجازه بدهید یک مثال ساده بزنیم. فرض کنید در برنامه یک کلاس مستطیل و یک کلاس مربع داریم. به نظر شما رابطه بین این دو کلاس باید چگونه باشد؟ همانطور که میدانید مربع یک نوع مستطیل است. بنابراین با یک رابطه از نوع is-A مواجهیم. اما احتمالا چون به تازگی در یک مقاله بدبینانه مثل این یکی، خوانده اید که استفاده همیشگی از وراثت در این موارد بوی بد تولید میکند، از این که جواب بدهید وراثت میترسید!
اما فرض کنید یک برنامه نویس بی دقت برای حل این مسئله به سرعت از وراثت استفاده کرده باشد. میخواهیم متدی داشته باشیم که مساحت شکل را با استفاده از اتریبیوت طول و عرض آبجکت شکل محاسبه کند. اما مشکل اینجاست که مربع بر خلاف مستطیل برای محاسبه مساحت تنها به عرض احتیاج دارد. حال یا باید به کلاس مستطیل دست بریم و آن را برای قبول عذر مربعها سازگار کنیم و یا برنامه بخاطر بی مقدار ماندن اتریبیوت عرض در متد محاسبه مساحت با Exception مواجه شود. با اعمال روش اول اصل Open/Closed در SOLID را نقض کرده ایم و با اعمال روش دوم برنامه دارای اشکال است.
در این نوشته با اصل سوم از اصول SOLID در طراحی کد آشنا شدید. اصول SOLID مجموعه ای از پنج اصل پایه ای در شیوههای درست برنامه نویسی است. اصول SOLID به شما کمک میکنند از بوهای بد کد یا Code Smells اجنتاب کنید! با رعایت این اصول میتوانید کدهایی تمیز (Clean Code) بنویسید. تغییر در کدها و گسترش آنها با رعایت SOLID ساده، و هزینههای مالی و زمانی آن کاهش مییابد. پس میبینید که یادگیری تک تک این اصول برای یک برنامه نویس تا چه حد حیاتی است. بنابراین بهتر است حتما خواندن این نوع مقالات را جدی بگیرید! آیا شما تجربه ای از بوی بد ناشی از رعایت نکردن اصل جانشینی لیسکف داشته اید؟! از خواندن نظرات شما خوشحال میشویم!
به نظرم مثال اینکه گربه رو به جای شیر جا بزنیم کاملا غلطه
چون نه شیر یک نوع گربه هست
و نه گربه یک نوع شیر هست
بلکه هر دو یک گربه سان هستند
درواقع این درسته که ما یک کلاس گربه سان داشته باشیم و کلاس گربه و شیر هر دو از کلاس گربه سان ارث بری بکنن
بنده هم با شما موافقم. بنظرم مثال مربع و مستطیل بهتر و دقیقتر هست.
ممنون که با ما همراه هستید.