Thực hành tốt nhất để tuần tự hóa các tập hợp DDD


23

Theo logic miền DDD không nên bị ô nhiễm với các mối quan tâm kỹ thuật như tuần tự hóa, ánh xạ quan hệ đối tượng, v.v.

Vậy làm thế nào để bạn tuần tự hóa hoặc ánh xạ trạng thái của tập hợp mà không hiển thị công khai thông qua getters và setters? Tôi đã thấy rất nhiều ví dụ cho việc triển khai kho lưu trữ, nhưng thực tế tất cả chúng đều dựa vào các bộ truy cập công cộng trên các thực thể và các đối tượng giá trị để ánh xạ.

Chúng ta có thể sử dụng sự phản chiếu để tránh những người truy cập công cộng, nhưng IMO những đối tượng miền này vẫn hoàn toàn phụ thuộc vào mối quan tâm tuần tự hóa. Ví dụ: bạn không thể đổi tên hoặc xóa trường riêng mà không điều chỉnh cấu hình tuần tự hóa / ánh xạ. Vì vậy, bạn phải xem xét việc tuần tự hóa nơi bạn nên tập trung vào logic miền.

Vì vậy, những thỏa hiệp tốt nhất để làm theo ở đây là gì? Sống với người truy cập công cộng, nhưng tránh sử dụng chúng cho bất cứ điều gì khác ngoài mã bản đồ? Hay tôi chỉ bỏ lỡ một cái gì đó rõ ràng?

Tôi rõ ràng quan tâm đến việc tuần tự hóa trạng thái của các đối tượng miền DDD (tập hợp bao gồm các thực thể và các đối tượng giá trị). Đây KHÔNG phải là về tuần tự hóa trong các kịch bản kịch bản nói chung hoặc chuyển trong đó các dịch vụ phi trạng thái hoạt động trên các đối tượng chứa dữ liệu đơn giản.

Câu trả lời:


12

Các loại đối tượng

Đối với mục đích thảo luận của chúng tôi, hãy tách các đối tượng của chúng tôi thành ba loại khác nhau:

Logic miền kinh doanh

Đây là những đối tượng có được công việc được thực hiện. Họ chuyển tiền từ tài khoản kiểm tra này sang tài khoản khác, thực hiện các đơn đặt hàng và tất cả các hành động khác mà chúng tôi mong đợi phần mềm kinh doanh sẽ thực hiện.

Các đối tượng logic miền thông thường không yêu cầu bộ truy cập (getters và setters). Thay vào đó, bạn tạo đối tượng bằng cách trao các phụ thuộc của nó thông qua một hàm tạo, và sau đó thao tác với đối tượng thông qua các phương thức (nói, đừng hỏi).

Đối tượng truyền dữ liệu

Đối tượng truyền dữ liệu là trạng thái tinh khiết; chúng không chứa bất kỳ logic kinh doanh nào. Họ sẽ luôn có người truy cập. Họ có thể có hoặc không có setters, tùy thuộc vào việc bạn có viết chúng theo cách không thay đổi hay không . Bạn sẽ đặt các trường của mình trong hàm tạo và các giá trị của chúng sẽ không thay đổi trong suốt vòng đời của đối tượng hoặc các bộ truy cập của bạn sẽ được đọc / ghi. Trong thực tế, các đối tượng này thường có thể thay đổi, để người dùng có thể chỉnh sửa chúng.

Xem các đối tượng Model

Xem các đối tượng Mô hình chứa biểu diễn dữ liệu có thể hiển thị / có thể chỉnh sửa. Chúng có thể chứa logic nghiệp vụ, thường được giới hạn để xác thực dữ liệu. Một ví dụ về đối tượng Mô hình xem có thể là InvoiceViewModel, chứa đối tượng Khách hàng, đối tượng Tiêu đề hóa đơn và Mục hàng hóa đơn. Xem các đối tượng Model luôn chứa các bộ truy cập.

Vì vậy, loại đối tượng duy nhất sẽ "thuần túy" theo nghĩa là nó không chứa các bộ truy cập trường sẽ là đối tượng Logic miền. Việc tuần tự hóa một đối tượng như vậy sẽ lưu "trạng thái tính toán" hiện tại của nó để có thể truy xuất nó sau này để xử lý hoàn tất. Mô hình Xem và DTO có thể được tuần tự hóa tự do, nhưng trên thực tế, dữ liệu của họ thường được lưu vào cơ sở dữ liệu.

Nối tiếp, phụ thuộc và khớp nối

