Làm thế nào để thiết kế ranh giới tổng hợp?


10

Tôi muốn viết một ứng dụng giống như thương mại điện tử.

Và bạn biết rằng trong các ứng dụng tương tự, các sản phẩm có thể có các tính chất và tính năng khác nhau. Để mô phỏng cơ hội như vậy, tôi đã tạo các thực thể mô hình miền sau:

Danh mục - đây là một cái gì đó như "điện tử> máy tính" tức là các loại sản phẩm. Các danh mục chứa danh sách các thuộc tính (Danh sách <Thuộc tính>).

Thuộc tính - thực thể độc lập có chứa tên, đơn vị đo lường, loại dữ liệu. Ví dụ: "tên", "trọng lượng", "kích thước màn hình". Các tài sản giống nhau có thể có các sản phẩm khác nhau.

Sản phẩm - chỉ chứa tên và danh sách các giá trị liên quan đến thuộc tính. Giá trị là một đối tượng chỉ chứa trường giá trị và id trường của thuộc tính.

Ban đầu tôi quyết định tạo Danh mục giống như tổng hợp trong sơ đồ này vì ví dụ: khi tôi thêm sản phẩm mới, tôi cần biết tất cả dữ liệu liên quan đến danh mục hiện tại, bao gồm các thuộc tính liên quan đến danh mục hiện tại ( category.AddNewSản phẩm (sản phẩm) ). Nhưng tôi nên làm gì khi tôi chỉ cần thêm một tài sản mới không thuộc bất kỳ danh mục nào. Ví dụ: tôi không thể thực hiện danh mục này.AddNewProperty (thuộc tính) vì nó nói rõ rằng chúng tôi thêm thuộc tính vào danh mục cụ thể.

Ok bước tiếp theo tôi quyết định tách Tài sản thành một tổng hợp riêng nhưng sau đó nó sẽ là một danh sách với các thực thể đơn giản.

Tất nhiên tôi có thể tạo một cái gì đó như PropertyAggregate để giữ bên trong danh sách các thuộc tính và quy tắc kinh doanh nhưng khi tôi thêm một sản phẩm, tôi cần phải có trong danh mục toàn bộ danh sách các thuộc tính thuộc danh mục này để kiểm tra các bất biến. Nhưng tôi cũng nhận thức được rằng việc giữ các liên kết bên trong tập hợp trên các tập hợp khác là một thực tế tồi.

Các tùy chọn để thiết kế trường hợp kinh doanh này là gì?


Bạn có thể cung cấp một ví dụ đầy đủ hơn về một danh mục, tài sản và sản phẩm? Điện tử hoặc máy tính sẽ là một danh mục, iPhone X sẽ là một ví dụ về sản phẩm, và một tài sản sẽ chính xác là gì? Màn hình 11 inch?
Neil

bạn gần như đúng Tôi đã thêm một số làm rõ
cephei

Có vẻ như bạn đang xem xét thiết kế tổng hợp độc quyền từ góc độ "thùng chứa dữ liệu". Bạn cũng có thể muốn suy nghĩ về việc sử dụng các trường hợp ứng dụng của mình, có tính đến các khía cạnh giao dịch, cộng tác / truy cập đồng thời, các sự kiện xảy ra, chuyển trạng thái, v.v.
guillaume31

Câu trả lời:


7

Trong phối cảnh DDD Category, ProductPropertylà các thực thể: tất cả chúng đều tương ứng với các đối tượng có bản sắc riêng.

Tùy chọn 1: thiết kế ban đầu của bạn

Bạn đã tạo Categorygốc của một tổng hợp duy nhất. Ở một bên, điều này có ý nghĩa, bởi vì tổng hợp phải đảm bảo tính nhất quán khi đối tượng của nó được sửa đổi, và Productphải có Propertiescủa nó Category:

nhập mô tả hình ảnh ở đây

