DDD: Phần 2 – Giao tiếp và Ngôn ngữ chung trong Domain-Driven Design

Xem lại phần 1: https://minhphien.com/ddd-part-1-phan-tich-mien-nghiep-vu-trong-domain-driven-design/

“Thứ được đưa vào production không phải là tri thức của chuyên gia miền, mà là những gì lập trình viên hiểu (hoặc hiểu sai).”
— Alberto Brandolini

Khi phát triển phần mềm, chúng ta thường nhảy ngay vào viết code, tạo schema, vẽ luồng xử lý. Nhưng nếu bỏ qua bước hiểu thật rõ nghiệp vụ, thì dù hệ thống có đúng về mặt kỹ thuật, nó vẫn có thể sai hoàn toàn về mặt giá trị.

Trong Domain-Driven Design (DDD), giai đoạn khai phá tri thức miền (domain knowledge discovery) là tối quan trọng. Đây là giai đoạn chúng ta “đồng bộ hóa tư duy” giữa chuyên gia miền và kỹ sư phần mềm, đảm bảo phần mềm mô phỏng đúng logic và bối cảnh nghiệp vụ. Trung tâm của giai đoạn này chính là khái niệm “Ngôn ngữ chung” (Ubiquitous Language).

Vấn đề thực sự là “hiểu sai”, không phải “thiếu thông tin”

Một dự án thất bại không phải vì thiếu tính năng, mà vì mọi người hiểu khác nhau về cùng một yêu cầu. Ví dụ, từ “policy” trong một hệ thống bảo hiểm có thể mang nghĩa là “hợp đồng”, nhưng với nhóm khác lại là “quy định”. Nếu không thống nhất, việc mapping các thực thể trong code sẽ rối loạn và dẫn đến lỗi logic trầm trọng.

DDD giải quyết triệt để vấn đề này bằng cách xây dựng một “ngôn ngữ được chia sẻ bởi tất cả các bên”: không chỉ giữa các lập trình viên, mà cả với chuyên gia nghiệp vụ, tester, nhà thiết kế UI/UX, quản lý dự án. Ngôn ngữ này phải bám sát tư duy gốc của nghiệp vụ, tránh dùng biệt ngữ kỹ thuật khiến người không chuyên cảm thấy xa lạ.

Ngôn ngữ chung là gì?

Ngôn ngữ chung là tập hợp các thuật ngữ nghiệp vụ được sử dụng xuyên suốt dự án: từ thảo luận, tài liệu, đến tên lớp, hàm, bảng dữ liệu. Nó không chỉ là “từ vựng” mà còn là mô hình tinh thần của doanh nghiệp, được phản ánh rõ nét trong code.

Một ví dụ điển hình:
Thay vì nói “nếu bảng placements có ít nhất một dòng đang active thì campaign được publish”, hãy nói:
🗣️ “Chiến dịch chỉ được publish khi có ít nhất một điểm hiển thị (placement) đang hoạt động”.
— Câu sau không chỉ dễ hiểu hơn mà còn mang đúng “tâm lý” nghiệp vụ.

Tại sao phải nghiêm túc với ngôn ngữ?

  1. Thống nhất suy nghĩ: Tất cả thành viên dùng cùng một khái niệm cho cùng một thực thể → giảm hiểu lầm.
  2. Gắn kết giữa business và code: Tên class, function, schema phản ánh trực tiếp nghiệp vụ.
  3. Phát hiện sớm các vùng mơ hồ: Khi không ai định nghĩa rõ một từ, đó là dấu hiệu của sự thiếu hiểu về miền.
  4. Tăng khả năng bảo trì: Khi domain thay đổi, ta điều chỉnh code theo cách tự nhiên nhờ vào sự phản ánh trực tiếp của ngôn ngữ.

Làm thế nào để xây dựng ngôn ngữ chung?

1. Trao đổi trực tiếp với chuyên gia miền

Không nên chỉ giao tiếp qua analyst hay PO. Lập trình viên cần nghe tận tai, hỏi tận gốc các logic nghiệp vụ, kể cả các edge case.

2. Đặt câu hỏi ngược lại

Nếu thấy hai từ dùng thay thế nhau như “user” và “account”, hãy hỏi:

“Chúng ta có thể nào có ‘user’ mà không có ‘account’ không?”

→ Chính những câu hỏi như vậy giúp khai thác các phân biệt tinh tế trong nghiệp vụ.

3. Dùng thử và tinh chỉnh

Ngôn ngữ chung không xuất hiện ngay lập tức. Hãy “chơi đùa với từ ngữ” trong workshop, sketch, sơ đồ bảng trắng. Sau mỗi lần thảo luận, chỉnh lại tài liệu và code cho sát với cách diễn đạt mới.

4. Diễn đạt dưới dạng mô hình

Mỗi từ trong ngôn ngữ chung phải có “địa chỉ” rõ ràng trong mô hình: là thực thể, hành vi, hay quy tắc?
Ví dụ:

  • “Đặc tả tuyến đường” → class RoutingSpecification
  • “Đơn hàng bị hủy vì quá hạn xác nhận” → rule trong aggregate Order

Công cụ hỗ trợ

  • Wiki / Glossary: Ghi chú các thuật ngữ và định nghĩa được hai bên thống nhất.
  • Gherkin / BDD test: Viết kiểm thử nghiệp vụ bằng ngôn ngữ tự nhiên, giúp chuyên gia miền xác nhận hành vi hệ thống.
  • Sơ đồ domain (Context Map, Class Diagram): Hỗ trợ trực quan hóa mô hình miền.

Thách thức khi xây dựng ngôn ngữ chung

  • Chuyên gia miền cũng mơ hồ: Nhiều khái niệm “ngầm hiểu” mà chưa từng được đặt tên rõ ràng.
  • Ngôn ngữ cũ đã ăn sâu: Trong dự án kế thừa, các tên bảng, API đã phản ánh mô hình sai lệch. Việc thay đổi cần kiên nhẫn và có chiến lược refactor.
  • Khó duy trì nhất quán: Nếu nhóm thiếu kỷ luật, các thuật ngữ sẽ nhanh chóng bị loãng hoặc biến dị.

Tóm lại

  • Đừng xem thường việc gọi tên đúng trong thiết kế phần mềm.
  • Ngôn ngữ chung là cầu nối giữa nghiệp vụ và kỹ thuật, không thể thiếu trong kiến trúc hướng miền (DDD).
  • Việc xây dựng và duy trì ngôn ngữ này là một nỗ lực tập thể, liên tục và đòi hỏi cam kết từ toàn đội ngũ.

🎓 Tài liệu nên đọc tiếp:

  • Eric Evans – Domain-Driven Design, Chapter 2: Communication and the Use of Language
  • Martin Fowler – Ubiquitous Language
  • Brandolini, Alberto – Introducing EventStorming

2 bình luận cho “DDD: Phần 2 – Giao tiếp và Ngôn ngữ chung trong Domain-Driven Design”

  1. […] Xem phần tiếp theo tại: DDD [Part 2]: Giao tiếp và Ngôn ngữ chung trong Domain-Driven Design […]

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