بایگانی

نوشته های برچسب زده شده ‘طراحی’

عمق وراثت (Depth of Inheritance)

هفته قبل رامین در جلسات باز نرم‌افزاری تبریز در مورد الگوی طراحی Decorator  صحبت می‌کرد. سوالی که توسط تعدادی از دوستان مطرح شد این بود که چرا از وراثت به جای این الگو استفاده نکنیم؟ دلیلی که توسط رامین به آن اشاره شد این بود که رفتار و ویژگی‌های جدید با استفاده از این الگو در زمان اجرا به نمونه کلاس‌ها اضافه می‌شود نه به خود کلاس. در حالیکه با استفاده از وراثت رفتار و ویژگی‌های جدید به زیرکلاس اضافه می‌شود و در نتیجه این ویژگی‌ها به همه نمونه‌های آن افزوده می‌شود.

وراثت در برایر Decorator

وراثت در برایر Decorator

اما مشکل دیگری که برای وراثت به آن اشاره شد افزایش تعداد زیرکلاس‌ها و عمق وراثت بود. در این پست می‌خواهیم کمی بیشتر در مورد عمق وراثت بحث کنیم.

عمق وراثت یکی از متریک‌های طراحی شی‌گرا می‌باشد که به این شکل تعریف می شود: “حداکثر فاصله یک گره از گره پدر درخت”. برای نمونه من درخت وراثت را برای کلاس Hidden از فریم‌ورک Asp.NET MVC رسم کردم و همانطوریکه در تصویر مشخص هست عمق این درخت ۴ هست. به یک نکته توجه کنید که در بسیاری از زبانها همه کلاس‌ها از یک کلاس پایه ارث می‌برند حتی اگر به طور صریح در کد شما به آن اشاره نشده باشد. برای نمونه در سی شارپ همه کلاسها از کلاس Object ارث می‌برند پس هر کلاسی که شما ایجاد کنید حداقل دارای عمق یک خواهد بود.

 

عمق وراثت کلاس Hidden

عمق وراثت کلاس Hidden

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

 

حداکثر مقدار قابل قبول برای عمق وراثت چقدر است؟ هیچ مقدار استانداردی برای حداکثر مقدار بهینه عمق وراثت تا بحال اعلام نشده است. مقادیر توصیه شده از ۵ تا ۸ متغییر است. برای نمونه مستندات مایکروسافت ویژوال استودیو مقدار ۵ را پیشنهاد می‌کند در حالیکه برای نمونه در سورس Asp.net MVC که مربوط به خود این شرکت هست عمقی تا هفت را می‌توان مشاهده کرد. شاید دلیلی که نمی‌توان یک حداکثر مقدار بهینه برای این متریک تعیین کرده در متفاوت بودن ماهیت سیستم‌های نرم‌افزاری باشد. برای مثال شاید برای یک فریم‌ورک توسعه وب مقدار ۵، ۶ قابل قبول است در حالیکه برای یک سیستم اتوماسیون اداری این اعداد یک مقدار بزرگ است.

حداکثر عمق کلاس در فریم‌ورک ASP.NET MVC

حداکثر عمق کلاس در فریم‌ورک ASP.NET MVC

قوانین طراحی ساده

همه ما از سادگی صحبت می‌کنیم و می‌گوییم عاشق سادگی هستیم. ولی شاید جمله «برای آن مسئله یک راه‌حلی پیدا کردم که عمراً کسی بتواند بفهمد چیکار کردم.» را بعضی وقت‌ها با افتخار بزبان می‌آوریم. پیدا کردن یک راه‌حل پیچیده برای یک مسئله که برای دیگران قابل درک نباشد یک حس نبوغ در ما القا می‌کند؛ اما اگر کسی بتواند برای همان مسئله راه حلی ارائه بدهد که به سادگی توسط همه قابل درک باشد، راه حل پیچیده من یک راه‌حل احمقانه و شاید من یک احمق نامیده شوم. پس قبل از اینکه هر لقبی بگیرید لطفاً این سؤال را از خودتان بپرسید «ساده‌ترین چیزی که ممکن است کار کند، چیست؟”.» این سوالی است که توسعه دهندگان چابک در هنگام نوشتن کد از خودشان می‌پرسند و بدین معناست که ساده‌ترین کاری را انجام دهید که شما را قادر می‌سازد تا در مسیر درست به پیش بروید.

 یک از ارزش‌های XP، سادگی و یکی از تکنیک‌های آن طراحی ساده (Simple Design) هست. Kent Beck مبدع XP برای داشتن یک طراحی ساده چهار قانون تعریف کردن که عبارت‌اند از:

  1. پاس شدن همه تست‌ها
  2. عدم وجود تکرار
  3. بیان مقصود برنامه نویس
  4. کاهش تعداد کلاس‌ها و متدها

پاس شدن همه تست‌ها

پیاده‌سازی تمام کلاس‌ها و متدهایی که بر عهده شما بود را تمام کردید، خوب آیا این به منزله پایان کار شما هست؟ چگونه تشخیص می‎‌دهید کدی که نوشتید واقعاً کار می‌کند؟ چگونه تشخیص می‌دهید زمانیکه قسمتی از نرم‌افزار را تغییر می‌دهید سایر اجزای نرم‌افزار هنوز به درستی رفتار می‌کنند؟

همه سوالهای بالا بر وجود تست در سیستم تاکید دارند. Unit Test ها کمک می‌کنند که شما بدانید چه زمانی وظیفه شما به پایان رسیده است – زمانیکه شما تمام تست‌های مرتبط با وظیفه‌ای که انجام می‌دهید را نوشته باشید و همه آن‌ها پاس شده باشند. اگر تست یا تست‌هایی پاس نشده باشد شما باید به فعالیت خودتان ادامه بدهید تا همه آن‌ها پاس بشود.

عدم وجود تکرار

تکه کدهایی که در قسمت‌های مختلف برنامه تکرار شده است همیشه فاجعه به بار آورده. کافی هست تغییری اتفاق بیافتد و نیاز باشد همه این تک‌ها اصلاح شوند، به صورت معمول یک و یا چند تا از این تک‌ها اغلب فراموش می‌شود و خطاهای که به مرور گزارش می‌شوند.

این اصل اغلب بین توسعه دهنده‌های نرم‌افزار با نام DRY(Don’t Repeat Yourself.) یا Once And Only Once شناخته می‌شود. البته اصل DRY درباره تکرار کد نیست و درباره تکرار دانش هست، این اصل بیان می‌کند که  هر قسمت از دانش ما در سیستم باید جایگاه واحد، بدون ابهام و معتبری داشته باشد. (حسین بقایی عزیز چند ماه قبل لینک یک پست را در مورد DRY توئیت کرده بود که به صورت عالی این اصل را تشریح کرده بود خواندنش را از دست ندهید.)

بیان مقصود برنامه‌‌نویس

شاید این اصل یکی از اولین اصول و در ظاهر ساده‌ترین اصلی است که تعدادی زیادی از برنامه‌نویس‌ها سعی می‌کنند آنرا رعایت کنند. تاکید این اصل بر روی این هست که اسامی متغیرها، متدها، کلاس‌ها و … باید به هدف وجود آن‌ها اشاره کند.

کاهش تعداد کلاس‌ها و متدها

این یکی از اصولی هست که شاید در نگاه اول با اصول بالا در تضاد باشد. وقتی برای نمونه شما برای حذف کدهای تکراری کدهای موجود را ریفکتور می‌کنید به احتمال زیاد تعداد کلاس‌ها و متدها شما افزایش می‌یابد. پس اصل چهارم به خودی‌خود نقض می‌شود؛ اما این اصل به تعداد کلاس‌ها اشاره نمی‌کند و در واقع اشاره آن به اصل YAGNI (You Aren’t gonna need it) می‌باشد.  اصل YAGNI بیان می‌کند که شما باید هر چیزی را وقتی پیاده سازی کنید که واقعاً به آن نیاز دارید و نه وقتی که می‌فهمید در آینده ممکن است به آن نیازمند شوید. این جمله یکی از جملاتی است که XP واقعاً روی آن تاکید دارد و اعلام می‌کند که شما حتی اگر اطمینان حاصل کنید که به این ویژگی در آینده نیاز خواهید داشت آنرا الان پیاده سازی نکنید. پس هدف اصل چهارم این است که نباید با پیاده‌سازی کلاس‌ها و متدهایی که احتمالاً در آینده فرضی به آن نیاز خواهیم داشت نعداد کلاس‌ها و متدها را افزایش بدهیم.