در دنیای مهندسی نرم افزار و برنامه نویسی شئ گرایی پنج قاعده کلی با نام SOLID وجود دارد که یادگیری آنها منجر به نوشتن بهتر نرم افزارها خواهد شد. ما در این مطلب تخصصی از وبسایت راکت قصد داریم شما را با این پنج قاعده آشنا کنیم. همچنین میتوانید برای آشنایی بهتر از دوره آموزشی «اصول طراحی شئ گرا SOLID» استفاده کنید.
اصل طراحی SOLID از رهنمودهای برنامه نویسی شی گرا بوده که برای توسعه نرمافزاری طراحی گردیده و به راحتی قابل نگهداری و گسترش است. همچنین تغییرات سریع و بدون اشکال را شامل میشود.
برای اولین بار SOLID توسط رابرت مارتین در سالهای ۲۰۰۰ معرفی شد. اما بعدا توسط افراد دیگری گسترش پیدا کرد و مفاهیم عمیقتری پیدا کرد. یکی از مهمترین افرادی که در توسعه این مفهوم نقش داشته است Michael Feathers بوده است.
در ارتباط با اینکه هر کدام از حروف SOLID به چه معنا هستند بعدا صحبت خواهیم کرد اما هدف اولیه از ایجاد SOLID این بود که چهار اصل مهم برای بهتر کردن برنامهها را رعایت کند که بدون به کارگیری یک اصل یکپارچه تقریبا غیر ممکن بودند. این چهار مورد عبارت هستند از:
سختی: اجرای حتی یک تغییر کوچک دشوار است، زیرا احتمالا تبدیل به یک آبشار عظیم از تغییرات است.
ظرافت: هر تغییری باعث خراب شدن نرمافزار در بسیاری از موارد میشود، حتی در بخشهایی که از نظر مفهومی به تغییر صورت گرفته مربوط نمیشوند.
عدم تحرک: ما قادر به استفاده مجدد از ماژولهای پروژههای دیگر نیستیم، زیرا این ماژولها وابستگی زیادی دارند.
چسبندگی: اجرای ویژگیهای جدید به روش صحیح دشوار است.
حال بیایید نگاهی به پنج اصل SOLID بیاندازیم. SOLID مخفف واژههای زیر است:
- Single Responsibility
- Open/Closed
- Liskov Substitution
- Interface Segregation
- Dependency Inversion
حال بیایید به صورت جداگانه با هر کدام از این موارد آشنایی پیدا بکنیم.
مورد اول: Single Responsibility
یک کلاس تنها و تنها باید یک دلیل برای تغییر یافتن و یا توسعه داشته باشد. به زبان سادهتر هر کلاس باید تنها یک وظیفه را به دوش بکشد و از یک کلاس برای انجام کارهای متفاوتی استفاده نشود. هدف مورد اول از بیان چنین حالتی این است که انسجام برنامهها و کلاسها را افزایش داده و همه بخشهای برنامه را با وضوح بیشتری همراه کند (چرا که هر کلاس یک وظیفه دارد).
اگر یک کلاس وظایف متعددی داشته باشد، احتمال وجود باگ و خطا را افزایش میدهد زیرا ایجاد تغییر در یکی از وظایف آن میتواند روی بقیه وظایف نیز تاثیر بگذارد بدون اینکه شما متوجه آن شوید.
این اصل قصد دارد تا رفتار را از کلاس جدا کند تا اگر در نتیجه تغییر شما خطایی به وجود آمد، روی بقیه رفتارهای کلاس تاثیر نگذارد.
مورد دوم: Open/Closed
نام کاملتر مورد دوم Open for Extension, Closed for Modification یا «باز برای توسعه، بسته برای ایجاد تغییر» است. در این مورد به صورت واضح ما از ایجاد تغییرات در کدهایی که از قبل وجود داشته و کار میکنند منع میشویم. دلیل این موضوع نیز واضح است چرا که در نهایت ما منجر به ایجاد باگ در کدها خواهیم شد.
البته این بدان معنا نیست که اگر در کدهای موجود یک باگ وجود داشته باشد شما نباید به آن دست بزنید. چرا که در صورت وجود باگ شما در مرحله اول باید آن را حل نمایید.
تغییر رفتار کنونی یک کلاس روی کلیه سیستمهایی که از آن کلاس بهره میبرند تاثیر میگذارد؛ اگر میخواهید کلاستان توابع بیشتری را اجرا کند، راهحل مناسب این است که تعداد توابع را افزایش دهید نه اینکه توابع را تغییر دهید.
این اصل قصد دارد تا رفتار یک کلاس/تابع را گسترش دهد بدون اینکه رفتار کنونی آن را تغییر دهد. این روش برای جلوگیری از تولید باگ هنگامی که کلاس/تابع در حال استفاده است، استفاده می شود.
مورد سوم: Liskov Substitution
در سومین گزینه مربوط به SOLID که قاعده Liskov نیز نام دارد شما باید به امر ارث بری توجه بالایی داشته باشید.
در این قاعده بیان شده که نوع خروجی از کلاس فرزند نباید با نوع خروجی کلاس پدر تفاوت زیادی داشته باشد. برای مثال تصور بکنید که خروجی کلاس پدر یک فنجان قهوه است در این صورت خروجی کلاس فرزند نباید یک کاسه سوپ باشد! در بهترین شرایط کلاس فرزند میتواند یک فنجان نسکافه به کاربر بدهد چرا که نزدیکی بسیار زیادی به خود قهوه دارد.
کلاس فرزند باید بتواند درخواستهای یکسانی را پردازش کند و همان نتیجه کلاس پدر را تحویل دهد یا نتیجه حاصل شده از همان نوع باشد.
اگر کلاس فرزند این شرایط را برآورده نکند، این بدان معناست که کلاس فرزند کاملا تغییر یافته و این اصل را نقض میکند.
این اصل قصد دارد تا یکپارچگی را تقویت کند به گونهای که کلاس پدر یا کلاس فرزند بتوانند بدون هیچ خطایی از همان روشها استفاده کنند.
مورد چهارم: Interface Segregation
این مورد را در سال ۱۹۹۶ رابرت مارتین شخصا تئوریزه کرد. براساس این قاعده مشتری نباید وابسته به اینترفیس یا رابطی باشد که در حال استفاده از آن نیست. هدف نهایی این است که رابطهای که به نادرستی نوشته شدهاند حذف شده و همه چیز با وضوح بیشتری ارائه شود.
کلاینت باید تنها متدهایی را که نیاز دارد مشاهده کرده و کلاسهای فرزند نیز تنها باید ویژگیهایی که مورد نیاز کلاینت است را به ارث ببرد. در این حالت شما دیگر با کلاسهای پیچیده و شلخته همراه نخواهید بود و ساختار کدهایتان بسیار بهبود میبخشد.
هدف از این اصل جدا کردن دستورالعملها به دستههای کوچکتر است تا یک کلاس تنها اعمالی را انجام دهد که به آنها نیاز دارد.
مورد پنجم: Dependency Inversion
در این قاعده به صورت صریح گفته میشود که ماژولهای سطح بالا نباید به ماژولهای سطح پایین وابستگی داشته باشند. هر دو این ماژولها باید مبتنی بر Abstraction باشند. از طرفی دیگر Abstraction نباید به جزئیات وابستگی داشته باشد بلکه عکس این موضوع باید صادق باشد.
برای درک چهار اصطلاح ماژول سطح بالا، پایین، Abstraction و جزئیات توضیحات زیر را مطالعه کنید.
High-level Module (or Class): کلاسی که عملی را با یک ابزار پیاده سازی میکند
Low-level Module (or Class): ابزاری که برای پیادهسازی عمل به آن نیاز است
Abstraction: نشان دهنده interface است که دو کلاس را به هم متصل میکند
Details: نحوه کار یک ابزار در بخش جزئیات نشان داده میشود
هدف از این اصل کاهش وابستگی کلاسهای پیشرفته به کلاسهای سطح پایین با معرفی یک interface است.
در پایان
یادگیری هر کدام از مفاهیمی که باعث بهبود و خواناتر شدن کدهایتان میشود در نهایت بهبود کلی کدهایتان را به ارمغان خواهد آورد. همواره این موضوع را به یاد داشته باشید که بهتر است از بهترین تکنیکها استفاده کرده و هیچگاه سراغ کدهای کثیف نروید.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید