اشتراک‌ها
نقدی بر AngularJs

Soon the next major version of the framework will come out, which breaks backward compatibility. Apparently, even developers of the framework realized that there is something wrong and decided to rewrite the framework almost from scratch. They don’t add new functionality, breaking backward compatibility, they rewrite almost everything. 

نقدی بر AngularJs
مطالب
Minimal API's در دات نت 6 - قسمت اول - معرفی
یکی از مهم‌ترین تغییرات دات نت 6، ارائه‌ی Minimal API's به همراه آن است که نسبت به MVC و سایر مشتقات ASP.NET Core، کمتر به همراه پیش‌فرض‌های نظری خاص و بسیار مقید و متعصبانه (opinionated) است؛ که این مورد خود مزیتی است جهت انجام امور متداول، به نحوی دیگر و دلخواه و با آزادی عمل بیشتری در طراحی endpoints مورد نیاز و کل برنامه. خصوصا این سبک جدید، با معماری برش‌های عمودی (vertical slices) ارائه شده‌ی توسط نویسنده‌ی AutoMapper، هماهنگی خاصی دارد و اینطور به نظر می‌رسد که جهت ساده سازی طراحی برنامه‌های ASP.NET Core با معماری CQRS ارائه شده‌است. با وجود Minimal API's می‌توان از دو لایه‌ی متداول برنامه‌ها رها شد: لایه‌ی سرویس‌ها و لایه‌ی مخازن یا Repositories. در معماری برش‌های عمودی، برنامه به ویژگی‌های خاصی (Features) تقسیم شده و هر ویژگی، متکی به خود طراحی می‌شود. زمانیکه از هندلرها برای هر Command و Query معماری CQRS استفاده می‌کنیم، این‌ها مختص به یک ویژگی متکی به خود طراحی می‌شوند و به همراه تمام اطلاعات و اعمال مرتبط هستند و دیگر در این حالت، وجود لایه‌های سرویس و مخزن، بی‌معنا و غیرضروری می‌شوند.

در ادامه قصد داریم تمام این موارد را مانند Minimal API's و معماری برش‌های عمودی به همراه CQRS، در طی یک سری و یک پروژه‌ی عملی ساخت یک Blog به نام MinimalBlog، بررسی کنیم. البته هدف ما در اینجا صرفا ساخت backend ساختار یافته‌ی این برنامه‌است؛ منهای UI آن. هدف اصلی ما از این سری، ارائه‌ی یک معماری، جهت کار با Minimal API's است.


دریافت کدهای کامل این سری

جهت مرور سریعتر و ساده‌تر این سری، کدهای کامل آن‌را از اینجا می‌توانید دریافت کنید: MinimalBlog.zip


پروژه‌هایی که برنامه‌ی MinimalBlog را تشکیل می‌دهند

برنامه‌ی MinimalBlog، تنها از سه پروژه‌ی زیر تشکیل می‌شود:
MinimalBlog.Api: این پروژه از نوع minimal API's است که توسط دستور جدید «dotnet new webapi --use-minimal-apis» آغاز خواهد شد و به صورت پیش‌فرض به همراه پشتیبانی از OpenAPI نیز هست. البته اگر از VS2022 استفاده می‌کنید، در حین آغاز یک پروژه‌ی Web API جدید، تیک مربوط به use controllers را در UI بردارید تا از Minimal API's استفاده شود.
MinimalBlog.Dal: که Dal در اینجا مخفف data access layer است و یک class library می‌باشد و با دستور dotnet new classlib آغاز می‌شود.
MinimalBlog.Domain: نیز یک class library است و با دستور dotnet new classlib آغاز می‌شود.

همانطور که مشاهده می‌کنید، این طراحی جدید، بدون وجود لایه‌ی متداول سرویس‌ها و یا مخازن است.


بررسی ساختار ابتدایی پروژه‌ی MinimalBlog.Api

