Link Search Menu Expand Document

Domain-Driven Design

Table of contents

  1. Giới thiệu
  2. Khái niệm
  3. Kiến trúc
    1. Domain Layer
    2. Application Layer
    3. Infrastructure Layer

Giới thiệu

Domain-Driven Design là một phương pháp tiếp cận trong việc phân tích và phát triển phần mềm khi giải quyết những vấn đề nghiệp vụ phức tạp. Ý tưởng cơ bản của phương pháp này là việc xây dựng sự kết nối chặt chẽ giữa thiết kế phần mềm và mô hình nghiệp vụ trong suốt vòng đời phát triển sản phẩm. Để tạo nên sự kết nối này, DDD đưa ra 3 yêu cầu cơ bản:

  • Trọng tâm của dự án là những nguyên tắc và logic nghiệp vụ
  • Thiết kế phần mềm cần phải phản ánh chính xác mô hình nghiệp vụ
  • Sự cộng tác liên tục giữa kĩ sư và chuyên gia nghiệp vụ

Kết quả của việc phân tích hệ thống dựa trên phương pháp DDD, kết hợp cùng mô hình kiến trúc Microservices giúp chúng ta tổ chức và phát triển những microservices giải quyết các vấn đề nghiệp vụ một cách tương ứng. Hoạt động kết hợp này được phản ánh qua một qui trình bao gồm các bước:

  • Phân tích nghiệp vụ - domain model
  • Định nghĩa ngữ cảnh - bounded context
  • Định nghĩa đối tượng (entities), tập hợp (aggregate) và dịch vụ (service)
  • Xác định microservices cần xây dựng

Journey Ouput

Khái niệm

DDD được tác giả Eric Evan đề xuất vào vào năm 2003 trong một quyển sách phần mềm nổi tiếng “Domain Driven Design - Tackling complexity in the heart of software”. Phương pháp này nhanh chóng nhận được sự đón nhận, phát triển từ cộng động và được áp dụng sâu rộng trong qui trình phát triển phần mềm ngày nay.

Để giới thiệu các khái niệm cơ bản trong DDD, chúng ta lấy ví dụ về phát triển hệ thống quản lý vận tải theo mô hình Uber. Trong quá trình thiết kế và xây dựng hệ thống, những kĩ sư phần mềm phối hợp chặt chẽ với những chuyên gia nghiệp vụ - domain experts. Việc trao đổi thông tin giữa những thành viên này cần dựa trên một ngôn ngữ mô tả chính xác các thuật ngữ, vấn đề hoặc qui trình cần giải quyết - ubiqitous language.

Quá trình cộng tác liên tục tạo nên một mô hình nghiệp vụ - domain model - một hình thức trừu tượng hoá từ mô hình kinh doanh doanh nghiệp - business domain. Khi nghiệp vụ phức tạp, mô hình này tiếp tục được phân chia thành nhiều thành phần nghiệp vụ nhỏ hơn, bao gồm:

  • Core Domains - nghiệp vụ cốt lõi, cơ bản nhất.
  • Sub Domains - nghiệp vụ có tính chất phụ trợ

Điểm quan trọng của việc chia tách này là tạo ra được những phạm vi ngữ cảnh - bounded context, giúp xác định rõ ranh giới giữa các nghiệp vụ, đồng thời thể hiện được chính xác ý nghĩa của những thực thể - entity trong mỗi phạm vi đó.

Trong ví dụ về hệ thống quản lý vận tải, chúng ta có những thành phần nghiệp vụ:

  • Khách hàng - Customer [Core]
  • Tài xế - Driver [Core]
  • Vận chuyển - Trip Management [Core]
  • Thanh toán - Payment
  • Hoá đơn - Invoice
  • Trợ giúp khách hàng - Call Center
  • Bản đồ - Location
  • Khuyến mại, marketing - Loyalty
  • Báo cáo sự cố - Reporting

Các thực thể trong ngữ cảnh Trip Management:

  • Chuyến đi - Trip
  • Đánh giá chất lượng phục vụ - Rating

Uber Ouput

Việc phân chia phạm vi các ngữ cảnh cũng giúp giảm thiểu sự phức tạp không cần thiết khi mô hình hoá các thực thể trong thực tế.

Ví dụ về đối tượng người dùng: trong ngữ cảnh khách hàng, hệ thống cần lưu lại rất nhiều thông tin về khách hàng, bao gồm dữ liệu cá nhân, lịch sử chuyến đi. Tuy nhiên, trong ngữ cảnh vận chuyển, chúng ta chỉ cần quan tâm đến khách hàng với những thông tin căn bản như tên tuổi, số điện thoại liên lạc, tuyến đường yêu cầu.

