Xem lại phần 3: DDD [Part 3]: Quản lý Domain Complexity: Khám phá Sức mạnh của Bounded Context trong Thiết kế phần mềm
🧠 Domain có 2 mặt: Problem Space vs Solution Space
🔍 Problem Space là gì?
- Là Core Domain + các Subdomain hỗ trợ nó
- Dùng để khám phá một vấn đề chiến lược cụ thể
- Subdomain giúp phân chia domain để hiểu và đánh giá chính xác phạm vi cần giải quyết
🛠️ Solution Space là gì?
- Gồm các Bounded Context, mỗi context ứng với một giải pháp phần mềm cụ thể
- Trong ideal case: mỗi Subdomain → 1 Bounded Context
- Nhưng trong thực tế (brownfield system) thì Subdomain và Context thường chồng lấn lộn xộn
Bounded Context & Mô hình
📌 Bounded Context không chỉ giúp bảo vệ tính nhất quán của Ubiquitous Language, mà còn cho phép mô hình hóa (modeling).
- Bạn không thể xây dựng mô hình nếu không xác định boundary – tức phạm vi chịu trách nhiệm.
- Mỗi Bounded Context có thể mô hình hóa cùng một thực thể trong business, nhưng với mục đích và cách giải quyết khác nhau.
Tính độc lập và liên kết của các Bounded Context
📌 Dù các bounded context có thể phát triển độc lập, chúng không hoàn toàn tách biệt.
- Chúng phải tích hợp để đạt được mục tiêu chung.
- Vì thế, luôn tồn tại các touchpoint – được gọi là contracts.
🧩 Contracts cần được xác định và phối hợp, vì:
- Mỗi bounded context sử dụng ubiquitous language riêng
- Phải lựa chọn ngôn ngữ tích hợp (integration language) phù hợp
📦 Ví dụ: ERP System và mô hình mua hàng tối ưu
- ERP system là hệ thống đơn lẻ (monolith) → có thể xem như 1 Bounded Context lớn
- Có thể chia logic trong ERP thành các Subdomain:
Inventory
,Purchasing
- Dự án mới: xây dựng Core Domain tên là Optimal Acquisitions (quyết định mua hàng tối ưu):
- Dùng các thuật toán ra quyết định từ kinh nghiệm cũ
- Phải tách biệt với ERP để không bị rối bởi mô hình cũ
🌐 Các Bounded Context xuất hiện:
Optimal Acquisitions Context
→ Core Domain → cần mô hình riêng, ngôn ngữ riêngPurchasing Context
→ hỗ trợ tương tác giữa Optimal Acquisitions và ERPInventory Context
→ quản lý kho, hỗ trợ hiển thị bản đồ kho hàng qua dịch vụ bản đồ ngoài
Ba nhóm mô hình tích hợp giữa bounded contexts
Chia theo mức độ collaboration giữa teams phát triển:
🔢 STT | 🤝 Hình thức hợp tác | 💬 Mô tả |
---|---|---|
1️⃣ | Cooperation | Hợp tác chặt chẽ, cùng nhau phát triển |
2️⃣ | Customer–Supplier | Một team phụ thuộc vào service của team kia |
3️⃣ | Separate Ways | Không hợp tác, tách rời hoàn toàn |
🤝 Nhóm 1: Cooperation – Hợp tác
📌 Các bounded contexts được phát triển bởi cùng 1 team hoặc các team có giao tiếp hiệu quả.
🧩 Pattern 1: Partnership
- Tích hợp kiểu ad hoc, thông báo & điều chỉnh linh hoạt.
- Không team nào áp đặt ngôn ngữ tích hợp.
- Cần:
- Đồng bộ thường xuyên
- Continuous Integration (CI)
- Hạn chế nếu teams phân bố địa lý xa

📌 Hình ảnh mô tả: Figure 4-1: The partnership model
🧩 Pattern 2: Shared Kernel
📌 Một phần mô hình (subdomain) được chia sẻ giữa nhiều bounded contexts.
- Mô hình dùng chung phải phù hợp với tất cả các bên.
- Mọi thay đổi phải được propagate ngay lập tức → tránh stale version.
Ví dụ: Hệ thống phân quyền người dùng dùng chung mô hình:
- Người dùng có quyền trực tiếp hoặc kế thừa từ đơn vị tổ chức.
- Thay đổi từ bất kỳ context nào đều ảnh hưởng đến toàn bộ hệ thống.

Figure 4-2: Shared kernel
📌 Triển khai kỹ thuật:
- Mono-repo: nhiều context dùng chung source
- Multi-repo: dùng linked library
- Mỗi thay đổi phải kích hoạt integration tests trên tất cả contexts liên quan
📌 Khi nào dùng:
- Khi cost của duplication > cost của coordination
- Phù hợp với core subdomain có tần suất thay đổi cao
- Phù hợp khi không thể áp dụng partnership vì giới hạn địa lý hoặc chính trị nội bộ
- Có thể dùng như giải pháp trung gian để modernize legacy system
🧠 Cảnh báo: Nếu shared kernel được phát triển bởi nhiều team → vi phạm nguyên tắc ownership độc lập của bounded context.
💼 Nhóm 2: Customer–Supplier
📌 Một context là consumer, một context là supplier cung cấp dịch vụ.
🧩 Pattern 3: Conformist
- Consumer tuân theo mô hình của supplier
- Xảy ra khi upstream không hỗ trợ downstream

📌 Hình ảnh mô tả: Figure 4-4: Conformist relationship
📌 Khi áp dụng:
- Hợp lý nếu upstream là chuẩn ngành, hoặc downstream không cần mô hình riêng
🧩 Pattern 4: Anticorruption Layer (ACL)
- Consumer không chấp nhận model của upstream
- Dùng ACL để dịch mô hình supplier thành mô hình riêng

📌 Hình ảnh mô tả: Figure 4-5: Integration through an anticorruption layer
📌 Khi áp dụng:
- Core subdomain cần kiểm soát model chặt chẽ
- Upstream là hệ thống legacy, kém hiệu quả
- Upstream thay đổi liên tục → dùng ACL để bảo vệ downstream
📌 Lợi ích:
- Isolate downstream khỏi foreign concepts
- Đơn giản hóa ubiquitous language của downstream
🧩 Pattern 5: Open-Host Service
- Upstream chủ động hỗ trợ consumers bằng cách cung cấp published language

Figure 4-6: Integration through an open-host service

Figure 4-7: Multiple versions of published language
📌 Ưu điểm:
- Decouple implementation model & public interface
- Cho phép versioning giao diện → consumers nâng cấp dần
❌ Nhóm 3: Separate Ways – Tách rời hoàn toàn
📌 Không tích hợp do các lý do sau:
🚫 Communication Issues:
- Chính trị nội bộ hoặc teams quá lớn khiến việc phối hợp kém hiệu quả
🚫 Generic Subdomains:
- Subdomain chung, dễ tích hợp độc lập (e.g., logging)
→ Việc chia sẻ phức tạp hơn lợi ích thu được
🚫 Model Differences:
- Mô hình khác biệt quá lớn → không thể conform hoặc dùng ACL
🧠 Lưu ý: Không nên áp dụng pattern này với core subdomain, vì việc nhân bản sẽ phá vỡ chiến lược tối ưu hóa.
🗺 Context Map
📌 Context Map = sơ đồ mô tả hệ thống & các bounded contexts, tích hợp qua patterns:
📌 Chức năng:
- Cung cấp cái nhìn chiến lược tổng thể
- Hiển thị các communication pattern giữa teams
- Phát hiện vấn đề tổ chức nội bộ
- Cần được duy trì thường xuyên như 1 phần của codebase
🛠 Công cụ đề xuất: Context Mapper
📌 Hình ảnh minh họa:

Figure 4-8: Context map

Figure 4-9: Complicated context map (multiple patterns in 1 relationship)
✅ Tổng kết các Integration Patterns
Pattern | Mô tả |
---|---|
Partnership | Hợp tác 2 chiều linh hoạt |
Shared Kernel | Dùng chung mô hình con giữa các context |
Conformist | Downstream chấp nhận mô hình của upstream |
Anticorruption Layer | Downstream dịch model của upstream |
Open-Host Service | Upstream cung cấp giao diện tối ưu cho downstream |
Separate Ways | Không tích hợp – mỗi bên phát triển riêng |
📝 Exercises (Câu hỏi ôn tập)
1. Pattern nào không nên áp dụng cho core subdomain?
2. Subdomain nào dễ áp dụng ACL nhất?
3. Subdomain nào phù hợp để làm Open-Host Service?
4. Pattern nào có thể vi phạm ownership của bounded context?
Xem tiếp phần 5: DDD [Part 5]: Transaction Script & Active Record – 2 patterns để giải quyết business logic đơn giản
Để lại một bình luận
Bạn phải đăng nhập để gửi bình luận.