در اینجا تنها تک فایل Program.cs، به همراه تنظیمات برنامه قابل مشاهده‌است و فایل Starup.cs از آن حذف شده‌است (اطلاعات بیشتر). این فایل نیز بر مبنای مفهوم top level programs طراحی شده‌است و به همراه تعریف class و یا فضای نامی نیست:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
همانطور که ملاحظه می‌کنید، تمام اتفاقات در همین تک فایل رخ می‌دهند. برای مثال سرویس‌های مورد نیاز برنامه به مجموعه‌ی builder.Services اضافه می‌شوند؛ شبیه به کاری که پیشتر در فایل Startup.cs و متد ConfigureServices آن انجام می‌دادیم.

پس از آن به تعاریف زیر می‌رسیم؛ تعاریف میان افزارهایی که پیشتر در متد Configure کلاس Startup انجام می‌شدند، الان همگی در تک فایل Program.cs قرار دارند:
var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
البته هنوز هم می‌توان در صورت نیاز به همان ساختار کلاس Startup پیشین نیز رسید.


در انتهای این فایل نیز تعاریف پیش‌فرض زیر قرار دارند:
var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateTime.Now.AddDays(index),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
در اینجا متد متد MapGet یک endpoint را تعریف کرده و سپس اکشنی را به آن انتساب می‌دهد. یعنی اگر آدرس weatherforecast/ درخواست شود، lambda expression تعریف شده، اجرا می‌شود. هدف از ارائه‌ی Minimal API نیز همین است تا بتوان با حداقل کدنویسی، سریعا به نتیجه‌ی مدنظر خود رسید.
در همین حال اگر برنامه‌ی Api را اجرا کنیم، به تصویر زیر خواهیم رسید:


در ادامه کدهای موجود در این فایل را Refactor کرده و به کلاس‌های دیگری منتقل می‌کنیم؛ چون اگر قرار باشد در طول زمان تمام endpoints مدنظر را در همینجا تعریف کنیم، کنترل برنامه از دست خارج خواهد شد.


غنی سازی Solution و کامپایلر #C با استفاده از فایل‌های editorconfig. و Directory.Build.props

در مورد این دو فایل در مطلب «غنی سازی کامپایلر C# 9.0 با افزونه‌ها » بیشتر بحث شده‌است. هدف از آن‌ها، اعمال یکسری تنظیمات سراسری، به تمام پروژه‌های یک solution به صورت یک‌دست است؛ مانند تنظیمات کامپایلر جهت نمایش اخطارها به صورت خطاها، تعریف usingهای سراسری سی‌شارپ 10 و یا اعمال Roslyn analyzers به تمام پروژه‌ها. این دو فایل را به همراه پروژه‌ی پیوست می‌توانید دریافت کنید و ... باید جزء استاندارد تمام پروژه‌های جدید باشند. چون وجود آن‌ها سبب خواهد شد که به شدت کیفیت کدهای نهایی افزایش یابند و مبتنی بر یکسری best practices شوند.
مطالب
از کار افتادن SQL Server Agent
SQL Server Agent مربوط به SQL Server 2008 از کار افتاده بود و راه اندازی نمی‌شد. خطای مرتبط با آن در لاگ‌های ویندوز به نحو زیر بود:
 SQLServerAgent could not be started (reason: Unable to connect to server '(local)'; SQLServerAgent cannot start).
پس از مدتی جستجو، عنوان شده بود که مسیر رجیستری زیر را یافته:
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLSERVER\SQLServerAgent
و در آن ServerHost را به نام سرور ویرایش کنید. سپس سرور را ری استارت نمائید. این تغییر انجام شد اما باز هم SQL Server Agent راه اندازی نمی‌شد.
لاگ‌های آن در مسیر ذیل ثبت می‌شوند:
 C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Log\SQLAGENT.OUT
در اینجا خطاهای زیر ثبت شده بودند:
 2013-01-28 20:02:34 - ! [298] SQLServer Error: 780, SQL Server Network Interfaces: The logon attempt failed [SQLSTATE HY000]
