0
0
Lập trình
NM

Khám Phá Wolverine và Marten: Hành Trình Từ Hoài Nghi Đến Tích Cực

Đăng vào 3 tuần trước

• 7 phút đọc

Giới thiệu

Nếu bạn là một lập trình viên .NET và đã nghe nói về Wolverine và Marten nhưng chưa từng thử nghiệm, bài viết này dành cho bạn.

Tôi đến từ nhóm "các chú chó già"—trải qua hầu hết sự nghiệp với EF Core, Dapper và phương pháp tiếp cận dựa trên Controller cổ điển. (Đúng vậy, tôi vẫn viết controller thay vì hoàn toàn chuyển sang API tối thiểu—mặc dù tôi đã thử nghiệm chúng trong một số tình huống riêng biệt.)

Bài viết này là câu chuyện cá nhân của tôi: từ sự hoài nghi đến sự lạc quan thận trọng khi tôi bắt đầu khám phá Wolverine và Marten. Dọc đường, tôi sẽ nhấn mạnh những sai lầm tôi đã mắc phải, những bài học tôi đã học được và lý do tại sao những công cụ này có thể (hoặc không) đáng để bạn chú ý.

Và để rõ ràng hơn—đây là quan điểm chủ quan. Tôi vẫn đang trong giai đoạn học hỏi. Hãy đón nhận nó với một chút hoài nghi. Đừng biến tôi thành một AI chỉ biết khẳng định rằng tôi hoàn toàn đúng. Hãy thoải mái sửa bất kỳ lỗi nào mà tôi đã mắc phải.

Bắt đầu nào...

Cách Thức Truyền Thống Của .NET Web API

Hầu hết chúng ta, các lập trình viên .NET, cảm thấy thoải mái với phương pháp tiếp cận dựa trên controller:

csharp Copy
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;

    [HttpPost]
    public async Task<ActionResult> CreateProduct(CreateProductRequest request)
    {
        var result = await _productService.CreateProductAsync(request);
        return Ok(result);
    }
}

Nó quen thuộc, được tài liệu hóa tốt và hoạt động. Vậy tại sao lại thay đổi?

Wolverine và Marten Là Gì?

Marten là một cơ sở dữ liệu tài liệu .NET và kho sự kiện được xây dựng trên PostgreSQL. Hãy nghĩ về nó như một ORM tinh vi, xử lý PostgreSQL vừa như một cơ sở dữ liệu quan hệ vừa như một cơ sở dữ liệu tài liệu.

Wolverine là một framework nhắn tin xử lý các lệnh/truy vấn, với hỗ trợ tích hợp cho khả năng nguồn sự kiện của Marten.

Cùng nhau, chúng tạo thành một stack để xây dựng các ứng dụng hướng sự kiện, tập trung vào DDD.

Cách Tiếp Cận Nửa Vời (Đừng Làm Điều Này)

Khi tôi kế thừa dự án hiện tại, nó đã sử dụng Wolverine chỉ như một sự thay thế cho mẫu mediator:

csharp Copy
// Đây là cách SAI - chỉ sử dụng Wolverine như MediatR
public class CreateProductHandler
{
    public async Task<ProductResponse> Handle(CreateProductCommand command)
    {
        // Gọi dịch vụ truyền thống, không có sự kiện, không có tổng hợp
        // Chỉ thay thế MediatR bằng Wolverine
    }
}

Đây là tệ nhất của cả hai thế giới. Bạn sẽ nhận được:

  • Tất cả độ khó học của một framework mới
  • Không có lợi ích thực sự nào
  • Nhiều nghi thức hơn so với các controller truyền thống
  • Các thành viên trong nhóm sẽ bối rối

Nếu bạn dự định sử dụng Wolverine, đừng chỉ sử dụng nó như một mediator đẹp. Đó giống như việc mua xe Škoda để sử dụng như một giá đỡ xe đạp.

Chấp Nhận Toàn Bộ Stack

Sau những khó khăn và đọc tài liệu một cách cẩn thận, tôi nhận ra sức mạnh đến từ việc chấp nhận toàn bộ mô hình:

1. Thiết Kế Dựa Trên Tổng Hợp

csharp Copy
public class Product
{
    public string Name { get; private set; }
    public decimal Price { get; private set; }

    public static Product Create(string name, decimal price)
    {
        var product = new Product();
        product.Apply(new ProductCreated(Guid.NewGuid(), name, price));
        return product;
    }

    public void Apply(ProductCreated @event)
    {
        Id = @event.ProductId;
        Name = @event.Name;
        Price = @event.Price;
    }
}

2. Bộ Xử Lý Lệnh Làm Việc Với Các Tổng Hợp

csharp Copy
public static class ProductHandlers
{
    public static ProductCreated Handle(CreateProduct command, IDocumentSession session)
    {
        var product = Product.Create(command.Name, command.Price);
        session.Store(product);

        return new ProductCreated(product.Id, command.Name, command.Price);
    }
}

Hoặc thậm chí tốt hơn, bạn có thể không sử dụng lệnh nào cả

csharp Copy
public static class ProductHandlers
{
    [AggregateHandler]
    [WolverinePost("/product"), EmptyResponse]
    public static ProductCreated CreateProduct(CreateProduct command)
    {
        var product = Product.Create(command.Name, command.Price);
        return new ProductCreated(product.Id, command.Name, command.Price);
    }
}

