Thiết kế hướng tên miền và tương tác tên miền chéo


10

Tôi là một người mới chơi DDD tương đối, nhưng tôi đang đọc bất cứ thứ gì và mọi thứ tôi có thể có được để đun sôi và chắt lọc kiến ​​thức của tôi.

Tôi đã xem qua câu hỏi DDD này và một trong những câu trả lời khiến tôi tò mò.

DDD Bounded Bối cảnh & Tên miền?

Trong một trong những câu trả lời, người đăng tải đưa ra ví dụ về hệ thống thương mại điện tử với các sản phẩm có ít nhất 2 tên miền:

1) Danh mục sản phẩm 2) Quản lý hàng tồn kho

OK, tất cả đều có ý nghĩa, tức là trong giao diện thương mại điện tử của bạn, bạn quan tâm đến việc hiển thị thông tin sản phẩm và không quan tâm đến việc quản lý hàng tồn kho.

NHƯNG. Bạn có thể muốn hiển thị mức tồn kho trên trang web hoặc bạn có thể muốn hiển thị số phiên bản của kho trong kho (hãy tưởng tượng kho của bạn là sách, tạp chí, v.v.). Thông tin này đến từ miền Hàng tồn kho.

Vì vậy, làm thế nào bạn sẽ xử lý này? Bạn sẽ

a) Tải cả miền Sản phẩm và miền Tổng kho? b) Bạn có giữ một số thuộc tính trên thực thể miền Sản phẩm của mình để lấy số trong kho và phiên bản trong kho, sau đó sử dụng Sự kiện Miền để cập nhật các thuộc tính này khi thực thể Hàng tồn kho được cập nhật không?

Một câu hỏi cuối cùng. Tôi biết chúng ta có nghĩa là quên / bỏ qua sự tồn tại của tên miền và chỉ nghĩ về tên miền. Nhưng chỉ cần nghĩ đến điều này, trong ví dụ trên, chúng ta sẽ có 2 bảng DB tiềm năng cho danh mục sản phẩm và hàng tồn kho sản phẩm. Bây giờ, chúng ta có sử dụng cùng một mã định danh trong đó là cùng một sản phẩm không. Hoặc, chúng ta có thể sử dụng 1 bảng và 1 hàng bảng cho dữ liệu và chỉ cần ánh xạ dữ liệu có liên quan lên các thuộc tính tổng hợp không?

Câu trả lời:


8

Bạn có thể muốn hiển thị mức tồn kho trên trang web hoặc bạn có thể muốn hiển thị số phiên bản của kho trong kho (hãy tưởng tượng kho của bạn là sách, tạp chí, v.v.). Thông tin này đến từ miền Hàng tồn kho.

Điều chính cần chú ý ở điểm này là bạn đang nói về một quan điểm, nghĩa là sử dụng dữ liệu cũ là chấp nhận được.

Điều đó đang được nói, bạn không cần phải tương tác với các tập hợp (chịu trách nhiệm ngăn chặn các thay đổi vi phạm bất biến kinh doanh), nhưng với sự thể hiện của một bản sao gần đây của trạng thái tổng hợp.

Vì vậy, những gì tôi thường mong đợi là một truy vấn chạy đối với Danh mục sản phẩm và một truy vấn khác đối với Kho lưu trữ và một cái gì đó để kết hợp cả hai vào DTO mà bạn cần để hỗ trợ chế độ xem.

Tải cả miền Sản phẩm và miền Tổng hợp hàng tồn kho?

Vì vậy, gần như vậy . Chúng tôi không cần tải tổng hợp, vì chúng tôi sẽ không thay đổi bất cứ điều gì. Nhưng chúng ta cần nhà nước của họ; vì vậy chúng tôi có thể tải nó. Điều đó nói rằng, tôi thường mong đợi hai tên miền sẽ chạy trong các quy trình khác nhau. Do đó, chúng tôi sẽ gọi cả hai, không tải cả hai.

Bạn có giữ một số thuộc tính trên thực thể miền Sản phẩm của mình để lấy số trong kho và phiên bản trong kho, sau đó sử dụng Sự kiện Miền để cập nhật các thuộc tính này khi thực thể Hàng tồn kho được cập nhật không?

