به نام خدا
در این آزمایش هدف بر آن است که دانشجویان با به کارگیری اصول SOLID در یک پروژهی عملی ساده آشنا شوند.
آشنایی اولیه با مفاهیم برنامه نویسی و طراحی شیگرا که دانشجویان قبلاً در درس برنامهسازی پیشرفته با آن آشنا شدهاند.
- یک Java IDE مانند IntelliJ IDEA و یا Eclipse به همراه jdk حداقل نسخه ۸
برای آشنایی با این اصول و آشنایی با منابع مناسب به اینجا مراجعه کنید.
در این آزمایش شما خواهید آموخت که چگونه میتوانید با به کارگیری اصول SOLID، نرمافزارهایی را بسازید که از نظر قابلیت نگهداری و بهبود، در وضعیت مطلوبی باشند و مدیریت تغییرات در آنها به آسانی میسر باشد (شک نکنید که به کارگیری این اصول اساسی و بسیاری دیگر از اصول مهندسی نرم افزار، باعث تفاوت شما با سایر همکارانتان خواهد شد)
میتوانید برنامه را از اینجا بارگیری کنید.
صورت آزمایش در درس افزار بارگزاری شده است و میتوانید برای تحویل گزارش (با در نظر گرفتن ملاحظات گفته شده) از قالب های زیر استفاده کنید.
تغییراتی را که در کد فعلی برنامه میدهید، در جدول زیر ثبت کنید و در نهایت تعداد کل تغییرات را اعلان کنید.
- توجه: مواردی که به عنوان تغییرات باید اعلان شود شامل این موارد هستند:
- ساخت کلاس جدید
- افزودن تابع جدید به کلاس و یا واسط (برای توابع جدید صرفا اعلام تغییر کنید)
- هر خطوط پیاپیای که در تابع main و برای افزودن یک قابلیت جدید اضافه میکنید. به عنوان مثال اگر سه خط را به منظور تشخیص نوع پیام اضافه میکنید، آن سه خط را در قالب یک تغییر اعلام کنید (البته جزییات آن را در ستون «شرحی کوتاه از تغییر» توضیح دهید).
ردیف |
محل اعمال تغییرات (کلاس/واسط) |
عنوان تغییر |
شرحی کوتاه از تغییر |
۱ |
OrderService |
افزودن تابع جدید |
افزودن یک تابع به نام onPhoneOrderRegister برای ثبت سفارشات تلفنی در واسط |
۲ |
OrderService |
افزودن یک تابع جدید |
افزودن یک تابع به نام onPhoneOrderPayment برای پرداخت سفارشات تلفنی |
۳ |
PhoneOrderService |
ساخت یک کلاس جدید |
یک کلاس برای پیاده سازی متود های phone |
۴ |
PhoneOrderService |
افزودن تابع جدید |
افزودن یک تابع به نام onPhoneOrderRegister برای ثبت سفارشات تلفنی |
۵ |
PhoneOrderService |
افزودن یک تابع جدید |
افزودن یک تابع به نام onPhoneOrderPayment برای پرداخت سفارشات تلفنی |
۶ |
OnlineOrderService |
افزودن تابع جدید |
افزودن یک تابع به نام onPhoneOrderRegister برای ثبت سفارشات تلفنی |
۷ |
OnlineOrderService |
افزودن یک تابع جدید |
افزودن یک تابع به نام onPhoneOrderPayment برای پرداخت سفارشات تلفنی |
۸ |
OnSiteOrderService |
افزودن تابع جدید |
افزودن یک تابع به نام onPhoneOrderRegister برای ثبت سفارشات تلفنی |
۹ |
OnSiteOrderService |
افزودن یک تابع جدید |
افزودن یک تابع به نام onPhoneOrderPayment برای پرداخت سفارشات تلفنی |
۱۰ |
PhoneOrderService |
افزودن تابع جدید |
پیاده سازی تابع onlineOrderRegister |
۱۱ |
PhoneOrderService |
افزودن یک تابع جدید |
پیاده سازی تابع onSiteOrderPayment |
۱۲ |
PhoneOrderService |
افزودن تابع جدید |
پیاده سازی تابع onSiteOrderRegister |
۱۳ |
PhoneOrderService |
افزودن یک تابع جدید |
پیاده سازی تابع onlineOrderPayment |
۱۴ |
Main |
پیاده سازی منطق ثبت سفارش تلفنی |
در قسمت اول باید سرویس تلفنی را به عنوان یک سرویس موجود نشان داده و اجازه انتخاب آن را بدهیم |
۱۵ |
Main |
پیاده سازی منطق پرداخت سفارش تلفنی |
در قسمت بعدی باید اگر سرویس تلفنی انتخاب شد پرداخت آن انجام شود |
مجموع تعداد تغییرات: ۱۵
در خصوص این برنامهای که نوشته شده بود و شما یک قابلیت به آن اضافه کردید، بر اساس اصول SOLID موارد نقض و یا محقق شدن هر کدام از آن اصول را بیان کنید. در بیان موارد تحقق و نقض، علت تحقق و یا نقض را نیز به صورت کامل توضیح دهید:
اصل 1 Single Responsibility |
موارد تحقق |
کلاس های food و order (این کلاس ها فقط ساختار کلاس را مشخص کرده اند و در آنها شی ساخته می شود. هر کدام هم مربوط به یک کانسپت است.) |
موارد نقض |
کلاس main - تابع main |
|
اصل 2 Open-Close Principle (OCP) |
موارد تحقق |
کلاس های food و order (ساده و بدون وابستگی خاصی تعریف شده اند و اکر تغییری ایجاد شود به راحتی می توان در آنها بدون ایجاد مشکل تغییر ایجاد کرد که نشان دهنده coupling کم و cohesion بالاست.) |
موارد نقض |
main , (Online,Onsite,Phone)OrderService , OrderService |
|
اصل 3 Liskov Substitution Principle |
موارد تحقق |
مورد ارثبری وجود نداشت. |
موارد نقض |
- |
|
اصل 4 Interface Segregation Principle |
موارد تحقق |
یک اینترفیس تعریف شده که آن هم مشکل دارد. |
موارد نقض |
OrderService - این مورد در Open-Close هم قرار می گیرد |
|
اصل 5 Dependency Inversion Principle |
موارد تحقق |
کلاس های اصلی (موجودیت ها) وابستگی خاصی ندارند. برای سرویس سفارش هم از یک اینترفیس استفاده شده که در حالت کلی مناسب است. مشکلات آن در اینجا مطرح نمی شود. |
موارد نقض |
تابع main |
در خصوص هرکدام از موارد نقض هرکدام از اصول، یک راهکار را به منظور رفع آن مشکل ارایه داده و در جدول زیر ثبت نمایید:
اصل مربوطه (از اصول SOLID) |
علت نقض |
راه حل پیشنهادی |
Single Responsibility |
در تابع main سه کار مختلف انجام میشد |
برای هر کدام یک تابع مختلف ایجاد کنیم |
open-close - Dependency Inversion |
این مورد در OrderService رعایت نشده بود به این دلیل که از تابع های جزيی استفاده شده بود که باعث پیاده سازی تابع های خالی در کلاس های دیگر میشد . به همین دلیل اگر تغییرات خاصی ایجاد میشد که کلی نبودند این روی سه کلاس دیگر تاثیر منفی می گذاشت. در واقع وابستگی جزيی ایجاد شده بود که نیازمند اصلاح است |
استفاده از تابع های کلی به جای جزيی (نه مخصوص کلاس های دیگر) |
open-close - Dependency Inversion |
تابع main که زده شده بود در واقع برای شروع پردازش است و نباید در آن زیاد عملیات های خاصی که مربوط به حوزه های مختلف هستند انجام میشد. در واقع این که روند اجرای کل برنامه در main باشد مناسب نیست و آن را به GodClass تبدیل می کند که باعث افزایش coupling شدید می شود. |
استفاده از یک کلاس دیگر برای اجرای روند برنامه و صرفا شروع برنامه توسط main |
Interface Segregation |
در OrderService همانطور که مطرح شد تابع های خوبی در نظر گرفته نشده بود و باعث پیاده سازی های بیجا و خالی میشد |
اصلاح توابع و کلی تر کردن آنها |
در نهایت، بر اساس تحلیلی که انجام دادهاید و راه حلهایی که در بخش قبل ارایه کردید، کد را اصلاح کرده و بر روی مخزن گیتهاب و در پوشهای مجزا از گام قبل commit و push کنید. انتظار میرود که تمامی راه حلهای پیشنهادی خود را بر روی این نسخه اعمال کنید و تمامی بهبودهایی که انجام میدهید، در جداول بخش قبل موجود باشد.
فرض کنید که گام 1 را برای کد اصلاح شده (پس از انجام گامهای ۲ و ۳) اجرا کردهاید.
- در این صورت از انجام کدام یک از تغییرات ثبت شده در جدول گام ۱ معاف خواهید شد؟ موارد ۱و ۲و ۶و ۷و ۸و ۹و ۱۰و ۱۱و ۱۲و ۱۳
- تعداد تغییرات مورد نیاز، چند تغییر خواهد شد؟ به ۵ تغییر کاهش می یافت
در این بخش، بیان کنید که از این گام چه نتیجهای گرفتهاید؟ و به نظر شما به کارگیری صحیح اصول SOLID در گامهای ۳ و ۴ چه مزایایی را نسبت به حالتی دارد که این اصول رعایت نشدهبود؟
استفاده از اصول SOLID در برنامهنویسی مزایای بسیاری دارد که واقعاً میتواند به بهتر شدن کدهایمان کمک کند. اول از همه، وقتی این اصول را رعایت میکنیم، کدها خواناتر و قابل فهمتر میشوند. یعنی اگر بعداً خودمان یا یکی دیگر از اعضای تیم بخواهد روی کدها کار کند، راحتتر میفهمد که چی به چیست و چرا هر بخش از کد نوشته شده است.
یکی دیگر از مزایای بزرگ SOLID این است که کدها انعطافپذیرتر میشوند. یعنی اگر بخواهیم یک ویژگی جدید به برنامه اضافه کنیم، لازم نیست کل کد را زیر و رو کنیم. فقط همان بخش مربوطه را تغییر میدهیم یا ویژگی جدید را به راحتی اضافه میکنیم، بدون اینکه بقیه قسمتها دچار مشکل شوند.
رعایت اصول SOLID باعث میشود باگها و خطاها کمتر شوند. وقتی هر کلاس و ماژول یک وظیفه مشخص دارد، تست کردن و پیدا کردن خطاها خیلی راحتتر میشود. این موضوع منجر به این میشود که برنامهها قابل اعتمادتر و با کیفیتتر باشند.
یک مزیت دیگر این است که کدها قابل نگهداریتر میشوند. یعنی اگر بعداً بخواهیم چیزی را تغییر دهیم یا بهبود دهیم، خیلی راحتتر میتوانیم این کار را انجام دهیم. نیازی نیست از اول همه چیز را بازنویسی کنیم یا نگران باشیم که یک تغییر کوچک کل برنامه را خراب کند.
همچنین، رعایت اصول SOLID به بهتر شدن همکاری تیمی هم کمک میکند. وقتی همه اعضای تیم از این اصول پیروی کنند، همکاری و هماهنگی خیلی راحتتر میشود و هر کسی میتواند روی بخش خودش تمرکز کند بدون اینکه نگران باشد تغییراتش روی کار دیگران تاثیر منفی بگذارد.
این تغییرات باعث می شود هزینه اسکیل کردن و بزرگ تر کردن پروژه کمتر بشود و اضافه کردن فیچر ها و maintenance پروژه کم هزینه تر و سریع تر بشود و تغییرات مورد نیاز برای هر چیز جدید را کمتر بکند.
در نهایت، رعایت اصول SOLID باعث میشود که ما به عنوان برنامهنویسان حرفهای شناخته شویم و کدهایمان هم از نظر کیفیت و هم از نظر کارایی به مراتب بهتر شود. این اصول، هم کار خودمان را راحتتر میکند و هم به تیم کمک میکند تا نرمافزارهای با کیفیتتری تولید کنیم.
- گام ۱ را انجام داده و سپس کد نوشته شدهی خود را (با رعایت محدودیتهای گفته شده در گام) در یک پوشه به نام Step_1_Non_SOLID ذخیره کنید و در مخزن گام ۲ قرار دهید. موارد توضیحی بایستی در بخش README مخزن قرار گیرد.
- گام ۲ (که بخش تحلیلی است) در فایل README مربوط به مخزن گام ۲ آورده شود (تمام جداول با فرمت داده شده و عناوین هرکدام از سوالات پرسیده شده بایستی در README آورده شود).
- گام ۳ که شامل بهبود است، بایستی به صورت جداگانه در پوشه دیگری به نام Step_3_With_SOLID قرار داده شود و در مخزن موجود باشد.
- گام ۴ نیز در قالب توضیحات در README مخزن آورده شود.
- گام ۵ (که نتیجه گیری است) در README مخزن آورده شود.