مطالب دوره‌ها
الگوی معکوس سازی کنترل چیست؟
معکوس سازی کنترل (Inversion of Control) الگویی است که نحوه پیاده سازی اصل معکوس سازی وابستگی‌ها (Dependency inversion principle) را بیان می‌کند. با معکوس سازی کنترل، کنترل چیزی را با تغییر کنترل کننده، معکوس می‌کنیم. برای نمونه کلاسی را داریم که ایجاد اشیاء را کنترل می‌کند؛ با معکوس سازی آن به کلاسی یا قسمتی دیگر از سیستم، این مسئولیت را واگذار خواهیم کرد.
IoC یک الگوی سطح بالا است و به روش‌های مختلفی به مسایل متفاوتی جهت معکوس سازی کنترل، قابل اعمال می‌باشد؛ مانند:
- کنترل اینترفیس‌های بین دو سیستم
- کنترل جریان کاری برنامه
- کنترل بر روی ایجاد وابستگی‌ها (جایی که تزریق وابستگی‌ها و DI ظاهر می‌شوند)


سؤال: بین IoC و DIP چه تفاوتی وجود دارد؟

در DIP (قسمت قبل) به این نتیجه رسیدیم که یک ماژول سطح بالاتر نباید به جزئیات پیاده سازی‌های ماژولی سطح پایین‌تر وابسته باشد. هر دوی این‌ها باید بر اساس Abstraction با یکدیگر ارتباط برقرار کنند. IoC روشی است که این Abstraction را فراهم می‌کند. در DIP فقط نگران این هستیم که ماژول‌های موجود در لایه‌های مختلف برنامه به یکدیگر وابسته نباشند اما بیان نکردیم که چگونه.


معکوس سازی اینترفیس‌ها

هدف از معکوس سازی اینترفیس‌ها، استفاده صحیح و معنا دار از اینترفیس‌ها می‌باشد. به این معنا که صرفا تعریف اینترفیس‌ها به این معنا نیست که طراحی صحیحی در برنامه بکار گرفته شده است و در حالت کلی هیچ معنای خاصی ندارد و ارزشی را به برنامه و سیستم شما اضافه نخواهد کرد.
برای مثال یک مسابقه بوکس را درنظر بگیرید. در اینجا Ali یک بوکسور است. مطابق عادت معمول، یک اینترفیس را مخصوص این کلاس ایجاد کرده، به نام IAli و مسابقه بوکس از آن استفاده خواهد کرد. در اینجا تعریف یک اینترفیس برای Ali، هیچ ارزش افزوده‌ای را به همراه ندارد و متاسفانه عادتی است که در بین بسیاری از برنامه نویس‌ها متداول شده است؛ بدون اینکه علت واقعی آن‌را بدانند و تسلطی به الگوهای طراحی برنامه نویسی شیءگرا داشته باشند. صرف اینکه به آن‌ها گفته شده است تعریف اینترفیس خوب است، سعی می‌کنند برای همه چیز اینترفیس تعریف کنند!
تعریف یک اینترفیس تنها زمانی ارزش خواهد داشت که چندین پیاده سازی از آن ارائه شود. در مثال ما پیاده سازی‌های مختلفی از اینترفیس IAli بی‌مفهوم است. همچنین در دنیای واقعی، در یک مسابقه بوکس، چندین و چند شرکت کننده وجود خواهند داشت. آیا باید به ازای هر کدام یک اینترفیس جداگانه تعریف کرد؟ ضمنا ممکن است اینترفیس IAli متدی داشته باشد به نام ضربه، اینترفیس IVahid متد دیگری داشته باشد به نام دفاع.
کاری که در اینجا جهت طراحی صحیح باید صورت گیرد، معکوس سازی اینترفیس‌ها است. به این ترتیب که مسابقه بوکس است که باید اینترفیس مورد نیاز خود را تعریف کند و آن هم تنها یک اینترفیس است به نام IBoxer. اکنون Ali، Vahid و سایرین باید این اینترفیس را جهت شرکت در مسابقه بوکس پیاده سازی کنند. بنابراین دیگر صرف وجود یک کلاس، اینترفیس مجزایی برای آن تعریف نشده و بر اساس معکوس سازی کنترل است که تعریف اینترفیس IBoxer معنا پیدا کرده است. اکنون IBoxer دارای چندین و چند پیاده سازی خواهد بود. به این ترتیب، تعریف اینترفیس، ارزشی را به سیستم افزوده است.
به این نوع معکوس سازی اینترفیس‌ها، الگوی provider model نیز گفته می‌شود. برای مثال کلاسی که از چندین سرویس استفاده می‌کند، بهتر است یک IService را ایجاد کرده و تامین کننده‌هایی، این IService را پیاده سازی کنند. نمونه‌ای از آن در دنیای دات نت، Membership Provider موجود در ASP.NET است که پیاده سازی‌های بسیاری از آن تاکنون تهیه و ارائه شده‌اند.




