🧩 Cross-Cutting Concern شماره ۲ — اعتبارسنجی (Validation)
اعتبارسنجی یکی از دغدغههای اساسی (Critical Cross-Cutting Concerns) در مهندسی نرمافزار است.
این بخش درواقع اولین خط دفاعی سیستم در برابر ورود دادههای نادرست به برنامه محسوب میشود.
اعتبارسنجی از بروز وضعیتهای ناسازگار داده (Inconsistent Data States) و آسیبپذیریهای امنیتی احتمالی (Security Vulnerabilities) جلوگیری میکند.
⚙️ اعتبارسنجی در Clean Architecture
در مثال زیر، یک Validation Pipeline Behavior ایجاد میکنیم.
این ساختار به ما اجازه میدهد تا منطق اعتبارسنجی را از منطق تجاری جدا نگه داریم —
بهعبارتی دیگر، اعتبارسنجی قبل از رسیدن درخواست به بخش اصلی پردازش انجام میشود.
این الگو موجب پاکسازی لایهٔ منطق تجاری (Business Logic) از قوانین تکراری و اطمینان از یکپارچگی دادهها میشود.
🧠 انواع اعتبارسنجی
در هنگام طراحی اعتبارسنجی، باید بین دو نوع مهم تمایز قائل شوید:
اعتبارسنجی ورودی (Input Validation)
اعتبارسنجی قوانین تجاری (Business Rule Validation)
🔹 Input Validation
برای بررسی درستی و قالب دادهها به کار میرود — مثلاً طول رشته، محدودهٔ اعداد یا فرمت تاریخ.
هدف از آن اطمینان از این است که داده قبل از ورود به منطق سیستم، معیارهای پایه را رعایت کرده باشد.
🔹 Business Rule Validation
بررسی میکند که دادهها با قوانین و منطق خاص دامنهٔ شما (Domain Logic) سازگار هستند یا نه.
🧩 نقش اعتبارسنجی در پایداری سیستم
اجرای مؤثر اعتبارسنجی به مقاومت (Resilience) و قابلیت اطمینان (Reliability) بالاتر برنامه منجر میشود.
با اعمال قوانین اعتبارسنجی میتوانید:
کیفیت دادهها را در سطح بالا حفظ کنید 🧾
و تجربهٔ کاربری بهتری ارائه دهید 💡
💻 نمونهکد Pipeline Behavior
internal sealed class ValidationPipelineBehavior<TRequest, TResponse>(
IEnumerable<IValidator<TRequest>> validators)
: IPipelineBehavior<TRequest, TResponse>
where TRequest : class
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
ValidationFailure[] validationFailures = await ValidateAsync(request);
if (validationFailures.Length != 0)
{
throw new ValidationException(validationFailures);
}
return await next();
}
private async Task<ValidationFailure[]> ValidateAsync(TRequest request)
{
if (!validators.Any())
{
return [];
}
var context = new ValidationContext<TRequest>(request);
ValidationResult[] validationResults = await Task.WhenAll(
validators.Select(validator => validator.ValidateAsync(context)));
ValidationFailure[] validationFailures = validationResults
.Where(validationResult => !validationResult.IsValid)
.SelectMany(validationResult => validationResult.Errors)
.ToArray();
return validationFailures;
}
}