فرشید عزیزی
فرشید عزیزی
خواندن ۵ دقیقه·۳ سال پیش

Abstraction layer over DbContext

ادامه از قسمت اول : پیاده سازی الگوی Repository در ASP.NET Core

مطابق مستندات مایکروسافت از آنجایی که کلاس DbContext الگوهای Unit of Work و Repository را پیاده‌سازی می‌کند، آیا ایجاد پیاده سازی های سفارشی لایه های Unit of Work و Repository هنگام استفاده از DbContext فایده ای دارد؟

کلاس DbContext ترکیبی از الگوهای Unit Of Work و Repository است.
کلاس DbContext بر اساس الگوی Unit of Work است که شامل تمام موجوديت هاي DbSet است. کلاس DbContext عملیات پایگاه داده را روی این موجودیت ها مدیریت می کند و بعداً تمام این به روز رسانی ها را به عنوان یک تراکنش در پایگاه داده ذخیره می کند.
در قسمت قبل گفتیم یکی از دلایل استفاده از Repository این است که وابستگی پروژه را به نوع دیتابیس از بین ببریم. اما در EF Core قبلا این کار انجام شده است. EF Core دارای یک سری Provider است که با تغییر آنها می توانید از دیتابیسی به دیتابیس دیگر جهش کنید بدون اینکه کدهای کار با دیتابیس را تغییر دهید.

گفتيم که کلاس DbContext نشان دهنده یک Unit of Work و DbSet است، اما با اين وجود برخی از توسعه دهندگان یک لایه انتزاعی روی آنها ایجاد می کنند که یک انتزاع دیگر از Data Access است.

مهمترين دلايلي که ممکن است بخواهيد این کار را انجام دهید(افزودن يک لايه انتزاعي بر روي DbContext) :

  • شاید شما نمی‌خواهید پروژه‌تان کاملاً با Entity Framework و معماری آن مرتبط باشد. بنابراین، شما Entity Framework را پشت آن انتزاعات پنهان می کنید تا بتوانید Entity Framework را جایگزین هر ORM دیگری بدون هیچ گونه تغییری در رابط لایه دسترسی به داده کنید.
  • پیاده سازی مخازن سفارشی مزایای متعددی را در هنگام پیاده سازی میکروسرویس ها یا برنامه های کاربردی پیچیده تر ارائه می دهد. الگوهای Unit of Work و Repository برای محصور کردن لایه persistence در نظر گرفته شده‌اند، بنابراین از لایه‌های application و domain-model جدا می‌شود.
  • شما از مخازن استفاده می کنید تا مشخص کنند که چه عملیاتی برای موجودیت های خاص مجاز است. (برای مثال، CustomerRepository ممکن است اجازه اضافه کردن و به‌روزرسانی مشتریان را بدهد، اما آنها را حذف نکند). از سوی دیگر، سایر توسعه دهنده گان را قادر می سازد تا به راحتی عملیات موجود برای موجودیت های خاص را تشخیص دهد.
  • خود مایکروسافت استفاده از الگوهای Repository را در سناریوهای پیچیده توصیه می‌کند تا کوپلینگ را کاهش داده و تست‌پذیری بهتر را ارائه دهد. در مواردی که ساده ترین کد ممکن را می خواهید، می خواهید از الگوی Repository اجتناب کنید.

در نهایت، بسیاری هستند که انتزاعی را روی DbContext و DbSet ایجاد نمی کنند. آنها فقط مستقیماً از آنها استفاده می کنند و انجام این کار کاملاً صحيح است.

بستگی به نحوه مدیریت وابستگی ها دارد

اگر Entity Framework لایه انتزاعی شما باشد و پایگاه داده خود وابستگی باشد، Entity Framework در واقع قبلاً Unit of Work و Repository شما را ارائه می دهد. معامله این است که دامنه شما به Entity Framework متکی است. تا زمانی که این وابستگی قابل قبول باشد، همه چيز خوب و صحيح است.

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

اساساً، همه چیز به جایی برمی‌گردد که شما خطی را ترسیم می‌کنید که چه چیزی یک «وابستگی خارجی» هست یا نیست. برای برخی پروژه ها مهم نیست، برای برخی پایگاه داده فیزیکی، برای برخی framework دسترسی به داده ها و غیره است.

يک ضد الگو (Anti-Pattern ) چیست؟

یک ضد الگو معمولاً یک راه حل بی اثر برای یک مشکل است. ضد الگوها تکنیک های برنامه نویسی ناکارآمدی هستند که به جای حل آن مشکل، مسائلي را ایجاد می کنند و به دلیل مهندسی بیش از حد(over-engineering)، استفاده نادرست از الگوهای طراحی، پیروی نکردن از روش های توصیه شده و غیره ظاهر می شوند.

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

یک لایه اضافی از انتزاع

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

وقتی متدهاي اضافی را در Repository خود اضافه می‌کنید، اوضاع بدتر می‌شود. شما با یک Repository مواجه خواهید شد که با لایه ذخیره سازی دائمی که در زیر آن استفاده می شود مطابقت دارد. به عنوان مثال، ممکن است به متدهایی مانند FindProductById، FindCustomerById و غیره نیاز داشته باشید. چنین متدهایی در ORM هاي بالغ وجود دارند. به این معنی است که شما بدون هیچ دلیل موجهی در حال ایجاد یک انتزاع در بالای یک انتزاع دیگر هستید.

معایب یک Generic Repository

در یک برنامه کاربردی، domain model و persistence model نقش جداگانه ای دارند. رفتار مدل domain با مسائل و راه حل های دنیای واقعی سر و کار دارد. مدل persistence نشان دهنده نحوه ذخیره داده های برنامه در Data Storage است.

الگوی Repository باید منطق persistence را در بر بگیرد و پیاده سازی های مربوط به ذخیره سازی داده ها را پنهان کند. عملیات در Repository ها باید رسا باشد تا عمومی.

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

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

بیشتر بخوانید : نقشه راه توسعه دهندگان Asp.NET Core


https://zarinp.al/farshidazizi

Abstraction layer over DbContextrepository patternunit of work patternentity framework
Software Engineer
شاید از این پست‌ها خوشتان بیاید