Nhưng mặt khác, tập hợp đơn có nghĩa là tất cả các đối tượng của nó có liên quan đến một gốc sở hữu chúng và tất cả các tham chiếu bên ngoài phải được thực hiện thông qua gốc tổng hợp này. Điều này ngụ ý rằng:

  • một cụ thể Productthuộc về một và chỉ một Category. Nếu Categorybị xóa, thì nó cũng vậy Products.
  • một cụ thể Propertythuộc về một và chỉ một Category. Nói cách khác, nếu "Màn hình TV" và "Màn hình máy tính" sẽ là hai loại, "Màn hình TV: kích thước" và "Màn hình máy tính: kích thước" sẽ là hai thuộc tính khác nhau.

Điểm thứ hai không tương ứng với lời kể của bạn: " Nhưng tôi nên làm gì khi tôi chỉ cần thêm một cái mới Propertykhông thuộc bất kỳ danh mục nào ". Và không rõ nếu cùng Propertiescó thể được sử dụng khác nhau Categories.

Tùy chọn 2: Tài sản bên ngoài tổng hợp

Nếu một Propertytồn tại độc lập với Categories, nó phải nằm ngoài tổng hợp. Và tương tự nếu bạn muốn chia sẻ Propertiesgiữa Categories(điều này có ý nghĩa về chiều cao, chiều rộng, kích thước, v.v ...). Điều này dường như chắc chắn là trường hợp.

Hậu quả là liên kết giữa Propertyvà những thứ thuộc về tổng hợp: trong khi bạn có thể điều hướng từ bên trong tổng hợp đến Property, bạn không còn được phép đi trực tiếp từ a Propertyđến các giá trị tương ứng. Hạn chế điều hướng này có thể được hiển thị trong sơ đồ UML:

nhập mô tả hình ảnh ở đây

Lưu ý rằng thiết kế này không ngăn cản bạn phải có một List<Property>trong Category, với một tham chiếu ngữ nghĩa (ví dụ java): mỗi tài liệu tham khảo trong danh sách đề cập đến một thể chia sẻ Propertyđối tượng trong một kho lưu trữ.

Vấn đề duy nhất với thiết kế này là bạn có thể thay đổi Propertyhoặc xóa nó: vì nó nằm ngoài tổng hợp, nên tổng hợp không thể quan tâm đến tính nhất quán của các bất biến của nó. Nhưng đây không phải là một vấn đề. Đó là hệ quả của các nguyên tắc DDD và sự phức tạp của thế giới thực. Dưới đây là một trích dẫn của Eric Evans trong cuốn sách bán kết " Thiết kế hướng tên miền: Xử lý sự phức tạp trong trái tim của phần mềm ":

Bất kỳ quy tắc nào kéo dài AGGREGATE sẽ không được dự kiến ​​cập nhật mọi lúc. Thông qua xử lý sự kiện, xử lý hàng loạt hoặc các cơ chế cập nhật khác, các phụ thuộc khác có thể được giải quyết trong một số thời gian được chỉ định. Nhưng các bất biến được áp dụng trong AGGREGATE sẽ được thực thi khi hoàn thành mỗi giao dịch.

Vì vậy, có, nếu bạn thay đổi a Property, bạn sẽ phải đảm bảo rằng một dịch vụ kiểm tra Danh mục đề cập đến nó được cập nhật khi cần thiết.

Tùy chọn 3: Danh mục, tài sản và sản phẩm trong các tập hợp khác nhau

Tôi chỉ tự hỏi nếu giả định rằng một Productthuộc về một đơn Categoryđược thành lập:

  • Tôi thường thấy các cửa hàng trực tuyến đề xuất một Productdưới một số Categories. Ví dụ: bạn sẽ tìm thấy "Thương hiệu máy tính xách tay X Model Y" trong danh mục "Máy tính xách tay" và danh mục "Máy tính" và "máy in đa chức năng Z" trong danh mục "máy in", "máy quét" và "fax".
  • Không phải ai đó có thể tạo cái Productđầu tiên và chỉ sau đó mới gán nó vào Danh mục và điền vào các giá trị?
  • Nếu bạn muốn tách một danh mục, bạn có thực sự xóa Sản phẩm của nó và sau đó tạo lại chúng theo các danh mục mới không?

