مطالب
آشنایی با Feature Toggle - بخش اول
فرض کنید میخواهید برای بخش‌هایی از نرم افزاری که طراحی کرده‌اید ، امکانی را در نظر بگیرید که بتوانید زمانیکه نرم افزار در حال استفاده‌است، قابلیت‌هایی از آن‌را فعال یا غیرفعال نمایید؛ بدون اینکه نرم افزار از دسترس خارج شود. Feature Toggle که تحت عنوان Feature Flag هم شناخته می‌شود همین امکان را برای ما به ارمغان می‌آورد و ما را قادر می‌سازد تا قابلیت‌هایی را از نرم افزار، فعال یا غیرفعال کنیم، بدون اینکه نیاز باشد نرم افزار از دسترس مشتریان خارج شود و یا نیاز باشد نسخه‌ی جدیدی از نرم افزار  منتشر شود. برای مثال قابلیت ثبت نام کاربران را در بازه‌های خاصی غیرفعال کنیم و یا فرض کنید قابلیت جدیدی به نرم افزار اضافه کرده‌اید و میخواهید بعد از پابلیش، در یک بازه زمانی که نرم افزار شما بازدید کننده‌های کمتری دارد، آن‌را موقتا فعال کنید، نتیجه خروجی را ببینید و سپس آن را غیر فعال نمایید. در ادامه این مقاله سعی خواهیم کرد ابتدا با یک مثال ساده با این قابلیت آشنا شویم و سپس به معرفی یکی از کتابخانه‌های محبوب در این زمینه بپردازیم.
Feature Toggle چیزی بیشتر از یک دستور IF نیست، اگر شرط مورد نظر برقرار بود، کد را اجرا میکند، در غیر اینصورت از اجرای آن بخش صرف نظر میکند.
IF (currentYear<2023){
alert('Wear a mask!');
}
در قطعه کد فوق، سال جاری را چک کرده‌ایم و گفته‌ایم اگر سال جاری کمتر از سال 2023 بود، به بازدید کننده یک پیغام را نمایش دهیم. حال فرض کنید بیماری کرونا، پیش از سال 2023 از بین برود، ولی طبق این شرط همچنان پیغام به کاربران نمایش داده میشود. میتوانیم فعال و غیر فعال بودن نمایش این پیغام را یا از دیتابیس و یا از فایل appsetting.json  بخوانیم که در این حالت  به صورت زیر می‌باشد :
var showCoronaAlert=_cofiguration.GetValue<bool>("Features:showCoronaAlert"); // or read this from Database
If(showCoronaAlert){
alert(Wear a amask!);
}
در این روش بجای اینکه تاریخ را چک کنیم و بر اساس آن تصمیم بگیریم که آیا پیغامی نمایش داده شود یا نه، وضعیت نمایش آن را از فایل تنظیمات و یا دیتابیس خوانده‌ایم. در این حالت دیگر نیازی به تغییر و انتشار نسخه‌ی جدیدی از نرم افزار نیست و فقط کافی‌است مقدار مربوط به نمایش پیغام را در دیتابیس و یا فایل تنظیمات، به روزسانی نماییم.

 کتابخانه  Microsoft.FeatureManagement
کتابخانه  Microsoft.FeatureManagement  توسط تیم اژور پیاده سازی و نوشته شده‌است و برای خواندن اطلاعات، از همان IConfiguration استفاده میکند که ما را قادر می‌سازد تنظیمات را از منابع مختلفی بخوانیم  و همچنین  قابلیت‌های آن فراتر از تنظیم یک مقدار با true/false می‌باشد که در ادامه با بعضی از آنها آشنا خواهیم شد.
ابتدا نیاز هست این کتابخانه را به صورت زیر نصب نماییم :
Install-Package Microsoft.FeatureManagement

سپس نیاز هست در متد ConfigureService، سرویس مربوطه را اضافه نماییم :
using Microsoft.FeatureManagement;
public void ConfigureServices(IServiceCollection services)
{
    services.AddFeatureManagement();
}

این کتابخانه به صورت پیش فرض، اطلاعات feature‌ها را از بخشی (section) تحت عنوان FeatureManagement  از فایل appsetting.json می‌خواند. پس نیاز داریم این بخش را در appsetting.json تعریف نماییم  ( لیست تمامی قابلیت‌هایی را که قصد داریم به صورت داینامیک فعال/غیرفعال کنیم، در این بخش اضافه خواهیم کرد):
"FeatureManagement": {
   
}
اگر تمایل داشتید از اسم دیگری برای بخش تنظیمات، در فایل appsetting. json  استفاده نمایید، می‌توانید به صورت زیر این کار را انجام دهید :
public void ConfigureServices(IServiceCollection services)
{
 services.AddFeatureManagement(Configuration.GetSection("MyFeatureManagement"))
}
در این مقاله از همان اسم پیش فرض استفاده شده است.
افزودن یک قابلیت جدید
"FeatureManagement": {
   "MaskAlert":true
}

همان مثال بالا را  در بخش FeatureManagement  اضافه کرده‌ایم  و مقدار true را به معنی فعال بودن، برای آن در نظر گرفته‌ایم. این حالت، ساده‌ترین روش ثبت یک قابلیت با استفاده از این کتابخانه می‌باشد. برای بررسی وضعیت هر کدام از قابلیت‌ها باید اینترفیس  IFeatureManager   را به کلاس مربوطه تزریق نماییم و سپس بر اساس نام قابلیت، وضعیت آن را بررسی نماییم:
 public class HomeController : Controller
    {
        private readonly IFeatureManager _featureManager;

        public HomeController(IFeatureManager featureManager)
        {
            _featureManager = featureManager;
        }
        public async Task<IActionResult> Index()
        {
            if(await _featureManager.IsEnabledAsync("MaskAlert"))
            {
                // show messeage
            }

            return View();
        }
    }
اگر نیاز هست از اسم دیگری برای بخش (section)

فعال سازی بر اساس تاریخ (TimeWindowsFilter)
یکی از قابلیت‌های این کتابخانه، فعال سازی بر اساس بازه زمانی هست. اگر نیاز دارید یک قابلیت در یک بازه‌ی خاص فعال شود، میتوانید از این قابلیت استفاده کنید. برای فعال سازی این امکان، باید فیلتر TimeWindowFilter را که به صورت توکار به همراه کتابخانه وجود دارد، به صورت زیر در متد configureServices ثبت نماییم:
public void ConfigureServices(IServiceCollection services)
{ 
    services.AddFeatureManagement().AddFeatureFilter<TimeWindowFilter>();
}

و سپس یک Feature را در بخش FeatureManagement همانند زیر تعریف میکنیم که توسط آن مشخص کرده‌ایم این قابلیت در بازه‌ی زمانی بین دو تاریخ تعریف شده، فعال باشد :
 "FeatureManagement": {
    "EmergencyBanner": {
      "EnabledFor": [
        {
          "Name": "Microsoft.TimeWindow",
          "Parameters": {
            "Start": "01 Mar 2021 12:00:00 +00:00",
            "End": "01 Apr 2021 12:00:00 +00:00"
          }
        }
      ]
    }
  }
و نحوه‌ی بررسی فعال بودن آن، همانند روش قبل می‌باشد و فقط کافیست اسم Feature را به متد IsEnabledAsync بدهیم:
if(await _featureManager.IsEnabledAsync("EmergencyBanner")){
// show Emergency banner 
}

 پارامتر‌های Start و End میتوانند به صورت تکی هم استفاده شوند؛ به این معنا که میتوانید فقط پارامتر start را مقدار دهی کنید و در این حالت از تاریخ مورد نظر به بعد، Feature مورد نظر فعال می‌باشد و یا اگر فقط پارامتر End مقدار دهی شود، Feature مورد نظر فقط تا تاریخ تعیین شده فعال هست و بعد از آن برای همیشه غیرفعال می‌شود.
در زیر، نمونه‌ای از این حالت تنظیم شده‌است :
"FeatureManagement": {
    "EmergencyBanner": {
      "EnabledFor": [
        {
          "Name": "Microsoft.TimeWindow",
          "Parameters": {
            "End": "01 Apr 2021 12:00:00 +00:00"
          }
        }
      ]
    }
  }

فیلتر‌های سفارشی
از دیگر مزایای این کتابخانه این هست که محدود به فیلترهای توکار خود آن نیستیم و امکان توسعه و نوشتن فیلتر‌های سفارشی را به ما میدهد. برای مثال اگر یک قابلیت را در نرم افزار پیاده سازی کرده‌ایم که میخواهیم فقط بر روی مرورگر‌های خاصی در دسترس باشد، میتوانیم به صورت زیر این کار را انجام دهیم:
ابتدا در appsetting.json قابلیت (Feature) مورد نظر را به صورت زیر تعریف می‌کنیم :
"FeatureManagement": {
    "ChatV2": {
      "EnabledFor": [
        {
          "Name": "BrowserFilter",
          "Parameters": {
            "AllowedBrowsers": [ "Chrome" ]
          }
        }
      ]
    }
  }
سپس فیلتر سفارشی را به صورت زیر پیاده سازی میکنیم :
[FilterAlias("BrowserFilter")]
public class BrowserFilter:IFeatureFilter
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public BrowserFilter(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
        }

        public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
        {
            var userAgent = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
            var settings = context.Parameters.Get<BrowserFilterSettings>();
            return Task.FromResult(settings.AllowedBrowsers.Any(userAgent.Contains));
        }
    }

کلاس BrowserFilter :
  public class BrowserFilterSettings
    {
        public string[] AllowedBrowsers { get; set; }
    }
بعد از پیاده سازی فیلتر فوق نیاز هست فیلتر سفارشی را که در بالا نوشتیم، در متد ConfigureServices ثبت نماییم. با توجه به اینکه برای تشخیص نوع مروگر کاربر نیاز هست  هدر درخواست را بررسی کنیم، پس نیاز هست IHttpContextAccessor را هم ثبت نماییم:
public void ConfigureServices(IServiceCollection services)
        {
            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddFeatureManagement()
                .AddFeatureFilter<BrowserFilter>();
        }
و برای بررسی فعال بودن قابلیت مورد نظر فقط کافیست مانند قبل، اسم قابلیت مورد نظر را به صورت زیر بررسی کنیم :
if(await _featureManager.IsEnabledAsync("ChatV2")){
// do something 
}

* از دیگر قابلیت‌های این کتابخانه، فعال و غیر فعال کردن کنترلر و اکشن متدها بر اساس وضعیت Feature‌ها می‌باشد که در بخش دوم این مقاله به توضیح این موارد خواهیم پرداخت.
مطالب
مایکرو سرویس‌ها - قسمت 2 - بررسی ویژگی‌ها
در قسمت قبل با مفهوم مایکرو سرویس‌ها آشنا شدیم. سرویس‌های کوچک و مجزایی که بصورت مستقل، قابلیت توسعه و استقرار دارند و در راستای انجام یک قابلیت کسب و کار در اختیار دیگران قرار می‌گیرند.

ویژگی‌های یک مایکرو سرویس چیست؟

بعد از آشنایی با معماری مایکرو سرویس‌ها می‌خواهیم با ویژگی‌های آن آشنا شویم. البته باید به این نکته توجه داشت که همه‌ی معماری‌های مایکروسرویس‌ها این ویژگی‌ها را ندارند؛ ولی میتوان انتظار داشت اکثر آن‌ها این ویژگی‌ها را از خود به نمایش بگذارند.

Componentization via Services 

تعریف ما از component، واحدی از نرم افزار می‌باشد که به تنهایی قابل جایگزینی و به‌روز رسانی می‌باشد.
همانطور که گفته شد، مایکرو سرویس‌ها یک نرم افزار را به سرویس‌های (business component) کوچکتری تقسیم میکنند که به تنهایی قابل توسعه و استقرار می‌باشند. ما کتابخانه‌ها را به عنوان component در نظر میگیریم که به نرم افزار ما پیوند خورده‌اند و به وسیله فراخوانی توابع در پروسه نرم افزار قابل استفاده می‌باشند. در حالیکه سرویس‌ها componentهایی هستند که خارج از پروسه نرم افزار ما می‌باشند و به وسیله مکانیزم‌های ارتباطی مانند Web Service Request و Remote Procedure Call قابل دسترسی هستند.
در سیستم های یکپارچه که از چندین  component تشکیل شده‌اند و این componentها در جریان یک پروسه با هم در ارتباط هستند، اگر بخواهیم در یک component تغییر ایجاد کنیم، این تغییر نیازمند استقرار مجدد کل سیستم می‌باشد. در حالیکه در معماری مایکرسرویس، کافی است شما  component (سرویس) ای را که تغییر کرده‌است، دوباره مستقر کنید و سایر بخشهای سیستم از این تغییر تاثیر نمی‌پذیرند.

Technology Heterogeneity 

یک سیستم را در نظر بگیرید که از همکاری  چندین سرویس تشکیل شده‌است. ما میتوانیم تصمیم بگیریم که برای هر کدام از سرویسها از تکنولوژی متفاوتی استفاده کنیم. این امر به ما اجازه می‌دهد برای حل هر مشکل، از بهترین ابزار و تکنولوژی استفاده کنیم. این امر بر خلاف سیستم‌هایی که تنها باید از تکنولوژی بکار رفته در سیستم استفاده کنند، انعطاف پذیری سیستم را بسیار بالا می‌برد.
برای روشن شدن موضوع فرض کنید می‌خواهیم در بخشی از سیستم، performance را افزایش دهیم. برای این امر میتوانیم از هر تکنولوژی که به ما کمک میکند، استفاده کنیم. برای نمونه در یک سیستم شبکه اجتماعی، می‌توانیم اطلاعات مربوط به کاربران و ارتباطات آن‌ها را در یک دیتابیس مبتنی بر گراف و اطلاعات مربوط به پست‌ها و نظرات کاربران را در یک دیتابیس سندگرا ذخیره کنیم. به این ترتیب مشاهده میکنیم که وابسته‌ی به تکنولوژی خاصی نمی‌باشیم و می‌توانیم بر اساس نیاز خود، از تکنولوژی مورد نظر بهره ببریم.


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

Resilience 

چنانچه یکی ازسرویسها دچار اشکال شود و این مسئله بصورت زنجیروار برای تمام سرویس‌ها رخ ندهد، با جدا شدن آن سرویس، درروند کار سیستم خللی بوجود نمی‌آید و سیستم بدون کمترین مشکلی به ادامه کار خود می‌پردازد. یعنی محدوده یک سرویس، دیوار حائلی می‌شود تا سایر بخشها تاثیر نپذیرند. در سیستم‌های یکپارچه چنانچه یک سرویس دچار اشکال شود، سایر بخش‌های سیستم نیز غیر قابل استفاده می‌شوند. البته می‌توان با نصب نسخه‌های متفاوتی بر روی ماشین‌های متفاوت (Scale out)، تاثیر اینگونه اختلالات را تا حدودی کاهش داد. اما بوسیله مایکرو سرویسها می‌توانیم سیستم‌هایی را بسازیم که قادرند با خطاهای بوجود آمده در سرویس‌ها به‌درستی رفتار کنند؛ تا خللی در کار سیستم ایجاد نشود.

Scaling

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


Gilt  یک خرده فروش آنلاین در صنعت مد می‌باشد که  بخاطر مسائل Performance به معماری مایکروسرویس‌ها روی آورد. آنها در سال 2007 با یک نرم افزار یکپارچه شروع به کار کردند. اما بعد از دوسال سیستم آنها قادر به مقابله با ترافیک سایت نبود. آنها با تقسیم بندی قسمت‌های اصلی سیستم خود به مایکرو سرویسها، توانستند خیلی بهتر و موثرتر با ترافیک رسیده مقابله کنند و قابلیت دسترسی پذیری سیستم را افزایش دهند. در حال حاضر سیستم  آنها از حدود 450 مایکرو سرویس تشکیل شده که هر کدام روی چندین ماشین مختلف در حال اجرا می‌باشند.


Ease of Deployment 

تغییر حتی یک خط کد، در برنامه‌ای که از چندین میلیون خط تشکیل شده است، ما را ملزم به استقرار مجدد کل سیستم  و انتشار نسخه جدید می‌کند. این استقرار می‌تواند تاثیر و ریسک بالایی را داشته باشد و ما را مجبور به تغییرات بیشتر و انتشار نسخه‌های دیگر کند که این حجم زیاد تغییرات ممکن است به محصول ما ضربه بزند.
اما در مایکرو سرویس‌ها یک تغییر کوچک، تمام سیستم را تحت تاثیر قرار نمی‌دهد. بلکه تنها تغییرات مربوط به سرویس مورد نظر می‌باشد که به صورت مستقل قابلیت استقرار را دارد و چنانچه سیستم دچار مشکل شود، منشاء تغییرات کاملا مشخصی می‌باشد و می‌توان سریعتر سیستم را به وضعیت قابل اطمینان بازگرداند. این ویژگی یکی از مهمترین دلایلی می‌باشد که شرکت‌هایی مانند Netflix و Amazon  به پیاده سازی این معماری روی آورده‌اند.

Organizational Alignment 

بسیاری از ما مشکلات مربوط به پروژه‌های بزرگ و تیم‌های بزرگ را تجربه کرده‌ایم و این مشکلات زمانیکه اعضای تیم به‌صورت متمرکز در کنار هم نباشند، افزایش پیدا می‌کند. ما میدانیم که اگر یک تیم کوچک، بر روی قطعه کد کوچکتری کار کند، می‌تواند بسیار موثرتر باشد تا زمانیکه یک تیم بزرگ، درگیر یک کد بزرگ شود.
مایکرو سرویس‌ها این امکان را به ما می‌دهند تا معماری خود را با ساختار سازمانی خود هم راستا کنیم  و به ما کمک میکنند تا با تقسیم ساختار نرم افزار به بخش‌های کوچکتر وایجاد تیم‌های کوچکتر مختص هر بخش، بازدهی و تاثیر تیم‌ها را در سازمان، افزایش دهیم.

Composability

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


Optimizing for Replaceability

اگر شما در یک سازمان متوسط و یا بزرگ، مشغول به کار باشید، ممکن است با یک سیستم بزرگ و قدیمی مواجه شده باشید که در گوشه‌ای از سازمان در حال استفاده می‌باشد و هیچ کسی رغبت نزدیک شدن به آن و دست بردن در آن را ندارد و اگر کسی از شما بپرسد «چرا نمی‌توان آن را تغییر داد؟» خواهید گفت این کار، بسیار پرریسک و پردردسر است.
با استفاده از معماری مایکروسرویس، هزینه این تغییرات به مراتب کمتر و تغییرات با ضریب اطمینان بالاتری انجام می‌شوند.
مطالب
توسعه برنامه های Cross Platform با Xamarin Forms & Bit Framework - قسمت سوم
در قسمت قبل، محیط توسعه نرم افزار مد نظرمان را ایجاد کردیم و توانستیم پروژه پیش فرض Xamarin forms را بیلد کنیم. حالا قصد داریم تا یک مثال ساده را با هم بررسی کنیم و آن را بر روی ویندوز تست کنیم. در قسمت بعدی نیز همین مثال ساده را بر روی Android و در قسمت بعدتر نیز بر روی iOS تست می‌کنیم. پس از اطمینان از اینکه امکان تست برنامه را بر روی هر سه پلتفرم یافته‌اید، بر روی آموزش موارد بیشتری از Xamarin Forms تمرکز می‌کنیم.
برای شروع، Xaml Live را از Visual Studio Marketplace دانلود کنید.
سپس در صورتیکه ابزار git را ندارید، آن را نیز دانلود و نصب کنید و بعد دستور git clone https://github.com/ysmoradi/XamApp را در Command line وارد کنید. دقت کنید پروژه را در جایی Clone نکنید که مسیر فولدر آن طولانی شود. این پروژه، یک پروژه آماده برای تست و تغییر است و ما برای بررسی نحوه اجرا آن در UWP - Android - iOS‌ از آن استفاده می‌کنیم. خود کدها در جلسات بعدتر بررسی خواهند شد. تنها چیزی که الآن اهمیت دارد اطمینان از راه اندازی شدن محیط توسعه نرم افزار شما به بهترین شکل ممکن است.
   
با ساختار پروژه و جزئیات آن در گذر زمان بیشتر آشنا می‌شویم، ولی به صورت کلی این Solution دارای 4 پروژه است:
XamApp - XamApp.Android - XamApp.iOS - XamApp.UWP
- در XamApp، تقریبا تمامی پروژه نوشته می‌شود. این مورد شامل منطق برنامه است که با CSharp نوشته می‌شود و ظاهر برنامه که با XAML نوشته می‌شود. اگر چه که می‌توان ظاهر برنامه را نیز با CSharp زد، انجام این کار به هیچ وجه توصیه نمی‌شود. در مورد Xaml نیز بعد از راه اندازی این مثال در Windows-Android-iOS صحبت خواهیم کرد.
- XamApp.Android پروژه‌ای است که اگر Set as start up project شود، به شما اجازه تست کدهای داخل XamApp را بر روی گوشی یا Emulator‌های اندرویدی می‌دهد. همچنین از طریق این پروژه می‌توانید پابلیش apk را بگیرید و به امکانات پایه Android مانند Activity - Fragment - Android XML - Intent و ... در همان زبان CSharp دسترسی داشته باشید. استفاده از این پروژه، مطلب قسمت بعدی این دوره آموزشی است.
- XamApp.iOS پروژه‌ای است که اگر Set as start up project شود، به شما اجازه تست کدهای داخل XamApp را بر روی گوشی یا Emulator‌های iOS ای می‌دهد. همچنین از طریق این پروژه می‌توانید پابلیش ipa را بگیرید و به امکانات پایه iOS مانند Delegate - Storyboard و ... در همان زبان CSharp دسترسی داشته باشید. در آموزش بعد از آموزش Android، به iOS نیز خواهیم پرداخت.
- XamApp.UWP پروژه‌ای است که اگر Set as start up project شود، به شما اجازه تست کدهای داخل XamApp را بر روی ویندوز خودتان می‌دهد. همچنین از طریق این پروژه می‌توانید پابلیش appxbundle یا msi را بگیرید و به امکانات پایه Windows در همان زبان CSharp دسترسی داشته باشید. UWP مخفف Universal windows platform است.

برای شروع پروژه‌های XamApp.Android و XamApp.iOS را Unload کنید، زیرا در این قسمت با آنها کاری نداریم. همچنین پروژه XamApp.UWP را Set as start up project کنید. 
فقط برای یکبار از منوی Tools در ویژوال استدیو، Options را باز کنید و در قسمت جستجوی آن، عبارت Intellitrace را بنویسید و اگر چیزی پیدا شد، تیک Enable Intellitrace را بردارید تا غیر فعال شود. همچنین مجدد Suppress JIT optimization را جستجو کنید و تیک آن را بزنید تا فعال شود.
دکمه F5 را بزنید و برنامه را اجرا کنید. یک دکمه می‌بینید که Text آن عبارت + است. اگر بر روی آن کلیک کنید، می‌بینید که متن Label بالای آن می‌شود Button tapped 1 time
فایل HelloWorldView.xaml را در فولدر Views در پروژه XamApp، پیدا کنید و نگاهی به کد Label و Button بیاندازید که درون StackLayout هستند و StackLayout خود داخل ContentPage است که در نتیجه صفحه اول ما کل فضایی را که دارد، به StackLayout اختصاص یافته‌است.
    <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
        <Label Text="{Binding StepsCount, StringFormat='{}Button tapped {0} times!'}" />
        <Button Command="{Binding IncreaseStepsCountCommand}" Text="+" />
    </StackLayout>
StackLayout نوعی Layout ساده‌است که بسته به تنظیم Orientation اش، می‌تواند Vertical یا Horizontal باشد. آیتم‌های داخل‌اش را که در این مثال Label و Button هستند، یا عمودی یا افقی می‌چیند که پیش فرض‌اش عمودی است. Horizontal Options و Vertical Options اش هم که هر دو Center هستند باعث می‌شود آیتم‌ها دقیقا در وسط StackLayout بنشینند. چون تمامی فضای ContentPage به StackLayout اختصاص یافته‌است، عملا Label و Button در وسط برنامه ظاهر می‌شوند.
Label ما دارای Text ای است که به StepsCount متصل یا Bind شده است ( به کمک Binding StepsCount).
StepsCount عددی است که در ابتدا صفر است و با کلیک دکمه، مقدار آن یکی یکی افزایش می‌یابد. این کد در HelloWorldViewModel.cs و به زبان CSharp نوشته شده‌است. StringFormat نیز در اینجا عملکردی معادل StringFormat در CSharp را دارد.
‌Button دارای Command ای است که به متدی در CSharp به نام IncreaseStepsCount متصل شده‌است.
حال نگاهی به کد CSharp بیندازیم:
    public class HelloWorldViewModel : BitViewModelBase
    {
        public int StepsCount { get; set; }

        public BitDelegateCommand IncreaseStepsCountCommand { get; set; }

        public HelloWorldViewModel()
        {
            IncreaseStepsCountCommand = new BitDelegateCommand(IncreaseStepsCount);
        }

        async Task IncreaseStepsCount()
        {
            StepsCount += 1;
        }
    }
ظاهر برنامه در فایل Xaml ای نوشته شده به نام HelloWorldView.xaml و منطق برنامه در کلاسی است به نام HelloWorldViewModel که این View و ViewModel انتهای نام این دو، از معماری MVVM یا Model - View - View Model می‌آید که در سال 2006~2007 و با معرفی WPF کم کم معروف شد و ما نیز از آن در این مثال داریم استفاده می‌کنیم.
StepsCount که در View به Text آن Label وصل شده بود، در CSharp یک Property از جنس int است. Command ما با نام IncreaseStepsCountCommand به متدی وصل شده‌است که کارش اضافه کردن یکی یکی StepsCount است.

