اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
چهار دقیقه
یکی از مهمترین تغییرات دات نت 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 و یا فضای نامی نیست:
همانطور که ملاحظه میکنید، تمام اتفاقات در همین تک فایل رخ میدهند. برای مثال سرویسهای مورد نیاز برنامه به مجموعهی builder.Services اضافه میشوند؛ شبیه به کاری که پیشتر در فایل Startup.cs و متد ConfigureServices آن انجام میدادیم.
پس از آن به تعاریف زیر میرسیم؛ تعاریف میان افزارهایی که پیشتر در متد Configure کلاس Startup انجام میشدند، الان همگی در تک فایل Program.cs قرار دارند:
البته هنوز هم میتوان در صورت نیاز به همان ساختار کلاس Startup پیشین نیز رسید.
در انتهای این فایل نیز تعاریف پیشفرض زیر قرار دارند:
در اینجا متد متد 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 شوند.
در ادامه قصد داریم تمام این موارد را مانند 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();
پس از آن به تعاریف زیر میرسیم؛ تعاریف میان افزارهایی که پیشتر در متد Configure کلاس Startup انجام میشدند، الان همگی در تک فایل Program.cs قرار دارند:
var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection();
در انتهای این فایل نیز تعاریف پیشفرض زیر قرار دارند:
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); }
در همین حال اگر برنامهی Api را اجرا کنیم، به تصویر زیر خواهیم رسید:
در ادامه کدهای موجود در این فایل را Refactor کرده و به کلاسهای دیگری منتقل میکنیم؛ چون اگر قرار باشد در طول زمان تمام endpoints مدنظر را در همینجا تعریف کنیم، کنترل برنامه از دست خارج خواهد شد.
غنی سازی Solution و کامپایلر #C با استفاده از فایلهای editorconfig. و Directory.Build.props
در مورد این دو فایل در مطلب «غنی سازی کامپایلر C# 9.0 با افزونهها » بیشتر بحث شدهاست. هدف از آنها، اعمال یکسری تنظیمات سراسری، به تمام پروژههای یک solution به صورت یکدست است؛ مانند تنظیمات کامپایلر جهت نمایش اخطارها به صورت خطاها، تعریف usingهای سراسری سیشارپ 10 و یا اعمال Roslyn analyzers به تمام پروژهها. این دو فایل را به همراه پروژهی پیوست میتوانید دریافت کنید و ... باید جزء استاندارد تمام پروژههای جدید باشند. چون وجود آنها سبب خواهد شد که به شدت کیفیت کدهای نهایی افزایش یابند و مبتنی بر یکسری best practices شوند.