5 điểm bởi GN⁺ 2025-03-29 | 1 bình luận | Chia sẻ qua WhatsApp
  • Các ứng dụng Python phức tạp khi mở rộng quy mô sẽ khó tiếp tục chịu đựng việc kiểm thử và thay đổi chỉ với cách triển khai đơn giản, và cuốn sách này trình bày các mẫu kiến trúc như lời giải thông qua các ví dụ mã
  • Lấy việc bán đồ nội thất trực tuyến của MADE.com và chuỗi cung ứng toàn cầu làm ví dụ, sách đặt trọng tâm vào domain modeling để chuyển các vấn đề vận hành trong thế giới thực thành mô hình phần mềm
  • Trục chính là TDD, DDD và kiến trúc hướng sự kiện, với mục tiêu là kiểm thử đơn vị nhanh, số lượng kiểm thử E2E ít, mô hình tách rời hạ tầng và tích hợp dựa trên message
  • Dù sử dụng Flask, SQLAlchemy, pytest, Docker, Redis, trọng tâm vẫn là tạo ra một cấu trúc trong đó lựa chọn công nghệ cụ thể bị đẩy xuống thành chi tiết triển khai
  • Bất kỳ ai đã từng xử lý ứng dụng Python phức tạp đều có thể đọc được, và không cần biết trước về DDD hay các mẫu kiến trúc ứng dụng cổ điển

Bắt đầu từ bài toán về một cấu trúc dễ kiểm thử

  • Sau cuốn sách trước của Harry Test-Driven Development with Python, câu hỏi còn lại là phải cấu trúc ứng dụng thế nào để việc kiểm thử trở nên dễ dàng
  • Điểm cốt lõi là tạo ra một cấu trúc có thể bao phủ đầy đủ business logic bằng kiểm thử đơn vị, đồng thời giảm tối đa số lượng kiểm thử tích hợp và kiểm thử E2E
  • Dù từng nhắc đến các khái niệm như "Hexagonal Architecture", "Ports and Adapters", "Functional Core, Imperative Shell", vào thời điểm đó họ vẫn chưa thực sự hiểu hoặc áp dụng chúng một cách đầy đủ
  • Bob trở thành kiến trúc sư vì trong nhóm không có ai phụ trách software architecture, và đã học được từ Ian Cooper một cách tiếp cận mới về viết mã và tư duy

Trường hợp MADE.com: mô hình hóa chuỗi cung ứng bằng phần mềm

  • Hai tác giả từng làm việc tại công ty thương mại điện tử châu Âu MADE.com và đã áp dụng các kỹ thuật trong sách để xây dựng hệ thống phân tán mô hình hóa các bài toán kinh doanh thực tế
  • Miền ví dụ dựa trên hệ thống đầu tiên Bob xây ở MADE, với mục tiêu sắp xếp lại những gì cần dạy cho các lập trình viên mới gia nhập nhóm
  • MADE.com vận hành một chuỗi cung ứng toàn cầu gồm các đối tác vận chuyển hàng hóa và nhà sản xuất
    • Để giảm chi phí, họ muốn tối ưu giao hàng sao cho không phải giữ hàng trong kho quá lâu
    • Lý tưởng nhất là chiếc ghế sofa đến cảng đúng vào ngày khách hàng mua, rồi được chuyển thẳng đến nhà khách mà không cần lưu kho
    • Có thể mất tới 3 tháng để hàng đến nơi bằng tàu container, nên việc căn thời điểm rất khó
  • Trong thực tế vận hành, luôn liên tục phát sinh các biến số như hư hỏng, ngập nước, chậm trễ do bão, lỗi xử lý từ đối tác logistics, thiếu giấy tờ, hoặc khách hàng thay đổi đơn hàng
  • Để xử lý các vấn đề đó, họ muốn biểu diễn vận hành trong thế giới thực bằng phần mềm và tự động hóa càng nhiều công việc càng tốt

