/Design-Patterns-SE-SUT

This is a project for Software Engineering Lab at SUT.

Primary LanguageJava

گزارش آزمایش چهارم

محمد نامدار ـــــ حمیدرضا دهباشی

پیاده‌سازی برنامه

از آنجا که با روش ایجاد آزمون‌رانه (TDD) این پروژه را پیاده سازی کرده‌ایم، ابتدا بر اساس تحلیل مسئله و نمودار UML زیر به طراحی تست ها می‌پردازیم.

uml diagram

تست ها در فایل PacketTest.java پیاده سازی شده‌اند.

test design

در ادمه ساختار برنامه شامل کلاس Packet، State و TransportMode است و state های متفاوت یا transportMode های متفاوت نیز وجود دارند. به این صورت که در هر مرحله در حلقه، اگر State بسته مقدار مناسبی باشد حلقه ادامه پیدا میکند و در غیر اینصورت از حلقه خارج می شویم. همچنین در حلقه تکرارشونده ورودی ها و خروجی های مدنظر پیاده سازی شده اند. در رابطه با نسبت الگوهای طراحی و نرم افزار پیاده سازی شده، به دلایلی که در پرسش 3 آورده شده است، از الگوی طراحی State استفاده شده است (این الگو در State و TransportMode استفاده شده است). نحوه تحقق این الگو نیز در پرسش 3 مطرح شده است.

در نهایت نیز درستی کد با استفاده از تست ها بررسی شده است.

test result

پرسش ها

سوال 1

در کتاب مورد نظر، سه دسته الگوی طراحی Creational، Structural و Behavioural معرفی شده است.

الگوهای طراحی سازنده، الگوهایی هستند که در هنگام ایجاد اشیا و نمونه های جدید به ما کمک میکنند. این دسته از الگوها شامل الگوهای زیر می باشند:

abstract factory, builder, factory method, prototype, singleton

الگوهای طراحی ساختاری راه حل هایی هستند که عمدتا در هنگام بهبود توسعه پذیری نرم افزار موثر هستند. در این الگوها روابط میان اشیا و کلاس ها مورد تاکید است. این دسته از الگوها شامل الگوهای زیر می باشند:

adapter, bridge, composite, decorator, facade, flyweight, proxy

دسته آخر، الگوهای طراحی رفتاری است. این الگوها راه حل هایی هستند که متمرکز بر پیاده سازی رفتار ها و الگوریتم های متفاوت توسط اشیا می باشد. این دسته از الگوها شامل الگوهای زیر می باشند:

chain of responsibility, command, interpreter, iterator, mediator, memento, observer, state, strategy, template method, visitor

سوال 2

الگوهای state و strategy در دسته الگوهای رفتاری قرار میگیرند زیرا هدف این الگوها ارائه نحوه پیاده سازی های متفاوت در نسبت با اشیا می باشد.

سوال 3

به صورت کلی الگوی strategy در حالاتی مناسب است که بخواهیم یک رفتار را در نسبت با چندین شیء یا کلاس متفاوت مطرح کنیم؛ در نتیجه این رفتار های مختلف باید به نوعی مستقل از وضعیت اشیا باشند. به عنوان مثال الگوریتم های مختلف مرتب‌سازی را می‌توان روی هر لیستی از اعداد اعمال کرد و به ویژگی ها و وضعیت شیء حاوی لیست مرتبت نیست. در نتیجه می‌توان از آن در کلاس های مختلف استفاده کرد. بنابراین اگر این شرایط برقرار نباشد، استفاده از این الگو پیچیدگی اضافی نسبت به الگوی state خواهد داشت. الگوی state رفتارهای متناسب با وضعیت هر شیء را می تواند به خوبی هندل کند و از آنجا که در این سوال تنها یک شیء داریم پس شرایط کلی جاری در برنامه و رفتار های مدنظر، وابسته به حالت همان یک شیء می باشد. پس الگوی State در این جا مناسب تر خواهد بود.

در رابطه با تحقق state در کد پیاده سازی شده، به اینصورت است که دو نوع حالت به صورت کلی در برنامه موجود است TransportMode و State اولی مربوط به express یا standard و دومی نیز مربوط به delivered یا in-transit می باشد. توجه کنید کلاس Packet، state را پیاده سازی می کند (الزاما باید checkContinue را پیاده سازی کند) و یک فیلد state نیز دارد که متناسب با وضعیت مورد نظر مقدار دهی میشود. بسته به state بسته ارسالی مشخص می شود که آیا در گام بعدی باید متوقف شد و برنامه بایستد، یا باید ادامه پیدا کند. این امر در checkContinue محقق شده است. هر state جدید اضافه شود کافی است checkContinue مربوط به خودش را پیاده سازی کند. همچنین در رابطه با TransportMode، بسته به نوع transport قیمت بسته مشخص می شود. از این تابع calcCost در getData استفاده شده است. هر TransportMode جدید کافی است calcCost مربوط به خودش را پیاده سازی کند. توجه کنید به این دلیل کلاس Packet اینترفیس TransportMode را به ارث نبرده است زیرا calcCost موجود در Packet به صورت خصوصی در نظر گرفته شده است و در حقیقت کلاینت تنها getData را صدا میزند و دیتای مورد نیاز خود را دریافت میکند (getData از calcCost استفاده میکند).

سوال 4

الف) Single Responsibility:

زیرا این اصل به این معناست که هر کلاس مسئولیت تنها یک قسمت از برنامه را بر عهده دارد. از طرفی، الگوی Singleton باعث میشود تنها یک نمونه از کلاس ایجاد شود و در نتیجه constructor علاوه بر ایجاد نمونه، مسئول تضمین یکتایی آن نیز است.

ب) Open-Closed:

زیرا زمانی میتوان گفت که یک کلاس open است که بتوان از آن ارث بری کرد. همچنین در ارث بری رابطه is-a برقرار است. فرض کنید یک کلاس singleton داریم و کلاس دیگری فرزند آن است. اکنون اگر چندین نمونه از کلاس فرزند داشته باشیم، آن گاه از آنجا که هر نمونه فرزند یک نمونه پدر است پس singleton برقرار نخواهد بود. در نتیجه یا میتوان الگوی singleton را داشت یا میتوان ارث بری را روی یک کلاس تعریف کرد. هر دوی اینها به دلایل مطرح شده ممکن نیست.

ج) Liskov Substitution:

به دلیل مطرح شده در قسمت open-closed و عدم توانایی ساختن subclass در الگوی singleton، این مورد نیز نقض می شود.

د) Interface Segregation:

از آن جا که امکان داشتن هیچ inteface wrapper در کلاس singleton وجود ندارد. این اصل نیز در رابطه با singleton قابل پیاده سازی نیست.

ه) Dependency Inversion:

این اصل تاکید میکند که entity ها باید وابسته به abstraction باشند و نه وابسته به implementation. از آن جا که singleton مبتنی بر concrete implementation است پس این اصل نیز نقض می شود.