مدیریت خطای تابعی (Functional) در NET. با الگوی Result ✅
چگونه باید خطاها را در کد خود مدیریت کنید؟
این موضوع بحثهای زیادی بوده است و من میخواهم نظر خود را به اشتراک بگذارم.
یک مکتب فکری استفاده از استثناها (exceptions) را برای کنترل جریان (flow control) پیشنهاد میکند. 🤯 این رویکرد خوبی نیست زیرا استدلال در مورد کد را دشوارتر میکند. فراخواننده (caller) باید جزئیات پیادهسازی و اینکه کدام استثناها را باید مدیریت کند، بداند.
استثناها برای شرایط استثنایی هستند.
امروز، میخواهم به شما نشان دهم چگونه مدیریت خطا را با استفاده از الگوی Result پیادهسازی کنید. ✨
این یک رویکرد تابعی برای مدیریت خطا است که کد شما را گویاتر میکند.
استثناها برای کنترل جریان ⚡️
استفاده از استثناها برای کنترل جریان، رویکردی برای پیادهسازی اصل fail-fast است.
به محض اینکه با خطایی در کد مواجه میشوید، یک استثنا پرتاب میکنید — که به طور موثر متد را خاتمه میدهد و فراخواننده را مسئول مدیریت استثنا میکند.
مشکل این است که فراخواننده باید بداند کدام استثناها را مدیریت کند. و این تنها از امضای متد مشخص نیست.
یک مورد استفاده رایج دیگر، پرتاب استثناها برای خطاهای اعتبارسنجی است.
در اینجا یک مثال در FollowerService آمده است: 👨💻
public sealed class FollowerService
{
private readonly IFollowerRepository _followerRepository;
public FollowerService(IFollowerRepository followerRepository)
{
_followerRepository = followerRepository;
}
public async Task StartFollowingAsync(
User user,
User followed,
DateTime createdOnUtc,
CancellationToken cancellationToken = default)
{
if (user.Id == followed.Id)
{
throw new DomainException("Can't follow yourself");
}
if (!followed.HasPublicProfile)
{
throw new DomainException("Can't follow non-public profile");
}
if (await _followerRepository.IsAlreadyFollowingAsync(
user.Id,
followed.Id,
cancellationToken))
{
throw new DomainException("Already following");
}
var follower = Follower.Create(user.Id, followed.Id, createdOnUtc);
_followerRepository.Insert(follower);
}
}