<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Clean Architecture với Golang on Thanh HV's Blog</title><link>https://thanhhv.github.io/series/clean-architect/</link><description>Recent content in Clean Architecture với Golang on Thanh HV's Blog</description><generator>Hugo -- 0.146.7</generator><language>en-us</language><lastBuildDate>Wed, 08 Jul 2026 15:00:00 +0700</lastBuildDate><atom:link href="https://thanhhv.github.io/series/clean-architect/index.xml" rel="self" type="application/rss+xml"/><item><title>Chương 14 — Level 4 Principal: Evolutionary Architecture, Refactor Legacy, Tổ chức &amp; Hiệu năng</title><link>https://thanhhv.github.io/series/clean-architect/14-principal/01-evolutionary-architecture-va-migration/</link><pubDate>Wed, 08 Jul 2026 15:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/14-principal/01-evolutionary-architecture-va-migration/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 4 – Principal&lt;/strong> · Ở cấp này, kiến trúc không còn là bài toán code — nó là bài toán &lt;em>thời gian&lt;/em> (hệ thống tiến hóa), &lt;em>con người&lt;/em> (team, ownership) và &lt;em>kinh tế&lt;/em> (chi phí, rủi ro, thứ tự đầu tư).&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-evolutionary-architecture--thiết-kế-cho-sự-thay-đổi-của-chính-kiến-trúc">1. Evolutionary Architecture — thiết kế cho sự thay đổi của chính kiến trúc&lt;/h2>
&lt;p>Sai lầm cấp principal phổ biến nhất: thiết kế &amp;ldquo;kiến trúc đích&amp;rdquo; 5 năm rồi ép hệ thống về nó. Thực tế: nghiệp vụ, tổ chức và công nghệ đều thay đổi nhanh hơn kế hoạch 5 năm. Kiến trúc tiến hóa (Ford/Parsons/Kua) đảo cách đặt vấn đề: &lt;strong>thay vì đoán đích đúng, tối ưu chi phí đổi hướng.&lt;/strong>&lt;/p></description></item><item><title>Chương 13 — So sánh khách quan: Clean vs Layered vs Hexagonal vs Onion vs MVC vs Modular Monolith vs DDD</title><link>https://thanhhv.github.io/series/clean-architect/13-so-sanh/01-so-sanh-cac-kien-truc/</link><pubDate>Wed, 08 Jul 2026 14:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/13-so-sanh/01-so-sanh-cac-kien-truc/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3–4&lt;/strong> · Mục tiêu: thoát khỏi tranh cãi danh pháp, chọn theo bài toán.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-khung-so-sánh">1. Khung so sánh&lt;/h2>
&lt;p>Mỗi &amp;ldquo;kiến trúc&amp;rdquo; thực chất trả lời một tập câu hỏi khác nhau — so sánh chỉ công bằng khi đặt đúng tầng câu hỏi:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Tầng tổ chức phụ thuộc trong một đơn vị deploy&lt;/strong>: Layered, Hexagonal, Onion, Clean.&lt;/li>
&lt;li>&lt;strong>Tầng tổ chức delivery/UI&lt;/strong>: MVC.&lt;/li>
&lt;li>&lt;strong>Tầng topology hệ thống&lt;/strong>: Modular Monolith (và Microservices).&lt;/li>
&lt;li>&lt;strong>Tầng mô hình hóa nghiệp vụ&lt;/strong>: DDD.&lt;/li>
&lt;/ul>
&lt;p>Chúng không loại trừ nhau — một hệ thống có thể đồng thời là: modular monolith (topology) × Clean Architecture (phụ thuộc) × DDD (mô hình) × MVC (trong tầng delivery).&lt;/p></description></item><item><title>Chương 12.3 — E-commerce · Giai đoạn 3: Tách service khi tổ chức đòi hỏi</title><link>https://thanhhv.github.io/series/clean-architect/12-vi-du-ecommerce/03-giai-doan-3-tach-service/</link><pubDate>Wed, 08 Jul 2026 13:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/12-vi-du-ecommerce/03-giai-doan-3-tach-service/</guid><description>&lt;blockquote>
&lt;p>Năm thứ 4: 40 engineer, 6 team, 500 nghìn đơn/ngày. Đây là chương về &lt;em>lý do đúng&lt;/em> và &lt;em>lý do sai&lt;/em> để tách, cùng kỹ thuật tách không ngừng hệ thống.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-khi-nào-monolith-thật-sự-hết-vai-trò">1. Khi nào monolith thật sự hết vai trò&lt;/h2>
&lt;p>Lý do &lt;strong>đúng&lt;/strong> (xuất hiện ở công ty này):&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Deploy coupling thành nút cổ chai tổ chức&lt;/strong>: 6 team xếp hàng chung một release train; một bug của team Catalog rollback cả deploy chứa hotfix của team Payment. Chi phí phối hợp tăng theo bình phương số team.&lt;/li>
&lt;li>&lt;strong>Chênh lệch tải &amp;amp; tài nguyên&lt;/strong>: đường search catalog cần 40 pod CPU cao vào giờ vàng; đường payment cần ổn định tuyệt đối và audit riêng (PCI-DSS) — chung binary nghĩa là scale cả cụm theo nhu cầu của phần nóng nhất, và mọi engineer đều &amp;ldquo;ở trong phạm vi audit&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>Bán kính sự cố&lt;/strong>: memory leak trong module notification OOM-kill cả tiến trình chứa payment.&lt;/li>
&lt;/ul>
&lt;p>Lý do &lt;strong>sai&lt;/strong> (đã bị bác trong design review): &amp;ldquo;microservices hiện đại hơn&amp;rdquo;, &amp;ldquo;để dùng ngôn ngữ mới&amp;rdquo;, &amp;ldquo;CV-driven&amp;rdquo;. Phép thử: &lt;em>nếu tách xong mà số team, quy trình deploy và yêu cầu scale y nguyên — bạn vừa mua độ trễ mạng và partial failure mà không mua được gì.&lt;/em>&lt;/p></description></item><item><title>Chương 12.2 — E-commerce · Giai đoạn 2: Modular Monolith</title><link>https://thanhhv.github.io/series/clean-architect/12-vi-du-ecommerce/02-giai-doan-2-modular-monolith/</link><pubDate>Wed, 08 Jul 2026 12:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/12-vi-du-ecommerce/02-giai-doan-2-modular-monolith/</guid><description>&lt;blockquote>
&lt;p>18 tháng sau: 12 engineer chia 3 team, 50 nghìn đơn/ngày. Các vết nứt giai đoạn 1 giờ đau thật. Câu trả lời KHÔNG phải microservices — mà là siết ranh giới trong chính monolith.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="bối-cảnh-và-triệu-chứng">Bối cảnh và triệu chứng&lt;/h2>
&lt;ul>
&lt;li>Team Payment muốn thêm VNPay + trả góp; mỗi lần sửa đụng &lt;code>order.Service.Place&lt;/code> — file mà team Order cũng đang sửa hàng ngày. Merge conflict, release phải phối hợp.&lt;/li>
&lt;li>Marketing cần: gửi email sau đặt hàng, cộng điểm loyalty, đồng bộ CRM — ba team khác nhau cùng đòi chen code vào &lt;code>Place()&lt;/code>. Hàm 40 dòng thành 180 dòng.&lt;/li>
&lt;li>Sự cố &amp;ldquo;charge rồi mất đơn&amp;rdquo; xảy ra thật 7 lần trong tháng cao điểm — mỗi lần một buổi điều tra + hoàn tiền thủ công.&lt;/li>
&lt;li>Query dashboard người bán làm chậm cả đường ghi (chung DB, khóa lẫn nhau).&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Chẩn đoán đúng bệnh trước khi kê đơn:&lt;/strong> vấn đề là &lt;em>ranh giới module chưa đủ chặt&lt;/em> và &lt;em>coupling thời gian trong Place()&lt;/em> — không phải &amp;ldquo;vì chưa có microservices&amp;rdquo;. Tách process bây giờ sẽ nhân các vấn đề trên với độ trễ mạng và partial failure. Modular monolith: giữ một binary, nâng ranh giới lên chuẩn &amp;ldquo;như thể sắp tách&amp;rdquo;.&lt;/p></description></item><item><title>Chương 12.1 — E-commerce từng bước · Giai đoạn 1: Monolith khởi đầu đúng cách</title><link>https://thanhhv.github.io/series/clean-architect/12-vi-du-ecommerce/01-giai-doan-1-monolith/</link><pubDate>Wed, 08 Jul 2026 11:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/12-vi-du-ecommerce/01-giai-doan-1-monolith/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Ví dụ tổng hợp&lt;/strong> · Ba giai đoạn của cùng một hệ thống: (1) monolith gọn, (2) modular monolith khi nghiệp vụ dày lên, (3) tách service khi tổ chức đòi hỏi. Mỗi giai đoạn là quyết định có bối cảnh — không phải giai đoạn sau &amp;ldquo;xịn hơn&amp;rdquo; giai đoạn trước.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="bối-cảnh-giai-đoạn-1">Bối cảnh giai đoạn 1&lt;/h2>
&lt;p>Startup 3 engineer, 3 tháng để ra MVP bán hàng: đăng ký user, danh mục sản phẩm, đặt hàng, thanh toán qua một cổng (giả định &amp;ldquo;MoPay&amp;rdquo;). Chưa rõ nghiệp vụ sẽ phát triển hướng nào.&lt;/p></description></item><item><title>Chương 11 — Production Concerns: Logging, Config, Observability, Shutdown, Retry, Idempotency</title><link>https://thanhhv.github.io/series/clean-architect/11-production/01-production-concerns/</link><pubDate>Wed, 08 Jul 2026 10:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/11-production/01-production-concerns/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3–4&lt;/strong> · Kiến trúc đẹp mà không vận hành được là bài tập trên giấy. Chương này trả lời: các concern vận hành nằm ở vòng nào, và viết thế nào để chúng không ăn mòn ranh giới.&lt;/p>&lt;/blockquote>
&lt;p>Nguyên tắc chung của cả chương: &lt;strong>concern vận hành là cross-cutting → sống ở adapter/middleware/decorator/composition root; vòng trong cùng lắm biết &lt;em>khái niệm&lt;/em> (context, error), không bao giờ biết &lt;em>công cụ&lt;/em> (Prometheus, OTel, Viper).&lt;/strong>&lt;/p></description></item><item><title>Chương 10 — Clean Architecture &amp; CQRS: Đường ghi và đường đọc</title><link>https://thanhhv.github.io/series/clean-architect/10-cqrs/01-clean-architecture-va-cqrs/</link><pubDate>Wed, 08 Jul 2026 09:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/10-cqrs/01-clean-architecture-va-cqrs/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3 – Senior&lt;/strong> · CQRS thường bị hiểu là &amp;ldquo;kiến trúc phức tạp với event sourcing và 2 database&amp;rdquo;. Bản chất nó khiêm tốn và hữu ích hơn nhiều.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Hai áp lực kéo model về hai hướng ngược nhau:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Đường ghi (command)&lt;/strong> cần model giàu: aggregate, bất biến, rule — &lt;code>Order.AddLine()&lt;/code> phải kiểm tra trạng thái, tính lại tổng (chương 9).&lt;/li>
&lt;li>&lt;strong>Đường đọc (query)&lt;/strong> cần dữ liệu phẳng, join sẵn, đúng hình dạng màn hình: &amp;ldquo;danh sách đơn + tên khách + số item + trạng thái thanh toán, phân trang, lọc theo 5 tiêu chí&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;p>Ép một model phục vụ cả hai tạo ra hai loại đau: (a) đường đọc &lt;strong>qua aggregate&lt;/strong>: load N aggregate đầy đủ + N query phụ để render một cái bảng — chậm và code repository mọc &lt;code>FindAllWithCustomerNameAndPaymentStatus(...)&lt;/code> vô tận; (b) aggregate &lt;strong>phình theo nhu cầu đọc&lt;/strong>: thêm field chỉ để hiển thị, bất biến loãng dần.&lt;/p></description></item><item><title>Chương 9 — Clean Architecture &amp; DDD: Lấp đầy vòng trong</title><link>https://thanhhv.github.io/series/clean-architect/09-ddd/01-clean-architecture-va-ddd/</link><pubDate>Wed, 08 Jul 2026 08:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/09-ddd/01-clean-architecture-va-ddd/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3 – Senior&lt;/strong> · Clean Architecture cho bạn cái vỏ (ranh giới, hướng phụ thuộc); DDD cho bạn cái ruột (mô hình hóa nghiệp vụ bên trong vòng domain). Thiếu một trong hai: vỏ đẹp ruột rỗng, hoặc mô hình hay bị hạ tầng ăn mòn.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Clean Architecture nói &amp;ldquo;đặt business rule vào vòng trong&amp;rdquo; nhưng &lt;strong>không nói business rule trông như thế nào&lt;/strong>. Hệ quả phổ biến: team dựng đủ 4 tầng, rồi vòng domain chỉ chứa struct trần (anemic model), toàn bộ logic dồn vào &amp;ldquo;service&amp;rdquo; — tức Transaction Script khoác áo Clean Architecture, trả phí kiến trúc mà không nhận mô hình.&lt;/p></description></item><item><title>Chương 8 — Testing Strategy: Unit, Integration, Mock vs Fake, Testcontainers</title><link>https://thanhhv.github.io/series/clean-architect/08-testing/01-testing-strategy/</link><pubDate>Wed, 08 Jul 2026 07:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/08-testing/01-testing-strategy/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3 – Senior&lt;/strong> · Testability không phải phần thưởng phụ của Clean Architecture — nó là &lt;em>bằng chứng&lt;/em> kiến trúc đúng. Kiến trúc không test được là kiến trúc sai, bất kể sơ đồ đẹp đến đâu.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Hai thái cực thất bại phổ biến:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Test kim tự tháp ngược&lt;/strong>: 500 E2E test dựng cả hệ thống, chạy 40 phút, flaky 5% — CI thành xổ số, dev tắt test để merge. Nguyên nhân gốc: nghiệp vụ dính hạ tầng nên &lt;em>chỉ có thể&lt;/em> test kiểu E2E.&lt;/li>
&lt;li>&lt;strong>Mock hóa toàn phần&lt;/strong>: mock mọi thứ kể cả struct nội bộ, assert từng lời gọi hàm — test khẳng định &lt;em>code viết như thế nào&lt;/em> thay vì &lt;em>hệ thống làm gì&lt;/em>. Refactor giữ nguyên hành vi vẫn vỡ 200 test → test trở thành lực cản refactor, phản bội chính mục đích của nó.&lt;/li>
&lt;/ul>
&lt;p>Chiến lược đúng bám vào cấu trúc các vòng: &lt;strong>mỗi vòng một loại test, chi phí thấp nhất có thể cho độ tin cần thiết.&lt;/strong>&lt;/p></description></item><item><title>Chương 7 — Integration: Kafka, RabbitMQ, Redis, External API, Event Publishing</title><link>https://thanhhv.github.io/series/clean-architect/07-integration/01-integration/</link><pubDate>Wed, 08 Jul 2026 06:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/07-integration/01-integration/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3 – Senior&lt;/strong> · Ranh giới với thế giới bên ngoài — nơi lỗi, độ trễ và bất nhất là chuyện thường ngày.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Hệ thống thực không sống một mình: nó gọi cổng thanh toán, phát event cho hệ thống khác, cache bằng Redis, nhận lệnh từ queue. Ba rủi ro kiến trúc:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Kiến thức về hệ ngoài rò vào nghiệp vụ&lt;/strong>: use case biết tên topic Kafka, format JSON của đối tác, TTL Redis → đổi đối tác/hạ tầng là mổ nghiệp vụ.&lt;/li>
&lt;li>&lt;strong>Đặc tính mạng rò vào nghiệp vụ&lt;/strong>: retry, timeout, circuit breaker viết lẫn trong use case → quy trình nghiệp vụ chìm trong code chống lỗi.&lt;/li>
&lt;li>&lt;strong>Bất nhất dữ liệu&lt;/strong>: ghi DB xong, publish event fail — hai hệ thống từ nay lệch nhau vĩnh viễn (bài toán dual-write).&lt;/li>
&lt;/ol>
&lt;p>Cấu trúc lời giải cho cả ba giống nhau — cũng là cấu trúc của cả tài liệu này: &lt;strong>vòng trong khai báo cổng theo ngôn ngữ nghiệp vụ; adapter vòng ngoài gánh mọi đặc tính của công nghệ cụ thể.&lt;/strong>&lt;/p></description></item><item><title>Chương 6 — Delivery Layer: HTTP, gRPC, GraphQL, CLI, Worker</title><link>https://thanhhv.github.io/series/clean-architect/06-delivery/01-delivery-layer/</link><pubDate>Wed, 08 Jul 2026 05:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/06-delivery/01-delivery-layer/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 2–3&lt;/strong> · Bài kiểm tra thật sự của Clean Architecture: cùng một use case phục vụ N cách vào mà không đổi một dòng nghiệp vụ.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Hệ thống trưởng thành hiếm khi chỉ có một cửa vào. Cùng nghiệp vụ &amp;ldquo;đổi điểm&amp;rdquo;: mobile app gọi REST, service nội bộ gọi gRPC, chiến dịch marketing chạy batch qua CLI, và một Kafka consumer đổi điểm tự động khi có event mua hàng. Nếu nghiệp vụ viết trong HTTP handler, ba cửa còn lại chỉ có hai lựa chọn tồi: copy-paste logic, hoặc &lt;strong>giả lập HTTP request nội bộ&lt;/strong> (gọi chính API của mình) — cả hai đều là nợ.&lt;/p></description></item><item><title>Chương 5 — Data Access: Repository, Transaction, Unit of Work, ORM vs SQL</title><link>https://thanhhv.github.io/series/clean-architect/05-data-access/01-repository-transaction/</link><pubDate>Wed, 08 Jul 2026 04:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/05-data-access/01-repository-transaction/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 3 – Senior&lt;/strong> · Data access là nơi Clean Architecture bị thử thách gay gắt nhất trong thực tế — transaction, N+1, mapping — và là nơi nhiều dự án gãy.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Ba bài toán mà mọi hệ thống phải giải, và giải sai thì Dependency Rule sụp:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Nghiệp vụ cần dữ liệu nhưng không được biết SQL&lt;/strong> — ai đứng giữa? (Repository)&lt;/li>
&lt;li>&lt;strong>Một use case ghi nhiều bảng phải atomic&lt;/strong> — transaction là khái niệm hạ tầng, sao use case điều khiển được nó mà không import &lt;code>database/sql&lt;/code>? (bài toán khó nhất chương)&lt;/li>
&lt;li>&lt;strong>Model của DB và model của domain khác nhau đến đâu thì tách?&lt;/strong> (ORM vs SQL, mapping)&lt;/li>
&lt;/ol>
&lt;h2 id="2-repository-pattern--bản-chất-thật">2. Repository Pattern — bản chất thật&lt;/h2>
&lt;p>Repository &lt;strong>không phải&lt;/strong> &amp;ldquo;class bọc mấy câu SQL&amp;rdquo;. Định nghĩa gốc (Evans/Fowler): &lt;em>ảo giác một collection trong bộ nhớ chứa các domain object&lt;/em> — nghiệp vụ &amp;ldquo;lấy ra, thao tác, đặt lại&amp;rdquo;, không biết đằng sau là Postgres hay RAM.&lt;/p></description></item><item><title>Chương 4 — Dependency Injection trong Go: Manual, Wire, Fx và Interface Placement</title><link>https://thanhhv.github.io/series/clean-architect/04-dependency-injection/01-di-trong-go/</link><pubDate>Wed, 08 Jul 2026 03:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/04-dependency-injection/01-di-trong-go/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 2–3&lt;/strong> · DI là cơ chế &lt;em>thi công&lt;/em> của Dependency Rule: mọi mũi tên đã đảo ở thiết kế phải được nối lại ở runtime — chương này bàn nối ở đâu, bằng gì.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Sau khi áp dụng DIP, các component chỉ biết interface. Nhưng lúc chạy, ai đó phải quyết định &lt;code>order.Service&lt;/code> dùng &lt;code>postgres.WalletRepo&lt;/code> hay &lt;code>mongo.WalletRepo&lt;/code>, và tạo chúng theo đúng thứ tự với đúng config. Câu hỏi của chương: &lt;strong>việc lắp ráp đó viết thế nào để (a) tường minh, (b) không rò rỉ kiến thức lắp ráp vào nghiệp vụ, (c) không thành 500 dòng spaghetti trong main.go khi hệ thống lớn?&lt;/strong>&lt;/p></description></item><item><title>Chương 3.1 — Tổ chức Package trong Go: cmd/, internal/, pkg/ và các trường phái</title><link>https://thanhhv.github.io/series/clean-architect/03-go-project-structure/01-package-organization/</link><pubDate>Wed, 08 Jul 2026 02:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/03-go-project-structure/01-package-organization/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 2–3&lt;/strong> · Chương này trả lời câu hỏi thực dụng nhất: &amp;ldquo;project của tôi nên có cấu trúc thư mục thế nào?&amp;rdquo; — nhưng bằng nguyên lý, không bằng template.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Go không quy định cấu trúc project (khác Rails/Django). Tự do này tạo ra hai thái cực lỗi:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Thiếu cấu trúc&lt;/strong>: mọi thứ trong một package &lt;code>main&lt;/code> 20.000 dòng, hoặc chia file tùy hứng — không có ranh giới nào để compiler bảo vệ.&lt;/li>
&lt;li>&lt;strong>Thừa cấu trúc&lt;/strong>: bê nguyên template &amp;ldquo;golang-standard-project-layout&amp;rdquo; hay &amp;ldquo;clean-architecture-template&amp;rdquo; trên GitHub về cho một service 3 endpoint — 40 thư mục, mỗi feature chạm 9 file, team ghét kiến trúc từ đó.&lt;/li>
&lt;/ul>
&lt;p>Cả hai đều xuất phát từ việc coi cấu trúc thư mục là &lt;em>mục tiêu&lt;/em> thay vì &lt;em>hệ quả&lt;/em> của các quyết định ranh giới (chương 1.1) và hướng phụ thuộc (chương 2.2).&lt;/p></description></item><item><title>Chương 2.3 — Bốn vòng trong Go: từ Entity đến Framework</title><link>https://thanhhv.github.io/series/clean-architect/02-clean-architecture-core/03-cac-layer/</link><pubDate>Wed, 08 Jul 2026 01:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/02-clean-architecture-core/03-cac-layer/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 2 – Engineering&lt;/strong> · Chương này dựng một service hoàn chỉnh, chạy được, minh họa cả bốn vòng.&lt;/p>&lt;/blockquote>
&lt;p>Bài toán xuyên suốt: &lt;strong>service quản lý ví điểm thưởng (loyalty wallet)&lt;/strong> — nghiệp vụ đủ thật để có rule, đủ nhỏ để đọc hết:&lt;/p>
&lt;ul>
&lt;li>Khách tích điểm khi mua hàng (1 điểm / 10.000 VND, hạng GOLD nhân đôi).&lt;/li>
&lt;li>Đổi điểm lấy voucher; không cho âm điểm; mỗi ngày đổi tối đa 3 lần.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="1-vòng-1--entities-enterprise-business-rules">1. Vòng 1 — Entities (Enterprise Business Rules)&lt;/h2>
&lt;h3 id="bản-chất">Bản chất&lt;/h3>
&lt;p>Entity chứa &lt;strong>quy tắc đúng bất kể ứng dụng nào dùng nó&lt;/strong> — quy tắc sẽ tồn tại kể cả khi công ty vận hành bằng giấy bút: &amp;ldquo;điểm không âm&amp;rdquo;, &amp;ldquo;GOLD nhân đôi&amp;rdquo;. Nó không biết use case nào gọi nó, không biết dữ liệu từ đâu đến.&lt;/p></description></item><item><title>Chương 2.2 — Dependency Rule: Luật duy nhất</title><link>https://thanhhv.github.io/series/clean-architect/02-clean-architecture-core/02-dependency-rule/</link><pubDate>Wed, 08 Jul 2026 00:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/02-clean-architecture-core/02-dependency-rule/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 2 – Engineering&lt;/strong> · Nếu chỉ được nhớ một điều từ toàn bộ tài liệu, hãy nhớ chương này.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-phát-biểu">1. Phát biểu&lt;/h2>
&lt;blockquote>
&lt;p>&lt;strong>Source code dependencies must point only inward, toward higher-level policies.&lt;/strong>
Phụ thuộc mã nguồn chỉ được trỏ vào trong, về phía chính sách cấp cao hơn.&lt;/p>&lt;/blockquote>
&lt;p>&amp;ldquo;Biết&amp;rdquo; ở đây nghĩa là bất kỳ dạng nào sau: câu lệnh &lt;code>import&lt;/code>; dùng kiểu dữ liệu của vòng ngoài trong chữ ký hàm/field; tham chiếu tên hàm, hằng số, biến; &lt;strong>và cả những dạng không có import&lt;/strong>: hiểu ngầm về format JSON của API, về schema bảng, về tên topic Kafka, về mã lỗi HTTP. Dependency Rule cấm tất cả — vòng trong phải có thể compile, test, và &lt;em>đọc hiểu&lt;/em> mà không cần vòng ngoài tồn tại.&lt;/p></description></item><item><title>Chương 2.1 — Vì sao Clean Architecture ra đời</title><link>https://thanhhv.github.io/series/clean-architect/02-clean-architecture-core/01-vi-sao-clean-architecture-ra-doi/</link><pubDate>Tue, 07 Jul 2026 23:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/02-clean-architecture-core/01-vi-sao-clean-architecture-ra-doi/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 2 – Engineering&lt;/strong> · Yêu cầu: đã hoàn thành Level 1.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement-câu-chuyện-lặp-lại-của-mọi-hệ-thống">1. Problem Statement: câu chuyện lặp lại của mọi hệ thống&lt;/h2>
&lt;p>Robert C. Martin công bố bài viết &amp;ldquo;The Clean Architecture&amp;rdquo; năm 2012, đúc kết từ hàng thập kỷ quan sát một vòng đời lặp đi lặp lại:&lt;/p>
&lt;p>&lt;strong>Năm 1:&lt;/strong> team chọn framework hot nhất (Rails/Spring/Django — ngày nay có thể là một &amp;ldquo;boilerplate Gin + GORM&amp;rdquo;). Framework quyết định cấu trúc project. Tốc độ ban đầu tuyệt vời — CRUD sinh ra trong vài giờ.&lt;/p></description></item><item><title>Chương 1.4 — Separation of Concerns &amp; Composition over Inheritance</title><link>https://thanhhv.github.io/series/clean-architect/01-foundation/04-separation-of-concerns/</link><pubDate>Tue, 07 Jul 2026 22:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/01-foundation/04-separation-of-concerns/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 1 – Foundation&lt;/strong> · Hai nguyên lý cuối của phần nền tảng.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="phần-a--separation-of-concerns-soc">Phần A — Separation of Concerns (SoC)&lt;/h2>
&lt;h3 id="1-problem-statement">1. Problem Statement&lt;/h3>
&lt;p>Một hàm handler điển hình trong dự án &amp;ldquo;chạy được là được&amp;rdquo;:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">CreateOrder&lt;/span>(&lt;span style="color:#a6e22e">w&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ResponseWriter&lt;/span>, &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Request&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. Parse JSON (concern: giao thức)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. Validate input (concern: hợp lệ dữ liệu vào)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. Check quyền user (concern: bảo mật)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. Tính giá, áp khuyến mãi (concern: NGHIỆP VỤ)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. Mở transaction, ghi 3 bảng (concern: lưu trữ, nhất quán)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 6. Ghi log, đẩy metric (concern: vận hành)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 7. Render JSON response (concern: giao thức)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Bảy mối quan tâm (concern), bảy tốc độ thay đổi khác nhau, bảy loại chuyên môn khác nhau — trộn trong một hàm. Muốn sửa &lt;strong>một&lt;/strong> concern phải đọc và hiểu &lt;strong>cả bảy&lt;/strong>; muốn test concern 4 phải dựng đủ 1–7. Đây là dạng tổng quát của mọi vấn đề đã nêu ở các chương trước.&lt;/p></description></item><item><title>Chương 1.3 — Dependency Inversion: Cỗ máy đảo chiều phụ thuộc</title><link>https://thanhhv.github.io/series/clean-architect/01-foundation/03-dependency-inversion/</link><pubDate>Tue, 07 Jul 2026 21:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/01-foundation/03-dependency-inversion/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 1–2 Bridge&lt;/strong> · Đây là chương kỹ thuật then chốt. Toàn bộ Clean Architecture đứng trên một cơ chế duy nhất được trình bày ở đây.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;h3 id="bài-toán">Bài toán&lt;/h3>
&lt;p>Business logic là tài sản quý nhất của hệ thống: nó mã hóa cách doanh nghiệp kiếm tiền, nó sống 10 năm trong khi framework HTTP sống 3 năm và fashion database đổi mỗi 5 năm. Vấn đề: &lt;strong>theo cách viết code tự nhiên, thứ quý nhất lại phụ thuộc vào thứ dễ thay đổi nhất.&lt;/strong>&lt;/p></description></item><item><title>Chương 1.2 — SOLID trong Go: Năm quy tắc quản trị phụ thuộc</title><link>https://thanhhv.github.io/series/clean-architect/01-foundation/02-solid/</link><pubDate>Tue, 07 Jul 2026 20:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/01-foundation/02-solid/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 1 – Foundation&lt;/strong> · Yêu cầu: đã đọc &lt;a href="https://thanhhv.github.io/series/clean-architect/01-foundation/01-coupling-cohesion/">Coupling &amp;amp; Cohesion&lt;/a>&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;p>Chương trước kết luận: kiến trúc tốt = coupling thấp + cohesion cao. Nhưng đó là &lt;em>đại lượng đo&lt;/em>, không phải &lt;em>quy tắc hành động&lt;/em>. Khi đứng trước một PR, engineer cần câu trả lời cụ thể: struct này nên tách không? Interface đặt ở đâu? Thêm case vào switch này có ổn không?&lt;/p>
&lt;p>SOLID (Robert C. Martin tổng hợp, đầu những năm 2000) là năm quy tắc hành động trả lời chính xác các câu hỏi đó. &lt;strong>Không có SOLID&lt;/strong>, mỗi engineer quyết định theo cảm tính → codebase thành tập hợp các phong cách mâu thuẫn, review kiến trúc thành tranh cãi ý kiến cá nhân.&lt;/p></description></item><item><title>Chương 1.1 — Coupling &amp; Cohesion: Gốc rễ của mọi vấn đề kiến trúc</title><link>https://thanhhv.github.io/series/clean-architect/01-foundation/01-coupling-cohesion/</link><pubDate>Tue, 07 Jul 2026 19:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/01-foundation/01-coupling-cohesion/</guid><description>&lt;blockquote>
&lt;p>&lt;strong>Level 1 – Foundation&lt;/strong> · Đối tượng: Backend Engineer trở lên
Đây là chương quan trọng nhất của toàn bộ tài liệu. Nếu bạn hiểu sâu coupling và cohesion, mọi pattern phía sau — SOLID, Dependency Rule, Clean Architecture, DDD — chỉ là hệ quả logic.&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="1-problem-statement">1. Problem Statement&lt;/h2>
&lt;h3 id="bài-toán-kinh-doanh">Bài toán kinh doanh&lt;/h3>
&lt;p>Hãy bắt đầu từ một tình huống có thật, không phải từ lý thuyết.&lt;/p>
&lt;p>Một công ty e-commerce có hệ thống đặt hàng viết bằng Go, chạy tốt trong 2 năm đầu. Đến năm thứ 3:&lt;/p></description></item><item><title>Clean Architecture với Golang — Từ First Principles đến Production</title><link>https://thanhhv.github.io/series/clean-architect/00-muc-luc/</link><pubDate>Tue, 07 Jul 2026 18:00:00 +0700</pubDate><guid>https://thanhhv.github.io/series/clean-architect/00-muc-luc/</guid><description>&lt;blockquote>
&lt;p>Tài liệu chuyên sâu dành cho Backend Engineer → Software Architect.
Ngôn ngữ minh họa: Go 1.22+, ưu tiên Standard Library.
Triết lý: &lt;strong>hiểu bản chất và trade-off, không sao chép template.&lt;/strong>&lt;/p>&lt;/blockquote>
&lt;h2 id="cách-đọc">Cách đọc&lt;/h2>
&lt;p>Tài liệu được viết theo chuỗi nhân quả — mỗi chương đứng trên chương trước:&lt;/p>
&lt;pre tabindex="0">&lt;code>Business Problem → Vì sao code khó bảo trì → Coupling → Dependency → SOLID
→ Clean Architecture ra đời → Dependency Rule → Layer → Production
→ Trade-off → Khi nào KHÔNG nên áp dụng
&lt;/code>&lt;/pre>&lt;p>Người mới nên đọc tuần tự. Người có kinh nghiệm có thể nhảy thẳng vào Level 3–4, nhưng nếu thấy một kết luận thiếu căn cứ — căn cứ nằm ở Level 1.&lt;/p></description></item></channel></rss>