طراحی سایت|طراحی اپلیکیشن

اصل Single Responsibility Principle در اصول SOLID

 SOLID یکی از محبوب ترین مجموعه های اصول طراحی در توسعه نرم افزار شی گرا است. این کلمه مخفف 5 اصل طراحی زیر است:

ابداع کننده ی اصول SOLID کیست؟

پنج اصل SOLID توسط Robert C.Martin برای اولین بار مطرح شد.

هدف اصول SOLID چیست؟

هدف این اصول توسعه کدی با خوانایی بالا و قابل آزمایش و توسعه پذیر همچین ساخت یک استاندارد بین تمامی توسعه دهنده ها است.

همه آنها بسیار مورد استفاده قرار می گیرند و ارزش شناختن را دارند. اما در این اولین پست از مجموعه درباره اصول SOLID ، من به اولین مورد تمرکز خواهم کرد: اصل مسئولیت منفرد (Single Responsibility Principle).

اصل اول:

Single Responsibility Principle

رابرت سی. مارتین آن را چنین توصیف می کند:

یک کلاس باید یک دلیل و فقط یک دلیل برای تغییر داشته باشد.

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

مزایای (Single Responsibility Principle) اصل مسئولیت منفرد

بیایید مهمترین سوالات را قبل از اینکه به عمق این اصل طراحی بپردازیم ، بیان کنیم: چرا باید از آن استفاده کنید و اگر آن را نادیده بگیرید چه اتفاقی می افتد؟

استدلال برای اصل مسئولیت منفرد نسبتاً ساده است: نرم افزار را آسان تر می کند و از اثرات جانبی غیر منتظره تغییرات آینده جلوگیری می کند.

فرکانس و اثرات تغییرات

همه ما می دانیم که الزامات با گذشت زمان تغییر می کنند. همچنین هریک از آنها مسئولیت حداقل یک طبقه را تغییر می دهد. هرچه کلاس شما مسئولیت بیشتری داشته باشد ، بیشتر اوقات نیاز به تغییر آن دارید. اگر کلاس شما چندین مسئولیت را اجرا کند ، آنها دیگر از یکدیگر مستقل نیستند.

شما باید کلاس خود را به محض تغییر یکی از مسئولیت های آن تغییر دهید.

این ممکن است چیز بزرگی به نظر نرسد ، اما همه کلاسها یا مولفه های وابسته به کلاس تغییر یافته را نیز تحت تأثیر قرار می دهد. بسته به تغییر شما ، ممکن است لازم باشد وابستگی ها را دوباره به روز کنید یا کلاسهای وابسته را از نو کامپایل کنید حتی اگر مستقیماً تحت تأثیر تغییر شما قرار نگیرند. آنها فقط از یکی دیگر از مسئولیت های اجرا شده توسط کلاس شما استفاده می کنند ، اما به هر حال شما باید آنها را به روز کنید.

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

درک آسان تر

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

با این حال ، اطمینان حاصل کنید که کد خود را بیش از حد ساده نکنید. برخی از توسعه دهندگان با ایجاد کلاسهایی تنها با یک عملکرد ، اصل مسئولیت واحد را به حداکثر می رسانند. بعداً ، هنگامی که آنها می خواهند برخی از کد های واقعی را بنویسند ، مجبورند بسیاری از وابستگی ها را تزریق کنند که باعث می شود کد بسیار ناخوانا و گیج کننده باشد.

بنابراین ، Single Responsibility Principle یک قانون مهم است که کد شما را بیشتر قابل فهم می کند ، اما از آن به عنوان کتاب مقدس خود استفاده نکنید. در هنگام تهیه کد از عقل سلیم استفاده کنید. داشتن چندین کلاس که فقط حاوی یک تابع باشند هیچ فایده ای ندارد.

یک سوال ساده برای اعتبار سنجی در طراحی شما

متأسفانه ، پیروی از Single Responsibility Principle بسیار ساده تر از آنچه معمول است به نظر می رسد.

اگر نرم افزار خود را برای مدت زمان طولانی تری بسازید و اگر لازم است آن را با نیازهای خود تغییر دهید ، به نظر می رسد ساده ترین و سریعترین روش افزودن روش یا عملکرد به کد موجود شما به جای نوشتن کلاس یا مولفه جدید است. اما این اغلب در کلاسهایی با مسئولیت بیشتر نتیجه می گیرد و نگهداری نرم افزار را دشوارتر می کند.

قبل از ایجاد هرگونه تغییر با پرسیدن یک سوال ساده می توانید از این مشکلات جلوگیری کنید: مسئولیت کلاس / کامپوننت / ریز سرویس شما چیست؟

اگر پاسخ شما شامل کلمه “and” باشد ، به احتمال زیاد Single Responsibility Principle را نقض می کنید. پس بهتر است قدمی به عقب بردارید و در مورد روش فعلی خود تجدید نظر کنید. به احتمال زیاد روش بهتری برای اجرای آن وجود دارد.

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

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

در مرحله بعدی ، بیایید به برخی از مثالهای جاوا در مورد اصل مسئولیت واحد نگاهی بیندازیم.

نمونه های واقعی Single Responsibility Principle در دنیای واقعی

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

یکی از آنها مشخصات Java Persistence API (JPA) است. تنها یک مسئولیت دارد: تعریف روشی استاندارد برای مدیریت داده ها با استفاده از مفهوم نقشه برداری رابطه ای شی گرا، در یک پایگاه داده رابطه ای وجود دارد.

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

اما این تنها مسئولیت مشخصات JPA است. سایر قابلیتهایی که شما ممکن است برای اجرای برنامه خود نیاز داشته باشید ، مانند اعتبار سنجی ، REST API یا ورود به سیستم ، به عهده JPA نیست. شما باید مشخصات یا چارچوب های دیگری را که این ویژگی ها را ارائه می دهند ، وارد کنید.

JPA EntityManager

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

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

مبدل Jrib Attribute

مسئولیت EntityManager ممکن است بیش از حد بزرگ باشد و بتواند به عنوان نمونه ای از اصل مسئولیت واحد قابل درک باشد. بنابراین ، بیایید به یک مثال کوچکتر نگاهی بیندازیم: AttributeConverter همانطور که مشخصات JPA آن را تعریف می کند.

مسئولیت AttributeConverter کم و آسان است. این یک نوع داده مورد استفاده در مدل دامنه شما را به نوعی تبدیل می کند که ارائه دهنده پایداری شما می تواند در پایگاه داده ادامه یابد. می توانید از آن برای پایدار نگه داشتن انواع داده های پشتیبانی نشده ، مانند کلاس مقدار دلخواه خود ، یا برای شخصی سازی نگاشت از نوع داده پشتیبانی شده ، مانند یک نقشه برداری سفارشی برای مقادیر enum ، استفاده کنید.

در اینجا مثالی از AttributeConverter آورده شده است که شی java.time.Duration را که توسط JPA 2.2 پشتیبانی نمی شود ، به java.lang.long ترسیم می کند. پیاده سازی سریع و آسان است. شما باید آن رابط AttributeConverter را پیاده سازی کنید و کلاس خود را با حاشیه نویسی em>Converter </ em حاشیه نویسی کنید.

شی java.time.Duration را که توسط JPA 2.2 پشتیبانی نمی شود ، به java.lang.long ترسیم می کند

همانطور که در نمونه کد مشاهده می کنید ، DurationConverter فقط دو عملیات تبدیل مورد نیاز را پیاده سازی می کند. روش convertToDatabaseColumn شی Duration را به Long تبدیل می کند ، که در پایگاه داده ادامه خواهد داشت. و convertToEntityAttribute عملیات معکوس را پیاده سازی می کند.

سادگی این قطعه کد ، دو مزیت اصلی Single Responsibility Principle را نشان می دهد. با محدود کردن مسئولیت DurationConverter به تبدیل بین دو نوع داده ، درک آن آسان می شود و فقط در صورت تغییر الزامات الگوریتم نقشه برداری تغییر می کند.