Những giới hạn bộc lộ khi dự án Python lớn dần

  • Python đã phát triển nhanh và trưởng thành hơn, nhưng giờ mới thật sự bắt đầu đảm nhận loại bài toán mà hệ sinh thái C# và Java đã xử lý từ lâu
  • Startup trở thành doanh nghiệp thực sự, còn web app và tự động hóa bằng script thì phát triển thành enterprise software
  • Triết lý của Python có câu “There should be one—and preferably only one—obvious way to do it”, nhưng khi quy mô dự án lớn lên, cách obvious nhất không phải lúc nào cũng phù hợp để quản lý độ phức tạp và thay đổi yêu cầu
  • Các kỹ thuật và mẫu được nói đến trong sách không mới, nhưng phần lớn vẫn còn tương đối mới với thế giới Python
  • Đây không phải là cuốn sách nhằm thay thế Domain-Driven Design của Eric Evans hay Patterns of Enterprise Application Architecture của Martin Fowler; ngược lại, sách thường xuyên tham chiếu các tác phẩm kinh điển đó và khuyến nghị nên đọc
  • Các ví dụ mã trong tài liệu hiện có thường được viết bằng Java hoặc C++/#, nên với lập trình viên Python, chúng có thể khá nặng để tiếp cận

Ba công cụ để quản lý độ phức tạp

  • Phát triển hướng kiểm thử (TDD) giúp tạo ra mã đúng và cho phép refactor hay thêm tính năng mà không sợ regression
    • Cách chạy kiểm thử nhanh nhất có thể
    • Cách lấy được nhiều độ bao phủ và phản hồi nhất từ các kiểm thử đơn vị nhanh, không phụ thuộc vào dependency
    • Cách giảm thiểu các kiểm thử E2E chậm và thiếu ổn định
  • Thiết kế hướng miền (DDD) buộc ta tập trung vào việc tạo ra một mô hình tốt cho miền nghiệp vụ
    • Cách để mô hình không bị ràng buộc bởi các mối quan tâm về hạ tầng
    • Cách để mô hình không trở nên khó thay đổi
  • Microservice kết hợp lỏng lẻo và tích hợp bằng message, đôi khi được gọi là reactive microservices, được xem như lời giải để quản lý độ phức tạp giữa nhiều ứng dụng hoặc nhiều miền kinh doanh
    • Tuy nhiên, cách ghép chúng với các công cụ sẵn có trong hệ sinh thái Python như Flask, Django, Celery không phải lúc nào cũng rõ ràng
  • Ngay cả khi không dùng hoặc không quan tâm đến microservices, phần lớn các mẫu trong sách và một phần đáng kể nội dung về kiến trúc hướng sự kiện vẫn áp dụng được cho kiến trúc monolithic

Độc giả và kiến thức giả định

  • Cuốn sách giả định người đọc đã từng tiếp xúc khá gần với các ứng dụng Python có độ phức tạp nhất định
  • Sách dành cho những ai đã trải qua nỗi đau của việc quản lý độ phức tạp
  • Không cần có kiến thức trước về DDD hay các mẫu kiến trúc ứng dụng cổ điển
  • Phần giải thích được xây dựng dần theo từng chương xoay quanh một ứng dụng ví dụ
  • Do các tác giả dùng TDD trong công việc, họ thường trình bày mã kiểm thử trước rồi mới đến phần triển khai
  • Sách dùng Flask, SQLAlchemy, pytest, Docker, Redis, nhưng nếu đã quen thì sẽ có ích chứ không phải điều kiện bắt buộc
  • Một trong những mục tiêu chính là tạo ra kiến trúc trong đó các lựa chọn công nghệ cụ thể trở thành chi tiết triển khai nhỏ nhặt

Cấu trúc của cuốn sách

  • Sách được chia thành hai phần
  • Phần 1: Kiến trúc hỗ trợ domain modeling

    • Domain modeling và DDD được trình bày ở chương 1, 2 và 7
    • Sách đặt ra tiền đề rằng các bài toán kinh doanh phức tạp phải được phản ánh thành mô hình miền trong mã
    • Giải thích cách bắt đầu từ một mô hình không có phụ thuộc bên ngoài và có thể được kiểm thử đơn vị rất nhanh
    • Sau đó quay lại bàn về việc chọn aggregate phù hợp và các vấn đề toàn vẹn dữ liệu
    • Các mẫu Repository, Service Layer, Unit of Work được trình bày ở chương 2, 4 và 5
    • Những mẫu này bổ trợ cho nhau để tách mô hình khỏi các phụ thuộc không cần thiết
    • Sách tạo một lớp trừu tượng quanh kho lưu trữ bền vững và đặt một service layer để nắm bắt các điểm vào hệ thống cùng những use case chính
    • Cho thấy một cấu trúc giúp dễ dàng tạo ra các điểm vào mỏng như Flask API hay CLI
    • Thảo luận về trừu tượng hóa và kiểm thử được tiếp tục ở chương 3 và 5
    • Sau khi giới thiệu mẫu Repository, sách bàn về cách chọn trừu tượng hóa và vai trò của nó trong cách ghép nối
    • Sau mẫu Service Layer, sách đề cập đến tháp kiểm thử và cách viết kiểm thử đơn vị ở mức trừu tượng cao nhất có thể
  • Phần 2: Kiến trúc hướng sự kiện

    • Kiến trúc hướng sự kiện được trình bày từ chương 8 đến 11
    • Giới thiệu các mẫu Domain Events, Message Bus, Handler
    • Domain Events là phương tiện để biểu đạt ý niệm rằng một tương tác nào đó trong hệ thống sẽ kích hoạt hành động khác
    • Message Bus cho phép hành động kích hoạt sự kiện và gọi handler phù hợp
    • Sách bàn về cách dùng sự kiện như một mẫu tích hợp giữa các dịch vụ trong kiến trúc microservices
    • Sách phân biệt commands và events, và ứng dụng về bản chất trở thành một hệ thống xử lý message
    • Ở chương 12, sách trình bày ví dụ CQRS theo cả cách dùng sự kiện và không dùng sự kiện
    • Ở chương 13, sách sắp xếp lại các phụ thuộc tường minh và ngầm định, đồng thời hiện thực một framework dependency injection đơn giản
    • Trong phần kết, sách nói về cách áp dụng các nguyên tắc này vào phần mềm hiện có thay vì chỉ vào ví dụ đơn giản bắt đầu từ đầu, đồng thời cung cấp thêm tài liệu nên đọc

Mã ví dụ và cách làm theo

  • Sách được xây dựng xoay quanh một dự án ví dụ duy nhất, và dự án này được mở rộng dần theo từng chương
  • Tác giả coi trọng việc người đọc thật sự chạm tay vào mã để có cảm giác về cách các mẫu hoạt động
  • Toàn bộ mã đều có trên GitHub và mỗi chương có một branch riêng
  • Có ba cách được đề xuất để làm theo
    • Tự tạo repository, xây dựng ứng dụng theo ví dụ trong sách và tham khảo repository của tác giả khi cần
    • Thử áp dụng từng mẫu theo từng chương vào dự án nhỏ của chính mình
    • Dùng phần "Exercise for the Reader" của từng chương cùng với mã GitHub có một số phần để trống để thực hành nhanh
  • Đặc biệt, với những ai muốn áp dụng các mẫu vào dự án riêng, việc xử lý ví dụ đơn giản trước sẽ là một bài luyện tập an toàn
  • Tối thiểu, tác giả khuyến nghị khi đọc từng chương hãy dùng git checkout để lấy mã từ repository và xem mã trong ngữ cảnh của một ứng dụng đang chạy thực sự

Giấy phép và định dạng

  • Mã và phiên bản trực tuyến được cấp phép theo Creative Commons CC BY-NC-ND
    • Mục đích phi thương mại
    • Ghi công tác giả
    • Được phép sao chép và chia sẻ
  • Bản in tuân theo giấy phép riêng, và nếu có lo ngại về việc tái sử dụng thì nên liên hệ O’Reilly
  • Quy ước trình bày trong sách phân biệt chữ nghiêng, chữ đơn cách, chữ đơn cách in đậm và chữ đơn cách nghiêng
    • Chữ nghiêng biểu thị thuật ngữ mới, URL, địa chỉ email, tên tệp và phần mở rộng
    • Chữ đơn cách biểu thị listing chương trình và các phần tử mã
    • Chữ đơn cách in đậm biểu thị lệnh hoặc văn bản mà người dùng phải nhập nguyên văn
    • Chữ đơn cách nghiêng biểu thị phần văn bản sẽ được thay bằng giá trị do người dùng cung cấp hoặc do ngữ cảnh quyết định

1 bình luận

 
xguru 2025-03-29

Đã có bản tiếng Hàn: Mẫu kiến trúc qua Python