در حالت عادی اگر بخواهید این برنامه را تغییر دهید که مثلا به جای یکی یکی بالا بردن StepsCount، آن را یکی یکی کم کند، ابتدا برنامه را Stop می‌کنید و سپس در Xaml برای Button مربوطه، Text را از + به - تغییر می‌دهید. همچنین کد CSharp را نیز عوض می‌کنید که می‌شود:
StepsCount -= 1
و مجددا F5 را می‌زنید. این روش قطعا خیلی Productive نیست و زمان زیادی را از شما می‌گیرد. شما می‌توانید با Break کردن اجرای برنامه به تغییر کدهای CSharp بپردازید. همچنین بدون Break کردن می‌توانید کدهای Xaml را تغییر دهید و به این روی، خیلی سریع‌تر پروژه را پیش ببرید.
با مشاهده این ویدئو می توانید درک بهتری از عملکرد Edit & continue داشته باشید. دقت کنید که در زمان تغییر ظاهر و منطق، اگر مثلا عدد، تا 17 افزایش داده شده بود برای تست، روی 17 می‌ماند و به صفر بر نمی‌گردد. در واقع کل برنامه Reload نمی‌شود و این تفاوت Edit & continue با Hot reload موجود در سایر ابزارهاست.

همچنین با کوچک و بزرگ کردن برنامه اجرا شده به سایز گوشی‌ها و تبلت‌های مختلف عملا می‌توانید برنامه را در سایزهای مختلف تست کنید. توجه داشته باشید که در Xamarin Forms مقدار دهی به طول و عرض و ... در تمامی پلتفرم‌ها و Device‌ها فارغ از Resolution یکسان است و در همه جا Width=64 عملا به یک سانتی متر اشاره دارد. علاوه بر این بدون اینکه صفحه مانیتور شما Touch باشد، می‌تواند حتی Touch را نیز تست کنید که برای این کار می‌توانید از Simulator استفاده کنید. به این صورت که به جای Local Machine گزینه Simulator را انتخاب می‌کنید.
 

 

برای پابلیش پروژه نیز می‌توانید از آموزش‌های بر روی وب استفاده کنید که شامل ارائه برنامه به استفاده کنندگان با یا بدون Microsoft Store است که از فرمت نه چندان جالب appxbundle استفاده می‌کند و ما از این آموزش عبور می‌کنیم و به ذکر این نکته بسنده می‌کنیم که نسخه بعدی Visual Studio 2017 یعنی 15.9 قابلیت ساختن msix یا Windows installer را نیز دارد که از هر چیزی بهتر است و برای پابلیش بهتر است تا ارائه نسخه Stable بعدی ویژوال استودیو که احتمالا در طی کمتر از یک ماه دیگر ارائه می‌شود، صبر کنید. دقت کنید علاوه بر کامپیوتر، لپ تاپ و تبلت‌های ویندوزی، برنامه‌ی شما بر روی XBox نیز می‌تواند کار کند.

در قسمت بعدی، همین پروژه را بر روی Android نیز اجرا می‌کنیم.

اشتراک‌ها
استفاده کردن از ریپازیتوری و الگوی UOW در دات نت کور

یک نرم افزار به منظور انجام عملیات عادی CRUD (ایجاد، خواندن،  به روزرسانی و حذف) روی داده‌ها ، نیاز به دسترسی به نوعی ذخیره داده دارد که به طور معمول، این می‌تواند نوعی پایگاه داده ، سیستم فایل یا هر نوع مکانیسم ذخیره سازی دیگری باشد که برای ذخیره داده استفاده می‌شود. 

استفاده کردن از ریپازیتوری و الگوی UOW در دات نت کور
نظرات مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت پنجم - پیاده سازی ورود و خروج از سیستم
  دو نرم افزار از آیدنتیتی سرور استفاده می‌کنند که بر روی دو ساب دامین یک دامنه هاست شده اند. اگر یکی از نرم افزار‌ها را در مرورگر باز کره و لاگین کنیم , سپس در تب دوم نرم افزار دیگر را باز کنیم , در نرم افزار دوم هم به صورت اتوماتیک لاگین هستیم( single sign in ). ولی با لاگ اوت در یکی از نرم افزارها , نرم افزار دیگر همچنان  signin  باقی میماند .  