Mặc dù sự thật là tuần tự hóa tạo ra sự phụ thuộc, theo nghĩa là bạn phải giải tuần tự hóa thành một đối tượng tương thích, nhưng không nhất thiết phải tuân theo việc bạn phải thay đổi cấu hình tuần tự hóa. Cơ chế tuần tự hóa tốt là mục đích chung; họ không quan tâm nếu bạn thay đổi tên của một tài sản hoặc thành viên, miễn là nó vẫn có thể ánh xạ các giá trị cho các thành viên. Trong thực tế, điều này chỉ có nghĩa là bạn phải tuần tự hóa lại thể hiện đối tượng để làm cho biểu diễn tuần tự hóa (xml, json, bất cứ thứ gì) tương thích với đối tượng mới của bạn; không cần thay đổi cấu hình cho serializer.

Đúng là các đối tượng không nên quan tâm đến cách chúng được nối tiếp. Bạn đã mô tả một cách những mối quan tâm như vậy có thể được tách rời khỏi các lớp miền: sự phản chiếu. Nhưng trình tuần tự hóa nên được quan tâm về cách nó tuần tự hóa và giải tuần tự hóa các đối tượng; Rốt cuộc, đó là chức năng của nó. Cách bạn giữ cho các đối tượng của bạn tách rời khỏi quy trình tuần tự hóa của bạn là làm cho việc tuần tự hóa thành một chức năng có mục đích chung , có thể hoạt động trên tất cả các loại đối tượng.

Một trong những điều mọi người bị nhầm lẫn là việc tách rời phải xảy ra theo cả hai hướng. Nó không; nó chỉ phải làm việc theo một hướng. Trong thực tế, bạn không bao giờ có thể tách rời hoàn toàn; luôn luôn có một số khớp nối. Mục tiêu của khớp nối lỏng lẻo là làm cho việc bảo trì mã dễ dàng hơn, không phải loại bỏ tất cả các phụ thuộc.


Tôi đồng ý với quan điểm của bạn về việc tách rời. Bộ nối tiếp phụ thuộc vào đối tượng miền và điều đó ổn. Nhưng không phải là cách khác. Tuy nhiên, tôi không đồng ý với quan điểm của bạn về người truy cập công khai trên các đối tượng miền. Trong thực tế họ thường có chúng, vâng. Nhưng IMO sẽ tốt hơn nếu triển khai logic miền trong thiết kế hướng đối tượng rõ ràng: Nói, đừng hỏi . Nhưng bạn vẫn cần người truy cập cho mục đích ánh xạ (ORM, tuần tự hóa, GUI ...). Và đó là điều tôi muốn tránh, nếu có thể.
EagleBeak

Làm thế nào để bạn có kế hoạch truy cập vào các lĩnh vực của bạn, nếu bạn không có người truy cập?
Robert Harvey

Trên thực tế, tôi không đề cập đến cả ba loại đối tượng mà bạn mô tả, mà là "tổng hợp" trong thuật ngữ DDD và các đối tượng phụ của chúng (đối tượng, đối tượng giá trị). Bây giờ tôi nhận ra rằng câu hỏi của tôi không đủ rõ ràng về vấn đề này. Lấy làm tiếc! Xin vui lòng xem chỉnh sửa của tôi ở trên.
EagleBeak

1
Về cơ bản, đây không phải là vấn đề chưa được giải quyết - bạn không thể đóng gói, tách rời và tuần tự hóa \ mã hóa đồng thời phơi bày DTO, là một cách để đạt được thỏa hiệp. Tuy nhiên, có nhiều cách ít xâm phạm hơn: yegor256.com/2016/07/06/data-transfer-object.html
Basilevs

1
Điều đó làm giảm việc đóng gói, bất kỳ ai cũng có thể thực hiện hoặc sử dụng lớp bạn bè để đọc nội bộ của đối tượng ,.
Basilevs

-1

Mục đích cơ bản của việc tuần tự hóa là để đảm bảo rằng dữ liệu được tạo ra bởi một hệ thống có thể được tiêu thụ bởi một hoặc nhiều hệ thống tương thích.

Cách tiếp cận đơn giản và mạnh mẽ nhất để tuần tự hóa là dịch dữ liệu sang định dạng bất khả tri loại duy trì cấu trúc theo định dạng đơn giản và dễ tiêu thụ. Ví dụ, các định dạng tuần tự hóa phổ biến nhất (ví dụ JSON, XML) sử dụng định dạng dựa trên văn bản được xác định rõ. Văn bản là đơn giản để sản xuất, truyền tải và tiêu thụ.