2013-01-28 20:02:34 - ! [298] SQLServer Error: 780, Cannot generate SSPI context [SQLSTATE HY000]
2013-01-28 20:02:34 - ! [000] Unable to connect to server ; SQLServerAgent cannot start
2013-01-28 20:02:34 - ! [298] SQLServer Error: 780, SQL Server Network Interfaces: The logon attempt failed [SQLSTATE HY000]
2013-01-28 20:02:34 - ! [298] SQLServer Error: 780, Cannot generate SSPI context [SQLSTATE HY000]
2013-01-28 20:02:34 - ! [382] Logon to server failed (DisableAgentXPs)
2013-01-28 20:02:34 - ? [098] SQLServerAgent terminated (normally)
همانطور که مشخص است مشکل اصلی در عدم توانایی لاگین اکانت SQL Server Agent ذکر شده است.
برای تغییر آن مسیر زیر را طی کنید:
 SQL Configuration manager -> SQL Server Agent -> Logon User -> NT/Local Service
به عبارتی در قسمت SQL Configuration manager، تنظیمات SQL Server Agent را یافته و نوع اکانت آن‌را به Local Service تغییر دهید.
پس از آن سرویس بدون مشکل استارت شد.
مطالب
محاسبه NOPS برای سرور شیرپوینت
NOPS یا Normalized User Operations Per Second ، عملیات کاربر نرمال در هر ثانیه است که در سرور‌ها برای محاسبه بار وارده بر سرور محاسبه می‌شود . و تعداد آن ، در حقیقت عددی است که تعداد کل عملکرد‌های کاربران معمولی و نرمال را در یک روز معمولی نشان می‌دهد . برای سرور‌های شیرپوینت نیز محاسبه آن پیشنهاد شده است .
توسط این عدد ، شما می‌توانید تعداد کاربرهای قابل پشتیبانی خود را تخمین زده و سخت افزار مورد نیاز را تهیه کنید
 فرمول کلی و ثابت شده زیر ، برای این منظور استفاده می‌شود : 

موارد فوق تقریبا واضح هستند که فقط 2 مورد از آنها را توضیح می‌دهم :
مورد D یعنی peak Factor ، مقداری بین 1 تا 10 است که برای نشان دادن ساعات پیک در طول ساعت کاری استفاده می‌شود . برای مثال اگر سازمانی از از 9 صبح تا 5 بعد از ظهر کار کند ، می‌توان به جرات گفت که اکثر کامندان روز کاری خود را با باز کردن محیط برنامه شیرپوینت آغاز می‌کنند که یک پیک محسوب می‌شود . سپس دقیقا بعد از نهار ، استفاده در حد پیک می‌شود . مقدار Peak Factor برابر 1 به این معنی است که هیچ بارگذاری پیکی وجود ندارد . و peak factor برابر 10 بیانگر این است که تمام آن، پیک محسوب می‌شود . به طور معمول برای یک سازمان این عدد تا سقف 5 بیان می‌شود . اگر می‌خواهید محافظ کارانه برخورد کنید ، تا سقف 7 محاسبه کنید .
 
مورد بعدی C است که تعداد عملکرد به ازای کاربر فعال در روز است . این مقدار نیز که عددی بین 1 تا 10 است ،  با میزان بهره برداری از محیط شیرپوینت در ارتباط است . مقدار 1 به این معنی است که کاربران شما تقریبا هیچ زمانی را به استفاده از شیرپوینت اختصاص نمی‌دهند و مقدار 10 به معنی این است که کاربران تمام روز خود را مشغول کارکردن با شیرپوینت هستند . برای یک سازمان می‌تواند این مقدار عددی نزدیک به 10 باشد . 
برای اطلاعات بیشتر در این زمینه می‌توانید به Appendix A از کتاب Sharepoint Administration و یا مقاله Calculating Bandwidth Requirements to Support Regional Users  مراجعه نمایید