Trong một số trường hợp, các entities không tồn tại độc lập và có vòng đời phụ thuộc vào một tập hợp - aggregate. Ví dụ khi việc đánh giá chất lượng phục vụ luôn phụ thuộc vào một chuyến đi, và trong trường hợp này thực thể biễu diễn mỗi chuyến đi được gọi là root entity.

Entity được định nghĩa là các đối tượng mang dữ liệu với khả năng định danh duy nhất. Bên cạnh Entity, chúng ta cũng sử dụng khái niệm value object để định nghĩa các đối tượng chứa dữ liệu đơn thuần. Ví dụ, trong ngữ cảnh Invoice, hoá đơn là những thực thể chứa giá trị identity giúp chúng ta có sự phân biệt về tính duy nhất. Mỗi hoá đơn cũng bao gồm đối tượng - value object chứa thông tin về thời gian đi, quãng đường. Những đối tượng này chỉ chứa giá trị thông tin đơn thuần và không cần mang tính chất duy nhất.

Trong phát triển phần mềm, có nhiều công nghệ cơ sở dữ liệu khác nhau để lưu trữ những đối tượng entity hay aggregate. Tuy nhiên, việc truy cập các đối tượng thông tin này thường được “đóng gói” qua một lớp trung gian - repository. Việc đóng gói này giảm tính sự phụ thuộc của mô hình nghiệp vụ vào công nghệ lưu trữ, và nâng cao khả năng nâng cấp, thay thế công nghệ khi cần thiết.

Bên cạnh các loại hình đối tượng liên quan đến dữ liệu và truy cập, chúng ta cũng có thêm một khái niệm khác về services. Services là những qui trình hoạt động nghiệp vụ, chính sách doanh nghiệp etc…liên quan đến nhiều đối tượng khác nhau. Vì ý nghĩa đó, các đối tượng service có tính chất stateless - các hoạt động service thực thi và không lưu giữ lại bất kì trạng thái nào.

Với ngữ cảnh Invoice trong ví dụ trên:

  • Entity Invoice được truy vấn qua repository IInvoiceRepository
  • PaymentService cung cấp phương thức thanh toán, sử dụng IInvoiceRepository để tạo ra hoá đơn khi việc thanh toán thành công

Domain Ouput

Kiến trúc

Sau khi phân tách các phạm vi ngữ cảnh, xác định các đối tượng nghiệp vụ bên trong chúng, bước tiếp theo là việc định nghĩa và xây dựng những microservices tương ứng.

Dựa trên nguyên tắc của phương pháp DDD, để tập trung vào việc xây dựng mô hình nghiệp vụ đồng thời giảm thiểu sự phụ thuộc đối với những thành phần khác của ứng dụng, mỗi services được chia thành nhiều lớp -layers.

Tác giả Eric Evan đề xuất kiến trúc multi-layers bao gồm:

  • Domain Layer
  • Application Layer
  • Infrastructure Layer

Domain Layer

Là thành phần quan trọng nhất trong kiến trúc bởi việc đóng gói các qui tắc và mô hình nghiệp vụ. Tầng nghiệp vụ này có các đặc điểm:

  • Biểu diễn mô hình nghiệp vụ qua entities dưới hình thức các lớp POJO [*]
  • Kiểm soát và thể hiện trạng thái hoạt động nghiệp vụ
  • Sử dụng Domain Event để thông báo cho các module khác khi một sự kiện xảy ra.
  • Hoạt động độc lập với tầng lưu trữ vật lý, không phụ thuộc trực tiếp ORM framework.

Định nghĩa

POJO (Plain Old Java Object) là thuật ngữ để chỉ các lớp đối tượng mang ý nghĩa logic đơn thuần, không ràng buộc vào ngôn ngữ hay framework cụ thể.

Application Layer

Chức năng chính của tầng này là quản lý các tác vụ yêu cầu từ bên ngoài và chuyển giao - delegate các thực thi nghiệp vụ xuống tầng Domain. Với ý nghĩa đó, tầng ứng dụng có khả năng:

  • Presentation interface - cung cấp chức năng ứng cho phía client
  • Application interface - giao tiếp ứng dụng với những services khác

Infrastructure Layer

Infrastructure layer làm việc trực tiếp với hạ tầng công nghệ của hệ thống phần mềm. Các chức năng chính của tầng này bao gồm:

  • Truy vấn, thay đổi thông tin trong cơ sở dữ liệu
  • Quản lý dữ liệu trên vùng nhớ tạm thời (cache data)
  • Bảo mật, giám sát, lưu trữ thông tin hoạt động (log, monitor)

Architecture layers Ouput


Tài liệu tham khảo


Copyright © 2019-2022 Tuan Anh Le.