DDD: Phần 4 – Mô hình hóa tích hợp giữa các Bounded Context trong Domain-Driven Design

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

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

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️⃣CooperationHợp tác chặt chẽ, cùng nhau phát triển
2️⃣Customer–SupplierMột team phụ thuộc vào service của team kia
3️⃣Separate WaysKhô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

PatternMô tả
PartnershipHợp tác 2 chiều linh hoạt
Shared KernelDùng chung mô hình con giữa các context
ConformistDownstream chấp nhận mô hình của upstream
Anticorruption LayerDownstream dịch model của upstream
Open-Host ServiceUpstream cung cấp giao diện tối ưu cho downstream
Separate WaysKhô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

Một bình luận cho “DDD: Phần 4 – Mô hình hóa tích hợp giữa các Bounded Context trong Domain-Driven Design”

  1. […] Xem lại phần 4: DDD [Part 4]: Mô hình hóa tích hợp giữa các Bounded Context trong Domain-Driven Design […]

Để lại một bình luận