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

Bài đăng

Hiển thị các bài đăng có nhãn Design Patterns

Mediator trong .NET: Từ MediatR đến martinothamar/Mediator

Mediator Pattern là gì? Mediator là một mẫu thiết kế hành vi (behavioral design pattern) giúp giảm sự phụ thuộc trực tiếp và phức tạp giữa các thành phần trong một hệ thống. Hãy hình dung một hệ thống phức tạp mà không có Mediator như một mạng lưới các đối tượng giao tiếp trực tiếp với nhau. Khi số lượng đối tượng tăng lên, số lượng kết nối và sự phụ thuộc sẽ tăng theo cấp số nhân, tạo ra một kiến trúc rối rắm, khó quản lý, thường được gọi là "spaghetti code". Mediator pattern giải quyết vấn đề này bằng cách giới thiệu một đối tượng trung gian (Mediator). Thay vì giao tiếp trực tiếp, tất cả các thành phần sẽ gửi yêu cầu hoặc thông báo đến Mediator. Mediator sau đó sẽ điều phối và chuyển tiếp các yêu cầu này đến (các) thành phần xử lý (handler) tương ứng. Điều này giúp các thành phần trở nên độc lập (decoupled) với nhau. Mối Liên Hệ Giữa Mediator, CQS và CQRS Để hiểu sâu hơn về sức mạnh và ứng dụng của Mediator pattern, chúng ta cần tìm hiểu về một nguyên tắc nền tảng trong th...

REPR (Request-Endpoint-Response) Pattern trong .NET

REPR là gì? REPR (đọc là "Reaper") là một mẫu thiết kế API mới, tập trung vào việc tổ chức các endpoint thay vì sử dụng controller truyền thống. Được giới thiệu bởi Steve "ardalis" Smith, REPR giúp cải thiện cách thức tổ chức các endpoint trong API, giúp chúng dễ dàng hơn trong việc tìm kiếm, điều hướng và chỉnh sửa. Với mẫu thiết kế này, mỗi endpoint sẽ được định nghĩa trong một lớp riêng biệt, mỗi lớp sẽ có một phương thức duy nhất để xử lý các yêu cầu đến. Mục tiêu của REPR là tổ chức ứng dụng theo một kiến trúc tập trung vào endpoint, tạo ra ba thành phần chính: Request Endpoint Response Như vậy, khi nhận một yêu cầu từ người dùng, chúng ta sẽ xử lý yêu cầu đó tại endpoint, sau đó trả về một đối tượng response. Phương pháp này giúp quá trình nhận, xử lý và trả về kết quả trở nên đơn giản và rõ ràng hơn. Tại sao cần phải có REPR? Khi phát triển API theo kiến trúc MVC, chúng ta bắt đầu với những controller nhỏ gọn và đơn giản. Tuy nhiên, khi ứng dụng phát triển, c...

Hướng dẫn sử dụng DependencyResolver trong Custom Validation Attribute

