چگونه استثناها (Exceptions) را با الگوی Result در NET. جایگزین کنیم ✨
در توسعه نرمافزار مدرن، مدیریت باظرافت خطاها و سناریوهای استثنایی برای ساخت اپلیکیشنهای قوی، حیاتی است. 🛡
در حالی که استثناها یک مکانیزم رایج در .NET برای مدیریت خطا هستند، آنها میتوانند سربار عملکردی (performance overhead) ایجاد کرده و جریان کد را پیچیده کنند.
امروز ما بررسی خواهیم کرد که چگونه استثناها را با الگوی Result در NET. جایگزین کنیم، و خوانایی، قابلیت نگهداری و عملکرد کد را افزایش دهیم.
🖊مقدمهای بر مدیریت استثنا در NET.
مدیریت استثنا یک مفهوم بنیادی در برنامهنویسی NET. است که به توسعهدهندگان اجازه میدهد خطاهای زمان اجرا را باظرافت مدیریت کنند. رویکرد معمول شامل استفاده از بلوکهای try, catch و finally برای گرفتن و مدیریت استثناها است.
بیایید اپلیکیشنی را بررسی کنیم که یک Shipment ایجاد میکند و از استثناها برای کنترل جریان استفاده میکند: 👇
public async Task<ShipmentResponse> CreateAsync(
CreateShipmentCommand request,
CancellationToken cancellationToken)
{
var shipmentAlreadyExists = await context.Shipments
.Where(s => s.OrderId == request.OrderId)
.AnyAsync(cancellationToken);
if (shipmentAlreadyExists)
{
throw new ShipmentAlreadyExistsException(request.OrderId);
}
var shipment = request.MapToShipment(shipmentNumber);
context.Shipments.Add(shipment);
await context.SaveChangesAsync(cancellationToken);
return shipment.MapToResponse();
}
در اینجا اگر یک shipment از قبل در دیتابیس وجود داشته باشد، ShipmentAlreadyExistsException پرتاب میشود. در endpoint Minimal API، این استثنا به صورت زیر مدیریت میشود:
public void MapEndpoint(WebApplication app)
{
app.MapPost("/api/v1/shipments", Handle);
}
private static async Task<IResult> Handle(
[FromBody] CreateShipmentRequest request,
IShipmentService service,
CancellationToken cancellationToken)
{
try
{
var command = request.MapToCommand();
var response = await service.CreateAsync(command, cancellationToken);
return Results.Ok(response);
}
catch (ShipmentAlreadyExistsException ex)
{
return Results.Conflict(new { message = ex.Message });
}
}
در حالی که این رویکرد کار میکند، معایب زیر را دارد: 👎
🔹 کد غیرقابل پیشبینی است، با نگاه کردن به IShipmentService.CreateAsync نمیتوانید با اطمینان بگویید که آیا متد استثنا پرتاب میکند یا نه.
🔹 شما باید از دستورات catch استفاده کنید و دیگر نمیتوانید کد را خط به خط از بالا به پایین بخوانید، باید دید خود را به عقب و جلو ببرید.
🔹 استثناها میتوانند در برخی اپلیکیشنها به مشکلات عملکردی منجر شوند زیرا بسیار کند هستند.
به یاد داشته باشید، استثناها برای شرایط استثنایی هستند. آنها بهترین گزینه برای کنترل جریان نیستند. در عوض، من میخواهم رویکرد بهتری را با الگوی Result به شما نشان دهم. 💡