اصول Solid

یکی از مسائلی که در برنامه نویسی با آن روبرو هستیم این است که اگر تمام قواعد کدنویسی تمیز را هم در نظر بگیریم باز هم در انتهای کار تعدادی ماژول خواهیم داشت که باید باهم تعامل کنند. اصول Solid در طراحی ماژول ها و ارتباط بین آنها ما را راهنمایی خواهد کرد. با رعایت این اصول ما می توانیم کد را براحتی تغییر دهیم، نگهداری آن برای ما راحت خواهد بود و قابلیت جابجایی خوبی را نیز داشته باشیم.اصول Solidاولین اصلی که در اصول Solid با آن مواجه هستیم، Single Responsibility Principle می باشد.تعریف صحیح آن این است که هر ماژول تنها و فقط یک دلیل برای تغییر باید داشته باشد. در حقیقت هر ماژول باید تنها و فقط به یک Actor در سیستم خدمات بدهد.از نشانه های مشخص شدن چند کاربره بودن یک ماژول، تغییرات ناگهانی در کد ما است. راه حل آن، جداسازی داده از عملکرد و همچنین پیاده سازی جداگانه عملکردها است. (هر کلاس یک کار انجام دهد).ممکن است با این کار تعداد کلاسهای ما زیاد شود و مدیریت آن سخت شود. راه حل آن ایجاد یک کلاس به عنوان Wrapper می باشد که استفاده از عملکردهای مختلف را برای ما ساده می کند.یکی دیگر از مشکلاتی که در دنیای نرم افزار با آن مواجه هستیم، تغییرات می باشد. تغییرات از عوامل خطا در نرم افزار است. دومین اصلی که در اصول Solid با آن مواجه هستیم، Open Close Principle است. ماژول های ما باید برای توسعه باز باشند و برای اعمال تغییر بسته باشند. باید بدون تغییرات در سورس های اصلی کلاس، به کلاس ها ویژگی اضافه کنیم. برای رعایت کردن این اصل، در زمان طراحی یک ماژول باید به این فکر کنیم کدام قسمت ها قابل تغییر است و کدام قسمت ها قابل تغییر نیست. (قسمت های متغیر را از کلاس جدا می کنیم). یکی دیگر از مطالبی که زیاد با آن سر و کار داریم، Abstraction (انتزاع) می باشد. همانطور که می دانیم Abstraction یکی از اصول شی گرایی است. سطح Abstraction یعنی در طراحی یک ماژول، بدانیم تا کجا این ماژول Abstract می باشد و سپس نمونه واقعی می شود. برای مثال در دنیای موجودات زنده، موجود زنده Abstract است، حیوان، گیاه و انسان Abstract هستند و در نهایت اسب یک نمونه واقعی می باشد و می توانیم از آن نمونه بسازیم. تعیین کردن سطح Abstraction، بسیار مهم است.سومین اصلی که در اصول Solid با آن مواجه هستیم، Liskov Principle می باشد. تعریف آن این است که اشیا پدر بتوانند با فرزندان جایگزین شوند و با جایگزینی عملکرد تغییری نکند. برای مثال یک کلاس محاسبه کارمزد داریم. کارمزد اداری با کارمزد خانگی متفاوت است. من یک کلاس کارمزد Abstract می سازم که یک متد برای محاسبه کارمزد دارد و برای کارمزد خانگی و اداری آن را Implement می کنم. حالا هر جایی که نیاز به محاسبه کارمزد دارم می توانم کلاس کارمزد را به عنوان ورودی بفرستم و چه کارمزد خانگی و چه کارمزد اداری بفرستم کار بدرستی انجام می شود.از مشکلات دیگری که در نرم افزار ها ممکن است با آن روبرو شویم، مواجه شدن با اینترفیس هایی می باشد که نمی دانیم نصف توابع آن چه وظیفه ای دارند. هم توسعه برای ما سخت می شود و هم اینکه تضمینی نیست که من توابع بی ربط را صدا نزنم. اصطلاحا به آن Fat Interface گفته می شود.چهارمین اصلی که در اصول Solid با آن مواجه هستیم، Interface Segregation Principle می باشد. تعریف آن این است که باید عملکرد ها را دسته بندی کنیم و هر عملکرد پیاده سازی صحیح خود را داشته باشد. برای این کار باید Actor هایی که در سیستم داریم را همیشه در نظر بگیریم.اصل آخر، Dependency Inversion Principle می باشد. ما یکسری کلاس داریم که این کلاس ها برای Implement شدن دارای وابستگی هستند. مثلا کلاسی برای ارسال پیام دارم. یک راه این است که خودم نیازمندی های خودم را تعریف کنم و از آن استفاده کنم. مشکل اینجاست که فرض کنید من تا امروز پیام را به وسیله sms ارسال می کردم و باید از فردا به صورت Email ارسال کنم. و یا کلاس ارسال sms که من از آن استفاده می کنم، به هر دلیلی تغییر کند (برای مثال تغییر در پارامترها). در این دو حالت، باید کلاس خودم را تغییر دهم و اصل Single Responsibility را زیر سوال ببرم.اما راه درست این است که وظیفه ساختن نیازمندی ها را به بیرون از کلاس منتقل کنم. در حقیقت ماژول های سطح بالا نباید به ماژول های سطح پایین وابستگی پیدا کنند و فقط باید به Abstraction وابسته باشند. Abstraction باید دارای سطح درستی باشد و اگر می خواهیم کامپوننت بنویسیم باید Abstraction توسط خودمان تعیین شده باشد و وابسته به شرکت خاصی نباشیم.پایان