بازخوردهای پروژه‌ها
چند پیشنهاد
با تشکر از ایده و نرم افزار جالب شما، چند ایده به نظر بنده می‌تواند کمک کننده باشد:
1. دانلود خودکار یا غیر خودکار آخرین دیتابیس توسط برنامه
2. تبدیل لینک‌های داخلی از لینک به سایت به لینک در سطح داخلی برنامه
3. دانلود عکس‌ها و فایل‌های مرتبط جهت ایجاد نسخه 100% آفلاین
4. ایجاد امکان full screen برای html viewer برای خواندن ساده‌تر متون
مطالب
نگهداری رشته ها (String) در حافظه به صورت Encrypt
در همین سایت در بخش لینک‌های ارسالی ، لینکی توسط آقای امیر هاشم زاده به اشتراک گذاشته شده بود با عنوان  "چرا هکرها نوع داده String را دوست دارند" ؛ مقاله ای بود در سایت CodeProject که در آن روش هایی که هکرها توسط آن می‌توانند اطلاعات حساس نرم افزار را که در قالب String در حافظه ذخیره شده اند را بررسی نمایند.
اصل مطلب را می‌توانید اینجا مطالعه کنید.

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

نمونه ای از استفاده این تابع را در زیر مشاهده میکنید:
public class Example
{
    public static void Main()
    {
        .
        SecureString securePwd = new SecureString();
        ConsoleKeyInfo key;

        Console.Write("Enter password: ");
        do {
           key = Console.ReadKey(true);

           // بررسی میشود که کلید فشرده شده جزو حروف الفبا می‌باشد یا کلید دیگری است
           if (((int) key.Key) >= 65 && ((int) key.Key <= 90)) {
              // کاراکتر مربوط به کلید فشرده شده به انتهای متغیر سکوراسترینک اضافه می‌شود
              securePwd.AppendChar(key.KeyChar);
              Console.Write("*");
           }   
        // خروج از حلقه در صورت فشردن کلید اینتر
        } while (key.Key != ConsoleKey.Enter);
        Console.WriteLine();

        try
        {
            MessageBox.Show(securePwd);
        }
        catch (Win32Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

در کدهای بالا رمز عبور از کاربر دریافت شده و در متغیر securepwd که شئی از کلاس SecureString می‌باشد ذخیره می‌شود.پس از آن شئی SecureString عبارت مربوطه را به صورت رمز گذاری شده در حافظه ذخیره میکند.
در این روش ابتدا مقدار کلید فشرده شده در متغیر Key که از نوع ConsoleKeyInfo تعریف شده ذخیره می‌شود. بعد از آن مقدار آن بررسی شده و اگر جزو حروف الفبای انگلیسی بود به انتهای متغیر securepwd افزوده می‌شود. این کار با متد AppendChar انجام می‌شود. این عملیات تا فشرده شدن کلید Enter ادامه پیدا میکند.
اشتراک‌ها
جایگزینی ساده و سبک برای SSMS

یک نرم افزار ساده و سبک جهت جایگزینی با SSMS و اتصال به دیتابیس‌های مختلف

این نرم افزار در دوسنخه 32 و 64 بیتی موجود است و همچنین جدیدا این شرکت به پشتیبانی از مونگو هم رو آورده است.

دوستانی که از سیستم‌های کند رنج میبرن و SSMS فشار سنگینی به سیستم آن‌ها می‌آورد، این برنامه گزینه بسیار خوبی برای جایگزینی به حسا می‌آید

جایگزینی ساده و سبک برای SSMS
نظرات نظرسنجی‌ها
آیا در کنفرانس‌های توسعه دهندگان داخلی شرکت می‌کنید؟
من خودم خیلی مشتاق شرکت در همچین کنفراس هایی هستم ولی متاسفانه بیشتر رویداد ها  در حوزه استارتاپ ها  و معرفی آنها می‌باشند .
به نظرم کنفراس‌های در حوزه نرم افزار خیلی در روند رشد و آگاهی برنامه نویسان تاثیر داره و اگر اساتید حوزه نرم افزار داخلی در این راستا اقدام کنند کمک بزرگی خواهد بود .
برای  نمونه TehranDb  کار خوب و کاربردی برای افراد فعال در زمینه دیتابیس هستش .