"Đừng băng qua suối. Nó sẽ rất tệ."

Sử dụng các sự kiện để phối hợp thông tin trên các bối cảnh tên miền: ý tưởng tuyệt vời . Đẩy các khái niệm thuộc về một lĩnh vực này sang một lĩnh vực khác: ngược lại với một ý tưởng tuyệt vời, ngoại trừ nhiều hơn thế.

Bạn muốn giữ cho tên miền sạch sẽ. Các ứng dụng tương tác với các miền, nó không quá quan trọng. Vì vậy, ví dụ, ứng dụng Inventory gọi một dịch vụ trong ứng dụng sản phẩm là truy vấn một số khái niệm cụ thể của sản phẩm để thêm vào chế độ xem. Hoặc ngược lại.

Tôi không biết bất kỳ lý do nào mà một ứng dụng cần phải được giới hạn trong một tên miền. Miễn là có một nguồn sự thật duy nhất, bạn có thể phân phối các giao dịch theo bất kỳ cách nào bạn muốn.

Nhưng chỉ cần nghĩ đến điều này, trong ví dụ trên, chúng ta sẽ có 2 bảng DB tiềm năng cho danh mục sản phẩm và hàng tồn kho sản phẩm. Bây giờ, chúng ta có sử dụng cùng một mã định danh trong đó là cùng một sản phẩm không.

Đó sẽ là cách dễ dàng. Theo nghĩa lớn hơn, bạn sử dụng cùng một mã định danh vì thực thể trong thế giới thực là như nhau; hai bối cảnh giới hạn khác nhau mô hình thực thể khác nhau, nhưng mô hình không phải là thực thể thế giới thực.

Khi điều đó không hoạt động, sau đó bạn sẽ cần một số truy vấn để sử dụng để thu hẹp khoảng cách. Tôi nghĩ rằng biến thể phổ biến nhất của điều này là thực thể mới hơn bảo tồn id của thực thể cũ hơn. Bạn cũng sẽ thấy điều này trong một BC duy nhất: ứng viên, khi được chấp thuận, sẽ trở thành khách hàng. Đó là một tổng hợp khác nhau (trạng thái liên quan đến khách hàng phải chịu một bất biến khác với trạng thái của người nộp đơn); vì vậy nếu lớp kiên trì của bạn đang sử dụng các luồng sự kiện, luồng cho tổng hợp mới sẽ cần một mã định danh khác. Vì vậy, sẽ có một chút trạng thái ở đâu đó nói rằng "ứng viên này đã trở thành khách hàng này".

Hoặc, chúng ta có thể sử dụng 1 bảng và 1 hàng bảng cho dữ liệu và chỉ cần ánh xạ dữ liệu có liên quan lên các thuộc tính tổng hợp không?

YIKES! Không, đừng làm vậy. Bạn đang thêm tranh chấp giao dịch mà không có bất kỳ lý do kinh doanh nào để làm như vậy.


Tôi đã đánh dấu đây là câu trả lời, tín dụng cho @guillaume bên dưới, người cũng chỉ ra rằng việc đọc dữ liệu để hiển thị trong chế độ xem không yêu cầu tải lên các tổng hợp. Cảm ơn cho một câu trả lời chi tiết dài. Xuất phát từ cách tiếp cận mô hình dữ liệu "truyền thống" đầu tiên, tôi thấy khó khăn khi buộc bản thân phải quên đi lớp kiên trì và tập trung vào ngôn ngữ miền. Chỉ khi tôi nghĩ rằng tôi đã có nó, tôi đã đọc một bài viết khác làm tôi hiểu hơn.
PendorPaul

Tôi vừa đọc bài viết này msdn.microsoft.com/en-us/magazine/dn802601.aspx có chi tiết sử dụng Sự kiện Miền để sao chép một số dữ liệu giữa các bối cảnh. Ví dụ đang chia sẻ danh sách khách hàng giữa dịch vụ khách hàng và hệ thống xử lý đơn hàng. Đây là sao chép dữ liệu khách hàng trong hệ thống đặt hàng và sử dụng Sự kiện để đồng bộ hóa dữ liệu. Con ruồi này đối mặt với những gì chúng tôi đã trả lời ở đây. Chắc chắn trong mẫu được liên kết, bối cảnh đơn hàng chỉ cần có ID khách hàng và có thể được điền từ ứng dụng có quyền truy cập vào bối cảnh dịch vụ khách hàng.
PendorPaul

