Trong bài viết này, mình sẽ đưa ra 2 bài toán tương tự nhau, sử dụng Fluent Validation để validate cho bài toán đệ quy
Tính giai thừa
Ý tưởng cho việc sử dụng Fluent Validation để validate bài toán đệ quy là chia bài toán thành các bước con nhỏ, và áp dụng Fluent Validation để validate từng bước nhỏ này. Điều này giúp tách bài toán lớn thành những bài toán nhỏ hơn và dễ quản lý hơn.
Giả sử chúng ta có hàm tính giai thừa
Console.WriteLine("Please Enter a Number");
//read number from user
var number =Convert.ToInt32(Console.ReadLine());
//invoke the static method
var factorial = Factorial(number);
//print the factorial result
Console.WriteLine("factorial of"+number+"="+factorial.ToString());
public static int Factorial(int number)
{
if (number == 0)
return 1;
var factorial = 1;
for (int i = number; i >= 1;i-- )
{
factorial = factorial * i;
}
return factorial;
}
Luôn có 1 điểm bắt và có 1 hoặc nhiều điểm dừng trong bài toán đệ quy
if (number == 0)
return 1;
Trở lại bài toán trên, nếu áp dụng Fluent Vadiation, thì chúng ta sẽ có điểm dừng ở number == 0. Tuy nhiên chúng ta cần định nghĩa Model để có thể sử dụng với Fluent Validation
public class FactorialModel
{
public int Number { get; set; }
public int Result { get; set; }
}
public class FactorialModelValidator : AbstractValidator<FactorialModel>
{
public FactorialModelValidator()
{
RuleFor(x => x.Number).GreaterThan(0).WithMessage("Number must be greater than 0.");
}
}
Lưu ý: bạn cần đặt package FluentValidation
public int Factorial(FactorialModel model)
{
var validationResult = new FactorialModelValidator().Validate(model);
if (!validationResult.IsValid)
{
// Handle validation errors, throw an exception, or return an error message.
}
if (model.Number == 0)
{
model.Result = 1;
return 1;
}
model.Result = model.Number * Factorial(new FactorialModel { Number = model.Number - 1 });
return model.Result;
}
Gọi hàm kiểm tra
var factorialModel = new FactorialModel { Number = 8 };
var result = Factorial(factorialModel);
Console.WriteLine($"Factorial of {factorialModel.Number} is {factorialModel.Result}");
Cây nhiều nhánh
Ở Backend, hệ thống sẽ nhận được data là 1 cây nhiều nhánh, không giới hạn số lượng phần tử trong 1 nhánh, chỉ giới hạn Tree có tối đa 4 cấp
Ý tưởng: tạo một class validator riêng cho lớp TreeItem, làm điểm dừng, tương tự như bài toán ở trên
Model TreeItempublic class TreeItem
{
public string Title { get; set; }
public string Description { get; set; }
public List<TreeItem> TreeItems { get; set; }
}
Data test
Test_LessThan4Level();
Test_MoreThan4Level();
static void Test_LessThan4Level()
{
var treeItem = new TreeItem
{
Title = "Root",
Description = "Root description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 1",
Description = "Level 1 description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 2",
Description = "Level 2 description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 3",
Description = "Level 3 description",
TreeItems = new List<TreeItem>
{
// Add Level 4 items here
}
}
}
}
}
}
}
};
var validator = new TreeItemValidator();
var validationResult = validator.Validate(treeItem);
if (validationResult.IsValid)
{
Console.WriteLine("Validation passed.");
}
else
{
foreach (var error in validationResult.Errors)
{
Console.WriteLine(error.ErrorMessage);
}
}
}
static void Test_MoreThan4Level()
{
var treeItem = new TreeItem
{
Title = "Root",
Description = "Root description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 1",
Description = "Level 1 description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 2",
Description = "Level 2 description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 3",
Description = "Level 3 description",
TreeItems = new List<TreeItem>
{
new TreeItem
{
Title = "Level 4",
Description = "Level 4 description",
TreeItems = new List<TreeItem>
{
}
}
}
}
}
}
}
}
}
};
var validator = new TreeItemValidator();
var validationResult = validator.Validate(treeItem);
if (validationResult.IsValid)
{
Console.WriteLine("Validation passed.");
}
else
{
foreach (var error in validationResult.Errors)
{
Console.WriteLine(error.ErrorMessage);
}
}
}
Chúng ta sẽ viết class TreeItemValidator để kiểm tra TreeItem, sử dụng hàm Validate
RuleFor(item => item.TreeItems).Must(ValidateTreeItems).WithMessage("Maximum tree level exceeded.");
Function ValidateTreeItems được dùng làm điểm bắt đầu gọi hàm kiểm tra ở mỗi Level.
private bool ValidateTreeItems(List<TreeItem> treeItems)
{
// Recursive function to check the maximum tree level
return ValidateTreeItemsRecursive(treeItems, 0);
}
Tạo 1 điểm dừng trong function ValidateTreeItemRecursive
// Maximum level is 4
if (currentLevel >= 4)
return false;
Kết hợp lại, chúng ta có
public class TreeItemValidator : AbstractValidator<TreeItem>
{
public TreeItemValidator()
{
RuleFor(item => item.Title).NotEmpty().WithMessage("Title is required.");
RuleFor(item => item.Description).NotEmpty().WithMessage("Description is required.");
RuleFor(item => item.TreeItems).Must(<).WithMessage("Maximum tree level exceeded.");
}
private bool ValidateTreeItemsRecursive(List<TreeItem> treeItems)
{
// Recursive function to check the maximum tree level
return <Recursive(treeItems, 0);
}
private bool ValidateTreeItemsRecursive(List<TreeItem> treeItems, int currentLevel)
{
// Maximum level is 4
if (currentLevel >= 4)
return false;
// If the list is empty or null, it's a valid tree
if (treeItems == null || treeItems.Count == 0)
return true;
// Recursively check the tree items at the next level
foreach (var item in treeItems)
{
if (!ValidateTreeItemsRecursive(item.TreeItems, currentLevel + 1))
return false;
}
return true;
}
}
Hi vọng qua bài viết này, các bạn sẽ nắm được cách validate khi sử dụng đệ quy
Nhận xét
Đăng nhận xét