به الگوی Repository نه بگوییم

سوال: چرا با وجود فریم ورک های بالغ و قدرتمندی همچون Entity Framework و NHibernate الگو های Repository و Unit Of Work منسوخ شده محسوب شده و به یک Anti Pattern تبدیل شده اند؟الگوهای Repository و Unit Of Work در کتاب معروف آقای Martin Fowler به نام Patterns of Enterprise Application Architecture مطرح شده اند. آقای Fowler و نوشته های ایشان همیشه مرز های توسعه نرم افزار را به جلو برده اند و در بسیاری از کتاب های آکادمیک و سایر حوزه های مرتبط با نرم افزار به وب سایت ایشان و نوشته های شان بسیار اشاره می شود.سایت Martin Fowler، که حاوی مطالب بسیار خوبی است:martinfowler.com الگوی Repository یا مخزن این الگو پیشنهاد می کند که لایه ای در نرم افزار تعبیه شود که کار اصلی آن این است که واسطی بین لایه منطق-بیزینس و لایه دسترسی به داده باشد.این لایه نحوه دسترسی به پایگاه داده را از لایه های بالایی پنهان می کند. لایه های بالایی برای اجرای دستورات و یا فراخوانی داده ها نیاز دارند تا از طریق این لایه درخواست های خود را مطرح کنند. یکی از فواید این الگو آن است که از تکرار شدن کوئری ها - مخصوصا کوئری های پیچیده - در سراسر برنامه جلوگیری کرده و آن ها در یک متمرکز می کند. همچنین لایه منطق-بیزینس خود را درگیر SQL نمی کند و از طریق Repository می تواند در چارچوبی Object Oriented داده ها را فراخوانی کند.در این الگو برای هر یک از اشیا نیاز هست تا یک کلاس Repository جدا ساخته شود و این مخزن مسئولیت ساخت کوئری های مرتبط را به عهده خواهد گرفت.اطلاعات بیشتر از سایت Fowler:http://martinfowler.com/eaaCatalog/repository.html مثلا یک مخزن مربوط به کلاس student به شکل زیر می باشد: الگوی Unit Of Work: در عمده سناریو ها نیاز هست تا داده های زیادی از پایگاه داده فراخوانی شده و سپس در برخی از آن ها تغییراتی بدهیم، داده ای را اضافه کنیم و داده های دیگر ( مثلا نامعتبر ) را حذف کنیم.طبیعتا نمی توانیم به ازای هر تغییر و هر بار افزودن و حذف داده ها، بلافاصله و تک به تک، داده ها را به سمت پایگاه داده ارسال کنیم. چرا که این امر هم موجب کاهش کارایی و مصرف منابع خواهد شد و هم ممکن است در حین ثبت داده ها ناگهان خطایی رخ دهد و باقی تغییرات در پایگاه داده منعکس نشوند و خاصیت تراکنشی (Transactional) بیزینس از بین برود.الگوی Unit Of Work راهکاری را ارائه می دهد که در آن تمامی تغییرات داده شده در مدل، مانیتور می شوند. یعنی دقیقا در جایی ثبت می کنیم که چه مشخصاتی از چه اشیایی تغییر کرده، چه اشیایی اضافه شده و چه اشیایی حذف شده اند. سپس در انتها و پس از انجام کارها، با صدا زدن متد Save خواهیم فهمید که باید چه تغییراتی را به سمت پایگاه داده ارسال کنیم و البته این کار هم به صورت Transactional انجام خواهد گرفت.http://martinfowler.com/eaaCatalog/unitOfWork.html الگوهای Repository و Unit Of Work متعلق به دوران گذشته اند. یعنی سال 2003 که کتاب Patterns of Enterprise Application Architecture تالیف شد و ORM های قدرتمند امروزی وجود نداشت.امروزه Entity Framework پیاده سازی بسیار قدرتمندی از الگوهای فوق می باشد و قابلیت های بسیار بیشتری را نیز پوشش می دهد.1. کلاس DbContext دقیقا می تواند تغییرات اشیا را Track کرده و بداند چه چیز های حذف و اضافه شده اند. پس دیگر نیازی نیست ما دوباره از نوع Unit Of Work بنویسیم.2. توسط DbContext و DbSet ها می توانیم به راحتی و بدون استفاده از SQL پیچیده ترین کوئری ها را در سی شارپ بنویسیم.3. در روش Repository در هر مخزن، به مرور زمان با انبوهی از متد های بی ارزش مواجه می شویم. مثلا FindStudentByEmail، FindStudentById، FindStudentByName و ... که این ها موجب می شود سرعت توسعه کند شود. در صورتی که با استفاده از EF می توانیم این ها را به راحتی انجام دهیم و مدام لازم نیست به ازای هر کار متد بسازیم.4. در الگوی Repository، به ازای هر کلاس که به مدل اضافه می کنیم باید یک مخزن بسازیم که این خودش ما را با انبوهی از کلاس ها مواجه می کند.5. پیاده Repository ما را از بسیاری از قابلیت های بی نظیر EF محروم می کند و نمی گذارد که از انعطاف بی نظیر این فریم ورک استفاده کنیم.در واقع پنهان سازی EF در پشت Repository ها و Unit Of Work نه تنها ارزش افزوده ای ندارد، که موجب می شود سرعت توسعه کند و ملالت آور شود. مخزن هایی داشته باشیم که به مرور بزرگتر و بزرگتر می شوند و نکهداری و فهم شان دشوار خواهد شد. همچنین پنهان سازی EF در لایه ای دیگر یعنی اینکه نمی توانیم به معنی واقعی از EF استفاده کنیمدر مزمت Reposity Pattern در حین استفاده از EF:http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/ متاسفانه مثال های رسمی مایکروسافت مملو از استفاده از این الگوی منسوخ می باشد و همین موجب شده است که سردرگمی زیادی در توسعه دهندگان ایجاد شده و صدای انتقاد برخی بلند شود:http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application مطلبی به فارسی در همین زمینه:http://www.dotnettips.info/post/1773/repository-ها-روی-unitofwork-ایده-خوبی-نیستند مجددا در مورد استفاده از Unit Of Work و Entity Framework، این بار در سایت ASP.NET، که توصیه شده است از این الگو استفاده نشود:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application#repo