Bạn sẽ muốn rất chính xác trong suy nghĩ của bạn, ở đây. Sao chép dữ liệu giữa các hệ thống KHÔNG giống như sao chép dữ liệu giữa các mô hình miền. Bất cứ khi nào bạn thấy "chỉ đọc [lầm bầm]", đó là một gợi ý lớn rằng dữ liệu không thuộc về miền đó (ngay cả khi ứng dụng vẫn có thể quan tâm đến nó).
VoiceOfUnreason

Vâng, đó là những gì tôi nghĩ quá. Sự thay đổi quá trình suy nghĩ là đủ khó khăn nếu không có "chuyên gia" xuất bản các bài báo làm vẩn đục nước. Tôi đã dành ngày hôm nay để thực sự phân tích tên miền của mình, để thử và thực sự hiểu đầy đủ về Rễ BC và Tổng hợp của tôi nằm ở đâu. Tôi có khá nhiều ở đó, nhưng tôi cũng biết tôi có thể tinh chỉnh và cấu trúc lại mô hình của mình khi tôi đi. Tôi đã bị mắc kẹt trong phân tích quá nhiều ngày nay, lo lắng để bắt đầu viết mã sợ rằng tôi không có DDD trong đầu. Tôi nghĩ rằng tốt nhất là nên bẻ khóa và tiếp tục đặt câu hỏi về mã của tôi và liệu mô hình đó có đúng không. Tôi sẽ đến đó. Cảm ơn
PendorPaul

Có thể tôi đã đọc sai, nhưng thực tế tôi tin rằng bạn đang nói đến được gọi là Chuyển trạng thái được tổ chức sự kiện (Chuyển trạng thái được tổ chức sự kiện) và nó có thể là một mô hình rất mạnh, đặc biệt đối với chế độ xem bảng điều khiển / bảng nơi bạn cần lọc và dữ liệu trang trên các dịch vụ. Bạn có thể xây dựng "các phép chiếu" (về cơ bản là các khung nhìn) từ các sự kiện trong miền để điều khiển các bảng điều khiển này. Tôi đã sử dụng nó trước đây khá thành công. Nó có thể là một công cụ rất mạnh trong kịch bản phù hợp. IMHO điều quan trọng hơn ở đây là bạn nhận ra rằng các dự đoán này không đại diện cho các mô hình miền và chúng không nên chứa logic kinh doanh.
Jordan

3

Tôi nghĩ rằng câu hỏi của bạn thực sự đòi hỏi 2 bộ tùy chọn trực giao -

  • Bạn có tải hai đối tượng và trình bày dữ liệu của chúng cùng nhau hay bạn tải 1 đối tượng có chứa mọi thứ bạn muốn?

  • Bạn có sử dụng tổng hợp để hiển thị công cụ, hoặc cái gì khác?

Nếu bạn tin vào cách tiếp cận CQRS, hóa ra tổng hợp có thể không phải là lựa chọn tốt nhất cho việc đọc. Mỗi lần bạn tải một tổng hợp, cho dù hiển thị dữ liệu của nó hay sửa đổi nó, bạn sẽ thêm đồng thời và tranh chấp vào hệ thống của mình. Ngoài ra, các tập hợp có khả năng lớn hơn và tải chậm hơn so với khi bạn sử dụng các mô hình đọc đặc biệt được thiết kế để hiển thị.

Giải pháp a) từ Q của bạn dường như chịu rất nhiều cạm bẫy này. Tùy chọn b) có thể hợp lệ, nhưng tôi chỉ sử dụng nó nếu dữ liệu từ InventoryManagementBC là cần thiết để thực thi các bất biến khi làm thay đổi Producttổng hợp. Sẽ tốt hơn nếu một tập hợp chứa tất cả dữ liệu cần thiết để kiểm tra các quy tắc kinh doanh của nó khi sửa đổi, nhưng về phía đọc, chúng có thể ngồi ở bất cứ đâu.