معکوس سازی جریان کاری برنامه

جریان کاری معمول یک برنامه یا Noraml flow، عموما رویه‌ای یا Procedural است؛ به این معنا که از یک مرحله به مرحله‌ای بعد هدایت خواهد شد. برای مثال یک برنامه خط فرمان را درنظر بگیرید که ابتدا می‌پرسد نام شما چیست؟ در مرحله بعد مثلا رنگ مورد علاقه شما را خواهد پرسید.
برای معکوس سازی این جریان کاری، از یک رابط کاربری گرافیکی یا GUI استفاده می‌شود. مثلا یک فرم را درنظر بگیرید که در آن دو جعبه متنی، کار دریافت نام و رنگ را به عهده دارند؛ به همراه یک دکمه ثبت اطلاعات. به این ترتیب بجای اینکه برنامه، مرحله به مرحله کاربر را جهت ثبت اطلاعات هدایت کند، کنترل به کاربر منتقل و معکوس شده است.


معکوس سازی تولید اشیاء

معکوس سازی تولید اشیاء، اصل بحث دوره و سری جاری را تشکیل می‌دهد و در ادامه مباحث، بیشتر و عمیق‌تر بررسی خواهد گردید.
روش متداول تعریف و استفاده از اشیاء دیگر درون یک کلاس، وهله سازی آن‌ها توسط کلمه کلیدی new است. به این ترتیب از یک وابستگی به صورت مستقیم درون کدهای کلاس استفاده خواهد شد. بنابراین در این حالت کلاس‌های سطح بالاتر به ماژول‌های سطح پایین، به صورت مستقیم وابسته می‌گردند.
برای اینکه این کنترل را معکوس کنیم، نیاز است ایجاد و وهله سازی این اشیاء وابستگی را در خارج از کلاس جاری انجام دهیم. شاید در اینجا بپرسید که چرا؟
اگر با الگوی طراحی شیءگرای Factory آشنا باشید، همان ایده در اینجا مدنظر است:
Button button;
switch (UserSettings.UserSkinType)
{
   case UserSkinTypes.Normal:
      button = new Button();
      break;
   case UserSkinTypes.Fancy:
      button = new FancyButton();
      break;
}
در این مثال بر اساس تنظیمات کاربر، قرار است شکل دکمه‌های نمایش داده شده در صفحه تغییر کنند.
حال در این برنامه اگر قرار باشد کار و کنترل محل وهله سازی این دکمه‌ها معکوس نشود، در هر قسمتی از برنامه نیاز است این سوئیچ تکرار گردد (برای مثال در چند ده فرم مختلف برنامه). بنابراین بهتر است محل ایجاد این دکمه‌ها به کلاس دیگری منتقل شود مانند ButtonFactory و سپس از این کلاس در مکان‌های مختلف برنامه استفاده گردد:
 Button button = ButtonFactory.CreateButton();
در این حالت علاوه بر کاهش کدهای تکراری، اگر حالت دکمه جدیدی نیز طراحی گردید، نیاز نخواهد بود تا بسیاری از نقاط برنامه بازنویسی شوند.
بنابراین در مثال فوق، کنترل ایجاد دکمه‌ها به یک کلاس پایه قرار گرفته در خارج از کلاس جاری، معکوس شده است.


انواع معکوس سازی تولید اشیاء

بسیاری شاید تصور کنند که تنها راه معکوس سازی تولید اشیاء، تزریق وابستگی‌ها است؛ اما روش‌های چندی برای انجام اینکار وجود دارد:
الف) استفاده از الگوی طراحی Factory (که نمونه‌ای از آن‌را در قسمت قبل مشاهده کردید)
ب) استفاده از الگوی Service Locator
 Button button = ServiceLocator.Create(IButton.Class)
در این الگو بر اساس یک سری تنظیمات اولیه، نوع خاصی از یک اینترفیس درخواست شده و نهایتا وهله‌ای که آن‌را پیاده سازی می‌کند، به برنامه بازگشت داده می‌شود.
ج) تزریق وابستگی‌ها
Button button = GetTheButton();
Form1 frm = new Form1(button);
در اینجا نوع وابستگی مورد نیاز کلاس Form1 در سازنده آن تعریف شده و کار تهیه وهله‌ای از آن وابستگی در خارج از کلاس صورت می‌گیرد.