Nó sẽ không đơn giản hóa các tập hợp và bạn thậm chí sẽ có nhiều quy tắc hơn bao trùm các tập hợp. Nhưng hệ thống của bạn sẽ là bằng chứng trong tương lai nhiều hơn nữa.


Cảm ơn bạn rất nhiều đây là một lời giải thích rất hữu ích. Nhưng tôi muốn làm rõ một vài điểm. Tôi muốn bắt đầu với tùy chọn thứ hai và ai biết được, có lẽ tôi sẽ đến với người thứ ba. Nếu tôi Propertyvượt ra ngoài ranh giới của Categorytổng hợp thì điều này có nghĩa là nó Propertytrở thành một tổng hợp trong chính nó và cần một kho lưu trữ? Nếu đó là sự thật thì làm sao để vượt qua được yêu cầu List<Property>vào Categorydụ? Thông qua các nhà xây dựng? Nó sẽ đúng chứ? Và làm cách nào để tìm ra danh sách PropertyID của một Categorycái chưa được tạo?
cephei

@zetetic ngắn gọn: có, bạn sẽ cần một kho Tài sản độc lập. Hoặc bạn chuyển danh sách Thuộc tính hiện có cho nhà máy của Danh mục hoặc bạn tạo Danh mục trống và điền danh sách bằng phương thức addProperty. Đổi lại câu hỏi: hãy tưởng tượng bạn muốn có Thuộc tính "bắt buộc" và "tùy chọn" và đặc tính bắt buộc phụ thuộc vào danh mục. Làm thế nào bạn kiểm soát nó ?
Christophe

Trả lời câu hỏi của bạn, điều đầu tiên bạn nghĩ đến là tôi có thể tạo ra một thực thể đặc biệt Featurevà nó sẽ chỉ thuộc về Product. và thực thể này sẽ không tham gia tìm kiếm. bạn nói gì ?
cephei

@zetetic tại sao không! Tôi đã rời khỏi các Giá trị vì chúng hiện đang có trong sản phẩm và sẽ liên kết tính năng này với danh mục. Một danh mục có n tính năng (một phần của tổng hợp), Thuộc tính xác định m Tính năng (nhưng liên kết đi qua tính năng Danh mục->). Sau đó, bạn đã phân tách mối quan hệ nhiều-nhiều thành các yếu tố dễ quản lý hơn, làm rõ ranh giới tổng hợp. Cuối cùng về tiêm kho: điều này là không cần thiết nếu bạn tham khảo uẩn khác bằng cách nhận dạng (đọc bài viết này informit.com/articles/article.aspx?p=2020371&seqNum=4 )
Christophe

5

Theo tôi thấy, bạn có thể giải quyết điều này theo một trong hai cách:

Danh mục là một loại sản phẩm đặc biệt

Điều này có nghĩa là đối với bất kỳ sản phẩm nhất định nào trong cơ sở dữ liệu của bạn, nó chứa khóa ngoại trỏ đến cùng một sản phẩm bảng. Sản phẩm là sản phẩm chỉ khi không tồn tại sản phẩm có khóa ngoại bằng với id của sản phẩm nói trên. Nói cách khác, nếu nó không có sản phẩm theo nó, nó là một sản phẩm.

Điều này sẽ đơn giản hóa mọi thứ một chút. Các sản phẩm cho các thuộc tính sẽ có mối quan hệ một-nhiều và do đó, các danh mục của bạn cũng có mối quan hệ một-nhiều vì chúng cũng là các sản phẩm. Thêm một tài sản vào một danh mục sẽ dễ dàng như thêm một tài sản vào một sản phẩm trong chương trình của bạn. Tải tất cả các thuộc tính có nghĩa là kết hợp các thuộc tính của sản phẩm với các thuộc tính của sản phẩm danh mục được liên kết và cho đến khi bạn tiếp cận một sản phẩm danh mục không có cha mẹ.

Ứng dụng thương mại điện tử của bạn sẽ cần tạo sự khác biệt này, nhưng nếu bạn có khả năng tải các sản phẩm của một danh mục, thì đó không phải là mất hiệu suất để biết bạn đang giao dịch với một danh mục hoặc sản phẩm. Nó cũng tự cho mình tìm kiếm thời trang cây theo cấp độ sản phẩm vì mỗi sản phẩm (danh mục) sẽ mở ra một danh sách các sản phẩm phụ mà không cần phải làm thêm.