Về dữ liệu, một khuyến nghị phổ biến là cung cấp Bối cảnh cơ sở dữ liệu của riêng họ (vì lý do triển khai và lý do SoC). Bạn có thể sẽ phải sử dụng cùng một số nhận dạng nếu bạn muốn khớp các sản phẩm giữa hai BC.

Về các tương tác xuyên BC, bạn cũng có thể muốn xem /programming/16713041/cransicating-b between -two -bounded-contexts-in- ddd


1
OK, điều đó có ích. Về cơ bản, chúng tôi đang sử dụng Rễ tổng hợp và BC để đảm bảo các bất biến của chúng tôi là nhất quán và dữ liệu của chúng tôi là hợp lệ và các hoạt động chúng tôi muốn thực hiện được gói gọn trong tổng hợp hoặc BC của chúng tôi. Khi đọc và hiển thị dữ liệu đó, chúng ta có thể xử lý riêng và nhẹ mà không cần tất cả các tập hợp / BC. Rốt cuộc, tại sao chúng ta cần tải Tổng hợp khi tất cả những gì chúng ta đang làm là hiển thị dữ liệu trong báo cáo hoặc trên màn hình. Điều này làm cho ý nghĩa hoàn hảo. Cảm ơn.
PendorPaul

Đây là nơi CQRS thực sự tỏa sáng. Bạn chỉ có thể thực hiện một truy vấn SQL, tham gia các bảng và trả về truy vấn phù hợp cho một chế độ xem cụ thể. Nó cũng xóa repo của bạn khỏi mớ hỗn độn phương thức truy vấn. Ngoài ra, bạn thậm chí có thể sao chép dữ liệu trên dịch vụ như ElasticSearch và truy vấn nó.
chú ý

1

DDD có nghĩa là cho các ứng dụng mà logic kinh doanh phức tạp. "In một cái gì đó" không phải là một logic kinh doanh phức tạp. Nó thực sự không phải là một logic kinh doanh.

Nếu, logic nghiệp vụ trong một ngữ cảnh cần một số thông tin để xử lý đúng một số trường hợp sử dụng, thì thông tin đó là một phần của bối cảnh đó. Vì vậy, ý tưởng rằng một bối cảnh bị ràng buộc có thể cần thông tin có sẵn trong các bối cảnh bị ràng buộc khác nhau không có ý nghĩa, bởi vì bối cảnh bị ràng buộc có tất cả thông tin cần thiết.


OK, vì vậy hãy lấy một cái gì đó như Amazon, đó là một hệ thống phức tạp với logic kinh doanh phức tạp. Họ có quản lý danh mục và quản lý hàng tồn kho. Họ không cần tổng số hàng tồn kho để quản lý danh mục, ý tôi là tên sản phẩm, mô tả, loại, tình trạng, v.v. Tuy nhiên, họ hiển thị số lượng mặt hàng trong kho trên trang nhất của cửa hàng. Trong trường hợp đó, nơi bạn muốn tách biệt các miền Quản lý danh mục sản phẩm và hàng tồn kho sản phẩm, nhưng bạn cần hiển thị một số thông tin về hàng tồn kho trên trang sản phẩm của mình, bạn sẽ làm thế nào?
PendorPaul

Tôi đoán những gì tôi đang nói là miền Danh mục sản phẩm có tất cả thông tin cần thiết để quản lý danh mục sản phẩm. Miền hàng tồn kho có tất cả thông tin cần thiết để quản lý hàng tồn kho. Tuy nhiên, khi tôi muốn hiển thị một số thông tin cho người dùng và dữ liệu đó đến từ 2 miền, tôi phải làm điều đó ở đâu. Tôi có chỉ tải lên cả hai tên miền trong UI của mình và liên kết các thuộc tính tôi muốn hiển thị không? Hoặc tôi có một số cơ chế báo cáo / đọc khi tôi trả về một loại ẩn danh hoặc DTO chứa dữ liệu tôi cần cho giao diện người dùng của mình không?
PendorPaul