Custom Data Annotation (Attribute) là gì? Data Annotation trong ASP.NET MVC là một cách để bạn thêm các thuộc tính (metadata) vào các thuộc tính của model, cung cấp thông tin bổ sung về cách dữ liệu đó sẽ được xử lý. Custom Validation Attribute là một cách để bạn tự định nghĩa các quy tắc validate dữ liệu riêng cho các thuộc tính của model trong ASP.NET MVC. Nó kế thừa từ lớp ValidationAttribute và cho phép bạn tạo các logic validate phức tạp hơn so với các Data Annotation có sẵn. Ví dụ: [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class NotEqualToAttribute : ValidationAttribute { private const string DefaultErrorMessage = "{0} cannot be the same as {1}."; public string OtherProperty { get; private set; } public NotEqualToAttribute(string otherProperty) : base(DefaultErrorMessage) { if (string.IsNullOrEmpty(otherProperty)) { throw new ArgumentNullException("otherPro...

MediatR: Publish Notification

Trong MediatR, Publish Method chính là công cụ mà chúng ta sử dụng để gửi notification đến các handler đã đăng ký. Các handler này sẽ được thực thi theo thứ tự được đăng ký. Mô hình Publish Method trong MediatR được xây dựng theo design pattern Observer . Design pattern Observer (hay còn gọi là Subscriber) định nghĩa một mối quan hệ một-nhiều trong đó một đối tượng publisher duy trì một danh sách các đối tượng subscriber và gửi notification cho tất cả các subscriber khi có thay đổi xảy ra.  Ưu điểm của design pattern này là giảm sự phụ thuộc trực tiếp của các class. Việc thêm hoặc gỡ bỏ các subscriber (handler) đơn giản chỉ cần thực hiện thao tác đăng ký hoặc hủy đăng ký với mediator. Setup Notification MediatR cung cấp interface INotification làm lớp trung gian để thực hiện việc đăng ký subcriber // // Summary: // Marker interface to represent a notification public interface INotification { } Tạo 1 class cụ thể cho Notification public class AddAuthorEvent: INotification { ...

MediatR: CQRS Command Validation

Validation là 1 phần quan trọng của API. Khi sử dụng Clean Architect hoặc bất kỳ design pattern hiện đại nào, chúng ta thường tách phần Validation và Business Logic ra thành những thành phần riêng biệt. Lưu ý trong bài viết này, chúng ta chỉ nói về Input Validation. Chúng ta sẽ không tách Business Validation Giả sử với đoạn code sau, nếu không validate PageIndex thì thỉnh thoảng đoạn code sẽ gây ra exception nếu PageIndex < 0 public class GetAuthorQueryHandler : IRequestHandler<GetAuthorQuery, List<AuthorModel>> { private readonly IAuthorRepository _authorRepository; public GetAuthorQueryHandler(IAuthorRepository authorRepository) { _authorRepository = authorRepository; } public async Task<List<AuthorModel>> Handle(GetAuthorQuery request, CancellationToken cancellationToken) { if(request.PageIndex < 0) throw new Exception("PageIndex is invalid") return _authorRepository.GetAuthors(request.PageSize, request.PageIndex); } } Để phâ...

CQRS là gì?

Giới thiệu CQRS được lấy cảm hứng từ mô hình Command Query Separation (CQS) do Bertrand Meyer đề xuất trong cuốn sách "Object Oriented Software Construction". Triết lý chính của CQS là A method should either change state of an object, or return a result, but not both. In other words, asking the question should not change the answer. More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.” (Wikipedia) Dựa trên nguyên tắc này, CQS phân chia các phương thức thành hai nhóm: Command: Thay đổi trạng thái của đối tượng hoặc toàn bộ hệ thống (còn gọi là modifiers hoặc mutators). Query: Trả về kết quả và không thay đổi trạng thái của đối tượng. Trong thực tế, việc phân biệt ra Query và Command khá đơn giản. Bạn có thể tìm hiểu thêm bài viết tại đây CQRS: Bản nâng cấp của CQS CQRS (hay Command Query Responsibility Segregation) là một design pattern phân tách các hoạt động read và write dữ liệu. Trong đó chia việc tương ...

Command Query Separation

Lần đầu tiên mình bắt đầu khám phá design pattern CQRS (Command Query Responsibility Segregation), mình phải thừa nhận rằng nó đôi chút khó khăn. Nhưng đến khi mình đối mặt với những thách thức thực tế trong dự án cá nhân, mình mới thấu hiểu giá trị quan trọng của CQRS. Điều làm mình ấn tượng là CQRS không phải là một khái niệm quá rối bời. Ngược lại, khi bạn tiếp tục làm việc và trau dồi kinh nghiệm, bạn sẽ dần dần thích ứng và làm quen với nó. Như Lỗ Tấn đã nói, "Trên đời này làm gì có đường, người ta đi mãi thì thành đường thôi.". Vì vậy, giai đoạn bắt đầu tìm hiểu luôn là quan trọng nhất. Nếu bắt đầu mọi thứ quá phức tạp từ đầu, có thể các bạn sẽ cảm thấy mất hứng thú và không muốn tiếp tục đọc các phần sau. Bài viết này gồm nhiều phần, đầu tiên là mình nói về Command Query Separation, sau đó mới là phần Command Query Responsibility Segregation. Mục đích chính là chúng ta đi từ cách tiếp cận đơn giản đến phức tạp. Command Query Separation CQS là một nguyên tắc thiết kế mẫ...

Interceptor trong ASP.NET MVC

Interceptor là một trong những khái niệm quan trọng trong lập trình, cho phép chúng ta mở rộng và thay đổi hành vi của các phương thức mà không phải sửa đổi code nguồn gốc. Trong bài viết này, chúng ta sẽ khám phá cách sử dụng Interceptor trong Autofac, một container dependency injection phổ biến trong cộng đồng .NET. Mình minh họa bằng .NET Framework, các bạn dựa theo đó làm cho ví dụ .NET nha Giới thiệu về Interceptor Interceptor là một cơ chế cho phép chúng ta "giữ lại" việc gọi một phương thức và thực hiện các hành động nào đó trước và sau khi phương thức đó được gọi. Điều này thường được sử dụng để thêm logic chung, theo dõi, đo lường hoặc thậm chí thay đổi hành vi của các phương thức. Cài đặt Tạo Project ASP.NET MVC. Sau đó, cài đặt các package sau: Install-Package Autofac.Extensions.DependencyInjection Install-Package Autofac.Mvc5 Autofac.Extras.DynamicProxy Bạn cần có service và 1 interceptor để gắn vào service đó. Thêm IMessageService và MessageService public inte...

CQRS là gì?

Giới thiệu Trong thiết kế phần mềm, CQRS (Command Query Responsibility Segregation) và CQS (Command Query Separation) là hai mẫu thiết kế quan trọng, giúp tách biệt việc xử lý lệnh (command) và truy vấn (query). Tuy có tên gần nhau và có mục tiêu chung là tạo sự tách biệt giữa lệnh và truy vấn, nhưng chúng có những điểm khác biệt quan trọng.  Trong bài viết này, chúng ta sẽ tìm hiểu về sự khác biệt giữa CQRS và CQS. Command Query Separation (CQS) Command-query separation (CQS) is a principle of imperative computer programming. It was devised by Bertrand Meyer as part of his pioneering work on the Eiffel programming language. It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. CQS là một nguyên tắc thiết kế mẫu nơi mà việc gửi lệnh (command) và truy vấn (query) phải được tách biệt hoàn toàn. Nguyên tắc này đề xuất rằng mỗi phương thức trong hệ thống phần mềm sẽ là hoặc một lệnh (command) hoặc m...

Dispatcher Design Pattern

Giới thiệu Dispatcher Design Pattern là một mẫu thiết kế phần mềm thuộc nhóm hành vi (behavioral design pattern) được sử dụng để quản lý và điều phối các tasks, events, hoặc notification giữa các thành phần trong hệ thống. Mục tiêu chính của Dispatcher Pattern là giảm sự phụ thuộc trực tiếp giữa các thành phần, từ đó tăng tính tái sử dụng và linh hoạt của mã nguồn. So sánh Dispatcher với Service Tạo chương trình Console Application gồm có 2 Component A và B đều có hàm HanndleEvent(). namespace DispatcherDesignPattern.ServiceA; public class ComponentA { public void HandleEvent() { Console.WriteLine("ComponentA handles event"); } } namespace DispatcherDesignPattern.ServiceB; public class ComponentB { public void HandleEvent() { Console.WriteLine("ComponentB handles event"); } } Trong ví dụ đầu tiên, chúng ta tạo thêm Service EventService để gọi 2 hàm HandleEvent() của ComponentA và ComponentB. Chúng ta cần khai báo Compo...

Giới thiệu Aspect Oriented Programming (AOP)

Nguồn:  https://gpcoder.com/5112-gioi-thieu-aspect-oriented-programming-aop/ AOP là gì? Trong khi xây dựng các chương trình ứng dụng, có rất nhiều những vấn đề liên quan đến phần mềm mà chúng ta cần quan tâm. Chẳng hạn, chúng ta xây dựng một hệ thống đăng ký tạo tài khoản cho một ngân hàng. Ngoài công việc chính cho phép người dùng có thể tạo tài khoản (core concern), hệ thống còn phải đảm bảo các vấn đề khác (cross-cutting concern) như chứng thực người dùng, kiểm tra ràng buộc, quản lý transaction, xử lý ngoại lệ, ghi log, debug, đo hiệu năng của ứng dụng, … Logger logger = Logger.getLogger(...); TransactionManager tm = getTransactionManager(); public void addAccount(Account account) { logger.info("Creating (" + account + ") Account"); try { tm.beginTransaction(); db.add(account); tm.commit(); } catch (Exception) { tm.rollback(); logger.error("Account creation failed"); } } Như bạn thấy, logic của c...