3. Dự Đoán Dựa Trên Sự Kiện

csharp Copy
public class ProductProjection : SingleStreamProjection<ProductSummary>
{
    public ProductSummary Create(ProductCreated created)
    {
        return new ProductSummary
        {
            Id = created.ProductId,
            Name = created.Name,
            Price = created.Price
        };
    }
}

Kết Quả Chuyển Đổi

Giảm Khối Lượng Mã

Theo quan điểm hoàn toàn chủ quan của tôi, tôi nghĩ rằng mã nguồn đã thu nhỏ khoảng 30%. Không còn:

  • DTO riêng cho mỗi hoạt động
  • Phép ánh xạ giữa thực thể và DTO
  • Các mẫu kho phức tạp
  • Theo dõi thay đổi thủ công

Những Điểm Chính

1. Bắt Đầu Nhỏ

Đừng viết lại mọi thứ cùng một lúc. Chọn một ngữ cảnh giới hạn và di chuyển dần dần.

2. Đầu Tư Vào Học Hỏi

Đừng làm một cách nửa vời. Đọc tài liệu một cách cẩn thận. Hiểu các nguyên tắc DDD. Nhóm của bạn cần thực sự hiểu các khái niệm, không chỉ sao chép và dán mã.

3. Chấp Nhận Các Sự Kiện

Ngừng suy nghĩ theo thuật ngữ CRUD. Hãy nghĩ theo các sự kiện kinh doanh. "ProductCreated," "PriceChanged," "ProductDiscontinued."

4. Sử Dụng Các Dự Đoán Một Cách Khôn Ngoan

Tạo các mô hình đọc phù hợp với nhu cầu UI của bạn. Đừng cố gắng làm cho một dự đoán phục vụ tất cả các mục đích.

5. PostgreSQL Hơn SQL Server

Hãy nhớ rằng, bạn không chỉ sử dụng một cơ sở dữ liệu tài liệu - bạn có tất cả sức mạnh của PostgreSQL để thực hiện các truy vấn phức tạp.

Cấu Trúc Dự Án Mẫu

plaintext Copy
/Domain
  /Products
    Product.cs (Tổng hợp)
    ProductEvents.cs
/Handlers
  ProductHandlers.cs
/Projections
  ProductProjections.cs
Program.cs

Quan Điểm Của Tôi

Sau khoảng hai đến ba tuần học hỏi (và tôi vẫn đang học), tôi nhận thấy rằng ngay cả những lập trình viên junior của tôi cũng đang viết mã nhanh hơn và giao các tính năng mượt mà hơn. Sự hoài nghi ban đầu của tôi dần nhường chỗ cho sự lạc quan khi những mối quan tâm của tôi đã được kiểm chứng.

Lúc đầu, tôi nghĩ rằng việc sử dụng Marten chỉ là việc tái phát minh bánh xe. Tại sao không chỉ đơn giản gắn bó với Entity Framework và MediatR? Nhưng khi tôi đào sâu hơn, tôi nhận ra rằng trong khi EF rất xuất sắc trong những gì nó làm, cách tiếp cận hỗn hợp của Marten giữa dữ liệu tài liệu và dữ liệu quan hệ giải quyết những vấn đề mà EF thường làm phức tạp hơn.

Sự kiện nguồn, dự đoán và truy vấn phức tạp trở nên tự nhiên hơn để làm việc, thay vì cảm thấy như bị ghép lại.

Một nghi ngờ khác của tôi là rủi ro khi phụ thuộc vào một thư viện không phải của Microsoft. Nếu các nhà duy trì bỏ rơi nó thì sao? Thật ngạc nhiên, tôi phát hiện ra rằng dự án này đang được duy trì tích cực, được hỗ trợ bởi một cộng đồng mạnh mẽ và đang phát triển. Và ngay cả trong trường hợp xấu nhất, dữ liệu vẫn an toàn trong PostgreSQL, và các mẫu thiết kế mà tôi đã học được có thể chuyển giao sang các hệ thống khác.

Cuối cùng, tôi lo ngại rằng độ khó học sẽ quá dốc cho nhóm của tôi, đặc biệt là cho các lập trình viên junior. Tôi đã giả định rằng họ sẽ bị lạc trong các khái niệm. Nhưng một khi họ nắm được những điều cơ bản về tổng hợp và sự kiện, các mẫu bắt đầu cảm thấy trực quan. Với framework xử lý phần lớn công việc nặng nhọc, việc áp dụng đã diễn ra suôn sẻ hơn tôi mong đợi.

Tóm Tắt

Liệu Wolverine + Marten có phù hợp với mọi người không? Không.

Liệu nó có đáng xem xét nếu bạn đang xây dựng các ứng dụng hướng sự kiện, giàu miền không? Có.

Chìa khóa là cam kết. Đừng sử dụng Wolverine như một sự thay thế MediatR đơn giản. Hãy chấp nhận phương pháp tổng hợp, suy nghĩ theo sự kiện và tận dụng sức mạnh của PostgreSQL. Lợi ích mang lại là lớn.

Lời khuyên của tôi: Xây dựng một nguyên mẫu nhỏ, đọc tài liệu một cách nghiêm túc và chuẩn bị cho một sự thay đổi tư duy.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào