Nguyen Le PhongNguyen Le Phong

Loạt bài Blog

Nền tảng kiến trúc phần mềm

Một lộ trình thực tế qua ranh giới code, dependency direction, distributed systems, resilience, dữ liệu và những trade-off xuất hiện khi phần mềm lớn dần.

Source Code & Software Architecture

Clean, Onion và Hexagonal Architecture: ba tên gọi cho cùng một hướng nghĩ

Clean Architecture, Onion Architecture và Hexagonal Architecture thường bị xem như ba trường phái khác nhau. Thực ra chúng cùng nhắc về một điều: domain và business rule nên nằm ở trung tâm, framework và chi tiết kỹ thuật ở ngoài rìa. Bài này so sánh nhẹ nhàng để bạn chọn cách gọi và cách vẽ phù hợp với team.

15 phút đọc
Source Code & Software Architecture

Dependency Injection & Inversion of Control: bớt coupling mà không cần phép thuật

DI và IoC không phải phép màu của framework. Ý tưởng đơn giản hơn nhiều: đừng để một class tự tạo mọi dependency mà nó cần; hãy đưa dependency từ bên ngoài vào. Bài này giải thích vì sao cách làm đó giúp code dễ test hơn, dễ thay đổi hơn và đỡ dính chặt vào database, SDK hay service cụ thể.

14 phút đọc
Source Code & Software Architecture

Tổ chức codebase: theo layer, feature hay domain?

Một codebase bắt đầu lớn lên từ những lựa chọn rất nhỏ: thư mục trên cùng nên là controllers/services/models, hay orders/billing/auth? Bài này so sánh cách tổ chức theo layer, theo feature và theo domain, chỉ ra mỗi kiểu hợp với giai đoạn nào, và vì sao cấu trúc thư mục thật ra đang kể cách team suy nghĩ về sản phẩm.

14 phút đọc
Source Code & Software Architecture

Monolith, Modular Monolith hay Microservices: chọn theo giai đoạn, không theo trend

Microservices không phải điểm xuất phát bắt buộc, mà thường là cái giá phải trả khi team và hệ thống đã đủ lớn. Bài này đi qua hành trình từ monolith, modular monolith đến microservices, với các dấu hiệu thực tế giúp bạn biết khi nào nên tách, khi nào nên giữ lại, và khi nào chỉ đang đổi sự đơn giản lấy thêm vận hành.

16 phút đọc
Source Code & Software Architecture

Micro-Frontends: khi nào đáng tách, khi nào chỉ thêm rối

Micro-frontends có thể giúp nhiều team deploy độc lập hơn, nhưng cũng mang theo chi phí về routing, shared dependency, design system, performance và ownership. Bài này nhìn micro-frontends từ kinh nghiệm thực tế, để bạn biết khi nào nó giải phóng team, và khi nào nó chỉ biến frontend thành một distributed system khó chăm hơn.

15 phút đọc
Source Code & Software Architecture

Event-Driven Architecture: khi service bớt gọi trực tiếp và hệ thống dễ thở hơn

Khi service nào cũng gọi trực tiếp service khác, một dependency chậm có thể kéo cả checkout đi xuống. Bài này giải thích event-driven architecture bằng cách gần gũi: khi nào nên dùng sync hay async, command khác event ra sao, message broker thật sự bảo đảm điều gì, choreography và orchestration khác nhau thế nào, và lúc nào events chỉ làm hệ thống rối hơn.

15 phút đọc
Source Code & Software Architecture

Database-per-Service, Saga và Eventual Consistency: dữ liệu sống thế nào trong distributed systems

Tách code thường dễ hơn tách dữ liệu. Khi mỗi service cần sở hữu dữ liệu riêng, team phải đối mặt với shared database, eventual consistency, dual-write bug, outbox, saga, CQRS và event sourcing. Bài này đi qua những lựa chọn đó bằng ví dụ thực tế, để bạn hiểu trade-off trước khi hệ thống phân tán bắt đầu làm mọi thứ khó hơn.

14 phút đọc
Source Code & Software Architecture

Timeout, Retry, Circuit Breaker và Idempotency: bộ kỹ năng sống còn của distributed systems

Một lời gọi ra khỏi process có thể chậm, lỗi, timeout, hoặc chạy hai lần. Đó không phải chuyện hiếm, mà là đời sống bình thường của distributed systems. Bài này gom lại những kỹ thuật giúp hệ thống bền hơn: timeout, retry với backoff và jitter, idempotency, circuit breaker, bulkhead, graceful degradation và observability.

14 phút đọc