Có 2 lý do tại sao sử dụng một trong những định dạng này có thể không lý tưởng.

  1. Hiệu quả

    Có một chi phí cố hữu liên quan đến việc dịch tất cả các dữ liệu thành tương đương dựa trên văn bản của họ. Các kiểu dữ liệu sẽ không tồn tại nếu văn bản là cách hiệu quả nhất để thể hiện tất cả các dạng dữ liệu khác nhau. Ngoài ra, cấu trúc của các định dạng này không lý tưởng để truy xuất các tập hợp con dữ liệu không đồng bộ hoặc theo từng phần.

    Chẳng hạn, XML và JSON cho rằng dữ liệu đang được sử dụng sẽ được ghi và đọc từ đầu đến cuối. Để xử lý các tập dữ liệu rất lớn nơi bộ nhớ khan hiếm, hệ thống tiêu thụ dữ liệu có thể yêu cầu khả năng xử lý dữ liệu theo từng phần. Trong trường hợp đó, việc thực hiện tuần tự hóa / giải tuần tự mục đích đặc biệt có thể được yêu cầu để xử lý dữ liệu.

  2. Độ chính xác

    Việc truyền được yêu cầu để tuần tự hóa / giải tuần tự hóa dữ liệu từ loại dự định sang loại không biết dữ liệu dẫn đến mất độ chính xác.

Người ta có thể lập luận rằng việc tạo ra một biểu diễn nhị phân của các đối tượng và dữ liệu rõ ràng là giải pháp chính xác và hiệu quả nhất. Hạn chế lớn là việc triển khai tất cả các hệ thống vừa tiêu thụ vừa sản xuất dữ liệu cần phải tương thích. Đó là một hạn chế đơn giản trong lý thuyết nhưng đó là một cơn ác mộng để duy trì trong thực tế khi các hệ thống sản xuất có xu hướng thay đổi / phát triển theo thời gian.

Với những gì đã nói. Việc tách rời tuần tự hóa / giải tuần tự hóa từ các chi tiết cụ thể theo miền có ý nghĩa như một quy tắc chung vì các định dạng mục đích chung mạnh mẽ hơn, được hỗ trợ tốt hơn trên các hệ thống khác nhau và yêu cầu sử dụng ít chi phí bảo trì.


Xin lỗi, nhưng điều này không trả lời câu hỏi của tôi. Đó là về việc tách các đối tượng miền khỏi việc xê-ri hóa, không phải về lý do của việc xê-ri hóa hay ưu và nhược điểm của các định dạng khác nhau. Làm cách nào để tôi tuần tự hóa các đối tượng miền mà không công khai trạng thái riêng tư của chúng?
EagleBeak

@EagleBeak Ồ, tôi không nhận ra mối quan tâm của bạn là cụ thể về việc xử lý các thành viên tư nhân. Trong trường hợp của bạn, bạn có thể tuần tự hóa nhị phân (giả sử hệ thống nhận tuân theo các quy tắc / cấu trúc tương tự mà các đối tượng miền được tạo bên dưới) hoặc viết một số logic chỉ trích xuất dữ liệu công khai trước khi tuần tự hóa.
Evan Plaice

Tôi nghĩ rằng giả định 'thông thường' là dữ liệu được tuần tự hóa thành định dạng mục đích chung (ví dụ xml, json) sẽ được công khai và đặc quyền đó được kiểm soát thông qua API thông qua ACL hoặc một số tương đương khác. Tuần tự hóa / giải tuần tự hóa mục đích chung rơi nhiều hơn vào các dòng dữ liệu tách rời từ logic kinh doanh đi từ hệ thống này sang hệ thống khác.
Evan Plaice

Tôi đồng ý về các bộ truy cập công cộng thường được giả định trên các đối tượng sẽ được nối tiếp. Nhưng tôi vẫn muốn biết thêm về việc điều này liên quan đến DDD như thế nào và sự tập trung mạnh mẽ của nó vào việc đóng gói logic miền. Có phải tất cả các học viên DDD chỉ phơi bày trạng thái của mô hình miền thông qua các bộ truy cập công cộng để tuần tự hóa (và không bao giờ đề cập đến nó trong các ví dụ của họ)? Tôi nghi ngờ điều đó. Xin đừng hiểu lầm tôi. Tôi đánh giá cao đầu vào của bạn rất nhiều. Chỉ là tôi quan tâm đến một khía cạnh khác. (Cho đến nay tôi không nghĩ câu hỏi của mình quá mơ hồ, nhưng câu trả lời của Robert Harvey và của bạn đã khiến tôi suy nghĩ về điều đó ..)
EagleBeak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.