‫‫‫استفاده از الگوی mvp

حتماً تا به حال اسم mvp را چندین و چند بار شنیده و مطالبی را هم راجع به آن خوانده‌اید. mvp یک الگوی طراحی شبیه mvc است که بیشتر برای winform استفاده می‌شود. از جمله مزایای mvp عبارت‌اند از:

۱- Seperation of Concerns (جدا سازی بخش‌های مختلف): یعنی هر بخشی باید کار خودش را انجام دهد.
۲- loose coupling: کاهش وابستگی بین بخش‌های مختلف برنامه
۳- قابلیت‌های نگهداری و خوانایی بالا
۴- افزایش قابلیت unit test و تست پذیری
۵- کمک به جدا سازی کار طراح UI و برنامه‌نویس Code behind

پیاده‌سازی mvp هم مثل خیلی از design patternهای دیگر بر خلاف ظاهرش بسیار ساده است. mvp روش چندان عجیبی نیست به طوری که حتی ممکن است روش پیاده‌سازی UIی که خود شما تا حالا استفاده می‌کرده‌اید به طور ناخودآگاه شباهت زیادی به mvp داشته باشد. در روش mvp به ازای هر فرم سه کلاس برای model، view و presenter وجود دارد. البته برای view و model اینترفیس هم وجود دارد. view توسط فرم ویندوزی پیاده‌سازی می‌شود، model به منطق برنامه یا مثلاً دیتابیس وصل است، presenter هم رابط این دو تا است.

بهترین راه یادگیری mvp استفاده از مثال است. برای یادگیری بیشتر به منابع زیر مراجعه کنید:

http://www.dotnettips.info/2009/08/mvp.html
http://www.codeproject.com/KB/architecture/WinForms_MVP.aspx
http://codebetter.com/jeremymiller/2007/07/26/the-build-your-own-cab-series-table-of-contents/

‫‫‫Inversion of Control چیست؟

تا حالا شده که به خاطر دیدن نمونه کد یا یک روش نامانوس از خیر خواندن یا استفاده از سورس کدی گذشته باشید؟ حتی اگر مطمئن باشید آن چیز نامفهوم می‌تواند ابزار مناسبی برایتان باشد؟ یکی از نمونه کدهایی که همیشه مرا از کار روی بعضی سورس کدها فراری داده IoC.Resolve(“serverform”)‎ است.

همان طور که می‌توان از ظاهر این خط کد حدس زد، موضوع مربوط می‌شود به Inversion of Control با استفاده از Castle Windsor. مفهوم IoC ارتباط تنگانگی با Dependency Injection (همان DI) دارد. این دو مفهوم به طور خلاصه design patternهایی هستند که با کاهش وابستگی بین اجزا مختلف نرم‌افزار و اتوماتیک کردن روال instance گیری‌های طولانی از کلاس‌ها و interfaceهای مختلف به تولید نرم‌افزارهایی که تست و نگهداری راحت‌تری دارند کمک می‌کند.

به عنوان مثال فرض کنید کلاسی به اسم HtmlTitleRetriever دارید که constructor آن به دو اینترفیس IFileDownloader و ITitleScraper نیاز دارد. روش instance گرفتن از کلاس HtmlTitleRetriever بدون استفاده از IoC به شکل زیر است:

IFileDownloader downloader = new HttpFileDownloader();
ITitleScraper scraper = new StringParsingTitleScraper();
HtmlTitleRetriever retriever = new HtmlTitleRetriever(downloader, scraper);
حال با استفاده از IoC و مشخص کردن بعضی تنظیمات در app.config می‌توان از روش زیر برای instance گیری استفاده کرد:

HtmlTitleRetriever retriever = container.Resolve<HtmlTitleRetriever>();
این روش هم کد نویسی را خلاصه‌تر و راحت‌تر می‌کند و هم امکان توسعه و تغییر برنامه را در آینده می‌دهد بدون آن که نیاز به build و دستکاری مجدد باشد.

پ.ن.: این نوشته در واقع خلاصه‌ای از مطلب «Inversion of Control and Dependency Injection with Castle Windsor Container – Part I» می‌باشد.

‫محدودیت‌های Castle ActiveRecord

Castle ActiveRecord یک کتابخانه مفید برای استفاده از NHibernate است. این کتابخانه هم کار mapping را مشابه Fluent NHibernate ساده می‌کند و هم کار مدیریت session و خیلی کارهای دیگر را خودش مدیریت می‌کند. به طوری که استفاده از NHibernate بسیار ساده‌تر شود. Castle ActiveRecord در واقع پیاده‌سازی Design Patternی به همین نام یعنی Active Record است. با این که Castle ActiveRecord کار با NHibernate را بسیار ساده‌تر کرده ولی به خاطر همین سادگی، محدودیت‌هایی هم نسبت به استفاده مستقیم از NHibernate دارد. از جمله:

۱- الگوی Active Rercord به طور کلی مورد انتقاد است. بعضی‌ها معتقدند الگوی Active Record ناکارآمد است و می‌توان به جای آن از الگوهای بهتری مثل Repository Pattern استفاده کرد. دقت کنید که الگوی پیش‌فرض Castle ActiveRecord همان Active Record است اما می‌توان با الگوهای دیگری از جمله Unit of Work هم با آن کار کرد.

۲- در فرایند Schema Update آن نمی‌توان اسکریپت‌های update را قبل از اجرا دید.

۳- Second Level Cache در بیشتر متودهای کلاس ActiveRecordBase امکان پذیر نیست، از جمله بیشتر overloadهای متود FindAll. برای فعال بودن Second Level Cache باید در Criteriaها از SetCachable(true)‎ استفاده شود.

۴- Second Level Cache ظاهراً در ActiveRecordLinq هم به همان دلیل قبلی غیر فعال است. در LINQ موجود در NHibernate چه در provider قدیمی چه در NH 3 راه حل‌هایی وجود دارد ولی ظاهراً نمی‌توان از آنها در Castle ActiveRecord استفاده کرد.

قاعدتاً غیر از این‌ها محدودیت‌های دیگری هم وجود دارد اما آن چه که مهم است این است که عمده این محدودیت‌ها را می‌توان با ارث‌بری از کلاس ActiveRecordBase یا ActiveRecordMediator و افزودن امکانات مورد نظر به کلاس جدید دور زد. اگر هم پایه بودید می‌توانید یک branch از سورس کد Castle ActiveRecord ایجاد کرده، قابلیت مورد نظر را به آن اضافه کرده و patch آن را به تیم توسعه دهنده Castle ActiveRecord بفرستید تا اگر مورد قبول واقع شد، آن امکان من بعد در نسخه‌های رسمی Castle ActiveRecord اضافه شود.