به صورت خلاصه هر زمانیکه تولید و وهله سازی وابستگی‌های یک کلاس را به خارج از آن منتقل کردید، کار معکوس سازی تولید وابستگی‌ها انجام شده است.
پروژه‌ها
Iris Membership برای احراز هویت کاربران در ASP.NET MVC به صورت پویا
این پروژه، یک چارچوب کاری برای احراز هویت کاربران به صورت گروه بندی شده و تعیین سطوح دسترسی به صورت پویا است.
نکته: پروژه هنوز تکمیل نشده است و می‌توانید بیلدهای شبانه آن را از مخزن کد ذکر شده دریافت نمایید.
ممنون میشم که در تکمیل پروژه، پیشنهادات و ایده‌ها خود را بیان کنید.
توضیحات تکمیلی: به زودی
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت دوازدهم - توزیع برنامه
- در مورد تنظیمات سمت سرور AngularJS 2.0 در ASP.NET Core 1.0، در قسمت «معرفی بسته‌ی نیوگت Microsoft.AspNetCore.SpaServices» بحث شده‌است.
- اما ... Gulp جاوا اسکریپتی اساسا وابستگی خاصی به فناوری‌های سمت سرور ندارد. در اینجا فقط نحوه‌ی مسیردهی این پوشه‌ها مهم هستند (و Task runner آن فقط به این مسایل دقت می‌کند):
var appFolder = "./app";
var outFolder = "wwwroot";
در اینجا app/. به این معنا است که محل واقع شدن فایل تنظیمات gulp و همچنین فایل systemjs.config.js، یک سطح بالاتر هستند از پوشه‌ی app (جایی که قرار است فایل‌های اصلی از آن دریافت شوند) و همچنین پوشه‌ی wwwroot ذکر شده (جایی که قرار است فایل‌های نهایی کپی شوند):
gulpfile.js
systemjs.config.js
--app
--wwwroot
پاسخ به بازخورد‌های پروژه‌ها
شماره صفحه در هدر سفارشی و خروجی اکسل
1- ابتدا کش شدن هدر را غیرفعال کنید:
.PagesHeader(header =>
{
    header.CacheHeader(cache: false)
سپس callback مربوط به ایجاد هدر (RenderingReportHeader)، به ازای هر بار رندر شدن، یکبار فراخوانی می‌شود (اگر کش شدن هدر فعال باشد، فقط یکبار فراخوانی می‌شود). در اینجا یک متغیر به نام pageNumber تعریف کنید و مقدار آن‌را هر بار یک واحد افزایش دهید (یک فیلد خصوصی در سطح کلاس) . سپس این مقدار را در هدر سفارشی که طراحی می‌کنید، قرار دهید (به هر نحو و شکلی که صلاح می‌دانید؛ خروجی PdfGrid هر شکل دلخواهی را می‌تواند داشته باشد).
2- چنین امکانی وجود ندارد. این خروجی فقط در خود فایل قرار می‌گیرد و نحوه‌ی تشکیل آن هم دقیقا در حین تشکیل فایل PDF انجام می‌شود.
مطالب
WF:Windows Workflow #1
چرا از WorkFlow در پروژه‌های نرم افزاری استفاده می‌شود ؟

زمانیکه در حال انجام یک پروژه نرم افزاری هستید که این پروژه دارای پیچیدگی خاصی از لحاظ فرآیند و قوانین کاری می‌باشد بهترین راه حل Workflow Engine یا BPMS Engine می‌باشد.
البته شایان ذکر می‌باشد که میان این دو Engine تفاوت‌های بسیاری وجود دارد. شاید خیلی از برنامه نویس‌ها از خود این سوال را بپرسند که تمام قوانین کاری و فرآیند‌های یک سازمان را می‌توان با کد نویسی انجام داد، چه نیازی به این Engine‌ها برای مکانیزه کردن فرایند‌های یک سازمان است؟
جواب این سوال را با یک مثال ساده آغاز می‌کنم :
فرض کنید یک فرآیند خیلی ساده داریم که کار آن دریافت اطلاعات از بانک اطلاعاتی و ارسال آن به مدیر بخش و دریافت تایید از طرف مدیر می‌باشد. این کار توسط دو کاربر انجام می‌شود که در سازمان نقش و سطح دسترسی مختلفی را دارا می‌باشند و به این نکته توجه کنید و آن اینکه فرض کنید زمانیکه نرم افزار شما در سازمانی در حال انجام کار می‌باشد به شما خبر داده می‌شود که کاربر x به مرخصی رفته و نقش آن به کسی دیگر سپرده شده است و این کار باید از طریق سیستم و با تایید مدیر انجام شود و یا سطح دسترسی افراد در سازمان عوض شود. این ساده‌ترین فرآیند‌ی است که در زمان انجام پروژه با آن رو به رو می‌شویم .
اگر این فرآیند‌های ساده را بخواهیم با  100% کد نویسی  انجام دهیم، تعداد خط کد‌ها بسیار زیاد، زمان بر و انرژی زیادی از گروه گرفته می‌شود و مشکل به تعداد خط کد زیاد نیست، مشکل اصلی آن جایی است که برای پروژه بعدی قصد استفاده از این سیستم را داشته باشیم و نیاز به تغییر در بعضی از قسمت‌های سیستم باشد در این قسمت است که بیشترین زمان و انرژی از گروه گرفته می‌شود ولی در صورت استفاده از Workflow می‌توان در کمترین زمان و هزینه، پیچیده‌ترین Business Logic‌ها را پیاده سازی کرد.
نکته دیگری که در مورد اینگونه Engine‌ها باید گفته شود این است که در معماری SOA نقش فراوانی را دارا می‌باشند .
مطالب دوره‌ها
نگهداری سرور RavenDB
نگهداری سرور RavenDB شامل مواردی است مانند مدیریت فایل‌های آن، اضافه کردن یا حذف بانک‌های اطلاعاتی و تهیه پشتیبان از آن‌ها که در ادامه بررسی خواهند شد.


ایجاد و حذف بانک‌های اطلاعاتی جدید

برای این منظور به آدرس http://localhost:8080 مراجعه و از طریق کنسول مدیریتی تحت وب RavenDB بر روی دکمه New database کلیک کنید.


در صفحه باز شده می‌توان نام دیتابیس را مشخص کرد و همچنین در صورت نیاز افزونه‌هایی مانند فشرده سازی یا رمزنگاری اطلاعات را نیز فعال نمود.


پس از ایجاد دیتابیس، برای حذف آن، بر روی نام دیتابیس کلیک راست کرده و گزینه Delete را انتخاب کنید


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


و یا سرور RavenDB را خاموش یا stop کنید. سپس به پوشه Database کنار فایل Raven.Server.exe مراجعه کرده، بانک اطلاعاتی خود را یافته و سپس کل پوشه آن‌را Delete کنید.


سؤال: چگونه با دیتابیس‌های ایجاد شده کار کنیم؟

تاکنون تمام مثال‌های برنامه با بانک اطلاعاتی پیش فرض RavenDB کار کردند (چیزی شبیه به master database در اس کیوال سرور) و هیچگاه ابتدا یک دیتابیس جدید و مستقل را برای انجام آزمایشات خود، ایجاد نکردیم. بدیهی است این روش برای محیط‌های کاری توصیه نمی‌شود.


برای نمونه در اینجا به System database این مجموعه وارد شده‌ایم که تعریف جزئیات بانک اطلاعاتی جدید ایجاد شده را در خود دارد.

جهت استفاده از بانک اطلاعاتی جدید ایجاد شده در کدهای خود، فقط کافی است خاصیت DefaultDatabase یک DocumentStore مقدار دهی شود:
 using (var store = new DocumentStore
{
    Url = "http://localhost:8080",
    DefaultDatabase = "Test2"
}.Initialize())
{
  //...
}


تهیه پشتیبان از بانک‌های اطلاعاتی و بازیابی آن‌ها

ابتدا نیاز است تمام بسته‌های مورد نیاز را یکجا از آدرس http://ravendb.net/download تهیه کنید. سپس به پوشه backup آن مراجعه کرده و از فایل اجرایی Raven.Backup.exe آن می‌توان جهت تهیه پشتیبان از بانک اطلاعاتی خاصی استفاده نمود. لازم به ذکر است که این برنامه باید با سطح دسترسی ادمین اجرا شود.
 Raven.Backup.exe --url==http://localhost:8080 --dest=d:\backup
برنامه backup، آدرس سرور را گرفته و سپس فایل‌های پشتیبان تهیه شده را در آدرس مشخصی ذخیره می‌کند. برای مدیریت اجرای روزانه آن نیز از برنامه استاندارد windows task schedule manager استفاده نمائید. به علاوه امکانات Shadow copy ویندوز نیز در اینجا مفید خواهند بود.

برای بازیابی و Restore یک بانک اطلاعاتی ابتدا دستور Raven.Server.exe /help را صادر کنید تا کلیه سوئیچ‌های این برنامه مشخص شوند. یکی از آن‌ها Restore نام دارد که پارامترهای dest و src را دریافت می‌کند (کجا بازیابی شود و از کجا اطلاعات را بخواند).

همچنین بجای backup و restore، امکان export و import نیز وجود دارند و برای انجام آن از برنامه Raven.Smuggler.exe که کنار Raven.Server.exe قرار دارد، می‌توان استفاده کرد.
برای تهیه خروجی (که در حقیقت تهیه یک dump فشرده شده از اسناد JSON موجود است):
 Raven.Smuggler.exe out http://localhost:8080/ dump.raven
و برای بازیابی خروجی تولید شده:
 Raven.Smuggler.exe in http://localhost:8080/ dump.raven