Chuyển đến nội dung chính

Sử dụng Fluent Validation để validate cho bài toán đệ quy

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 TreeItem
public 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

Tham khảo

Recursive Functions in C#

Recursion 

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.