Thật hài hước khi nhìn lại những bình luận cũ này của tôi 11 tháng trước, nhưng dường như là cả cuộc đời. Bạn đã hoàn toàn đúng Euphoric về khía cạnh đọc và viết. Ứng dụng tôi đang làm việc đã phát triển khá nhiều vì sự hiểu biết của tôi đã phát triển. Bây giờ tôi đang sử dụng các phương pháp CQRS, thông qua Jimmy Bogards Mediatr. Tính linh hoạt tuyệt đối của việc có các lệnh tương tác với Uẩn, nhưng sau đó sử dụng các truy vấn và trình xử lý truy vấn để mang lại bất cứ thứ gì tôi cần để hiển thị là không thể tin được. Kết hợp nó vào Chế độ xem gọi vào các QueryHandlers đó và việc tách rời là tốt với cái này. Cảm ơn
PendorPaul

@PendorPaul, tôi nghĩ tôi đang ở nơi bạn 11 (bây giờ là 13) tháng trước. Điều gì đã đưa bạn đến nơi bạn đang ở bây giờ?
Greg Bell

1
@GregBell Bạn cần buộc thay đổi tư duy. Tôi đã bị mắc kẹt trong cách tiếp cận "thiết kế cơ sở dữ liệu, xây dựng tầng dữ liệu, xây dựng một số logic kinh doanh ... vv". Và tôi đã tập trung vào việc tạo ra tất cả các thực thể bao gồm. tức là "Sản phẩm" trong trang web Thương mại điện tử, đã xử lý mọi thứ từ giá cả, mô tả, hàng tồn kho, vị trí chứng khoán .... nhưng điều đó trở nên cực kỳ phức tạp. Cách tiếp cận bối cảnh bị ràng buộc có nghĩa là trong bối cảnh Hàng tồn kho, "Sản phẩm" chỉ chứa thông tin và hành vi để quản lý kho. Mô tả và hình ảnh được quản lý trong bối cảnh nội dung, giá cả trong bối cảnh giá cả.
PendorPaul

1

Theo quan điểm của tôi, có những định nghĩa khác nhau về "Sản phẩm" - mọi bối cảnh giới hạn đều có định nghĩa riêng về "sản phẩm" -domain:

  • Trong Nội dung - Quản lý - Giới hạn - Bối cảnh sản phẩm có hình ảnh và văn bản mô tả.
  • Trong Bối cảnh hàng tồn kho - Bối cảnh, một sản phẩm có số lượng tồn kho, người bán sản phẩm, phát sóng khi sản phẩm sẽ có sẵn
  • Trong Bối cảnh giá-Caculation-Bounding-Bối cảnh, có các quy tắc một sản phẩm có thể có giá bao nhiêu cho mỗi số lượng.

Trên hết, tôi sẽ thêm một Bối cảnh Cửa hàng bổ sung với định nghĩa sản phẩm của riêng mình (một sự kết hợp có liên quan của các miền sản phẩm của Bối cảnh-Bối cảnh khác).

Một Cửa hàng-Sản phẩm sẽ có "hình ảnh và văn bản mô tả" từ nội dung và tính khả dụng từ "Hàng tồn kho" chứ không phải "người bán sản phẩm" từ kho.

Cửa hàng-Bounding-Bối cảnh bổ sung này phụ thuộc vào Nội dung của Bounding-Context-s, Hàng tồn kho, Giá cả


Vậy bạn đang tạo ra Shop-Product BC đó như thế nào? Trong bối cảnh đó, bạn có tham chiếu đến Sản phẩm và hàng tồn kho BC không, và bạn có đang hydrat hóa những thứ đó từ cửa hàng kiên trì của bạn khi bạn tải BC Cửa hàng-Sản phẩm, sau đó cung cấp các thuộc tính bạn muốn từ các BC đó thông qua các thuộc tính Store Store của bạn không? Tôi đã tìm thấy bài viết này thực sự dọc theo những gì tôi đang nghĩ, xuyên qua các sự kiện BC nhưng @ guillaume13 ở trên đã chỉ ra rằng vì mục đích hiển thị, tôi có thể tránh BC và chỉ cần lấy lại dữ liệu tôi cần cho chế độ xem của mình. msdn.microsoft.com/en-us/magazine/dn802601.aspx
PendorPaul
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.