Nhược điểm của điều này tất nhiên là thông tin bổ sung có trong sản phẩm không có ý nghĩa đối với một danh mục sẽ tạo ra các trường không sử dụng vụng về trong sản phẩm. Mặc dù giải pháp này sẽ linh hoạt hơn trong ứng dụng của bạn, nhưng nó cũng hơi trực quan hơn.

Mối quan hệ nhiều-nhiều

Sản phẩm không còn trong mối quan hệ tổng hợp với tài sản. Bạn tạo một bảng ProductProperty với các khóa ngoại của cả bảng sản phẩm và bảng thuộc tính liên kết cả hai. Tương tự, bạn có một bảng danh mục có mối quan hệ nhiều-nhiều với bảng thuộc tính và bảng CategoryProperty với các khóa ngoại của cả bảng danh mục và bảng thuộc tính.

Bản thân sản phẩm sẽ có mối quan hệ nhiều-một với danh mục, cho phép bạn chủ yếu tạo một danh sách các thuộc tính duy nhất liên quan đến cả sản phẩm và danh mục thông qua tuyên bố chọn chính thức.

Từ quan điểm của cơ sở dữ liệu, điều này chắc chắn là sạch sẽ và linh hoạt hơn. Ứng dụng của bạn có thể có thể thực hiện phần lớn mà không cần giao dịch trực tiếp với CategoryProperty hoặc ProductProperty nếu truy vấn được thực hiện đúng. Tuy nhiên, bạn cũng không nên coi danh mục hoặc sản phẩm là chủ sở hữu của tài sản. Nó phải là thực thể riêng của nó trong chương trình của bạn. Điều này cũng có nghĩa là việc quản lý các tài sản nói trên sẽ là vấn đề tạo ra tài sản đó, sau đó liên kết nó với một danh mục hoặc một sản phẩm theo hai bước riêng biệt. Chắc chắn công việc nhiều hơn giải pháp đầu tiên, nhưng không có nghĩa là khó khăn hơn.

Ngoài ra, bạn cũng sẽ phải thực hiện kiểm tra bổ sung khi xóa danh mục hoặc sản phẩm nếu bất kỳ thuộc tính nào của nó đang được sử dụng bởi người khác (không giống như giải pháp đầu tiên mà bạn có thể loại bỏ một cách an toàn tất cả các thuộc tính liên quan của sản phẩm / danh mục cụ thể) .

Phần kết luận

Trong bối cảnh chuyên nghiệp, tôi sẽ đi thêm danh mục dặm và khoảng cách từ sản phẩm và sản phẩm từ tài sản bằng cách sử dụng phương pháp nhiều-nhiều. Sẽ không có khả năng trùng lặp dữ liệu, và theo một nghĩa nào đó, sẽ dễ dàng hơn để coi mỗi ba người này là thực thể riêng của mình. Tuy nhiên, không có nghĩa là giải pháp đầu tiên là một giải pháp tồi vì nó cũng cho phép bạn viết một ứng dụng đơn giản hơn. Chỉ cần biết rằng nếu bạn nghĩ rằng cuối cùng bạn có thể cần phải chuyển từ giải pháp này sang giải pháp khác, thì có lẽ đó chỉ là lợi ích tốt nhất của bạn để chọn giải pháp thứ hai.

Chúc may mắn!


Cảm ơn câu trả lời chi tiết và thú vị! ở cấp độ cơ sở dữ liệu tôi đã mô hình hóa như bạn đã giải thích trong trường hợp thứ hai, mẫu này được gọi là giá trị thuộc tính thực thể, nhưng tôi bị kẹt ở cấp mã, cụ thể là định nghĩa tổng hợp. Trong hầu hết các trường hợp, tất cả các thực thể này được sử dụng cùng nhau. có thể kết hợp thành một tổng hợp nhưng có những trường hợp như điền vào các thư mục theo nghĩa được đánh bại từ tổng hợp.
cephei
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.