DDD và các đối tượng giá trị. Các đối tượng giá trị có thể thay đổi là một ứng cử viên tốt cho Non Aggr. Thực thể gốc?


9

Đây là một vấn đề nhỏ

Có một thực thể, với một đối tượng giá trị. Không thành vấn đề. Tôi thay thế một đối tượng giá trị cho một đối tượng mới, sau đó nhibernate chèn giá trị mới và mồ côi đối tượng cũ, sau đó xóa nó. Ok, đó là một vấn đề.

Bảo hiểm là thực thể của tôi trong miền của tôi. Anh ta có một bộ sưu tập Địa chỉ (đối tượng giá trị). Một trong những địa chỉ là MailingAddress. Khi chúng tôi muốn cập nhật địa chỉ gửi thư, giả sử mã zip bị sai, theo học thuyết của ông Evans, chúng tôi phải thay thế đối tượng cũ cho một địa chỉ mới vì nó không thay đổi (một đối tượng giá trị phải không?).

Nhưng chúng tôi không muốn xóa hàng này, vì PK của địa chỉ đó là FK trong bảng MailingHistory. Vì vậy, theo học thuyết của ông Evans, chúng tôi gặp khá nhiều khó khăn ở đây. Trừ khi tôi thực hiện địa chỉ của mình Thực thể, vì vậy tôi không phải "thay thế" nó, và chỉ cần cập nhật thành viên mã zip của nó, như những ngày tốt đẹp cũ.

Bạn sẽ đề nghị gì cho tôi trong trường hợp này? Theo cách tôi thấy, ValueObjects chỉ hữu ích khi bạn muốn gói gọn một nhóm các cột của bảng cơ sở dữ liệu (thành phần trong nhibernate). Mọi thứ có id liên tục trong cơ sở dữ liệu, tốt hơn hết là biến nó thành một Thực thể (không nhất thiết phải là một gốc tổng hợp) để bạn có thể cập nhật các thành viên của nó mà không cần tạo lại toàn bộ biểu đồ đối tượng, đặc biệt nếu đó là một đối tượng được lồng sâu.

Bạn có đồng ý không? Được ông Evans cho phép có một đối tượng giá trị có thể thay đổi? Hoặc là một đối tượng giá trị có thể thay đổi là một ứng cử viên cho một Thực thể?

Cảm ơn


2
Có những thứ như "đối tượng giá trị có thể thay đổi"? Tôi luôn luôn có các đối tượng giá trị ấn tượng là bất biến.
Herby

@herby Tôi đoán bạn có thể có một đối tượng có thể thay đổi đại diện cho một đối tượng giá trị DDD trong mã, nhưng bạn sẽ phải xem xét rằng một khi bạn biến đổi đối tượng, nó không tham chiếu cùng một đối tượng giá trị DDD logic nữa mà là một đối tượng mới. Điều này có thể được mong muốn nhưng đó là một công thức cho sự nhầm lẫn imo - làm cho các đối tượng giá trị bất biến trong mã là một quy ước thông minh.
MattDavey

Câu trả lời:


8

Mọi thứ có danh tính phải là một Thực thể và mọi thứ không có danh tính là một giá trị đơn giản, do đó là một đối tượng giá trị.

Để trích dẫn Martin Fowler (lần lượt nói về Eric Evans)

  • Thực thể: Các đối tượng có bản sắc riêng biệt chạy qua thời gian và các biểu diễn khác nhau. Bạn cũng nghe thấy những thứ gọi là "đối tượng tham chiếu".
  • Đối tượng giá trị: Các đối tượng quan trọng chỉ có sự kết hợp các thuộc tính của chúng.

Lý do biến địa chỉ của bạn thành Đối tượng Giá trị:

Nếu địa chỉ của bạn có thể thay đổi, cuối cùng bạn sẽ làm hỏng lịch sử gửi thư của mình. Ví dụ: nếu bạn đang vận chuyển các mặt hàng cho khách hàng, bạn không thể chắc chắn địa chỉ nào bạn thực sự đã gửi một thứ gì đó trong quá khứ nếu địa chỉ mà bảng MailingHistory của bạn đề cập đã bị thay đổi.

Mục nhập MailingHistory Chúng tôi đã chuyển A764 đến địa chỉ 657 có nghĩa là Chúng tôi đã chuyển bài viết A764 đến Boston ngày hôm qua và chúng tôi đã chuyển bài viết A764 đến New York vào ngày mai.

Nếu địa chỉ gửi thư phải được thay đổi, không cần phải xóa địa chỉ cũ. Giữ nó và đánh dấu nó là không hoạt động , và cái mới là hoạt động .


Tất nhiên bạn có thể coi địa chỉ của mình là một Thực thể, nhưng chỉ khi cập nhật, nó sẽ không thay đổi địa điểm thực tế mà địa chỉ đang đề cập, do đó chỉ cho phép sửa lỗi chính tả.

Nếu bạn chắc chắn rằng bạn có thể đảm bảo rằng, hơn là sử dụng một Thực thể sẽ có thể.


Nhưng giải pháp tốt nhất IMHO là không giới thiệu một địa chỉ Thực thể trong lịch sử gửi thư của bạn, mà là lưu địa chỉ cụ thể trực tiếp trong bảng lịch sử gửi thư của bạn (về cơ bản sao chép dữ liệu của địa chỉ).

Bằng cách này, bạn luôn biết nơi bạn gửi đồ đạc của mình (hoặc bất cứ thứ gì bạn đang gửi thư) và vì bạn sẽ sử dụng một Thực thể có thể thay đổi, bảng địa chỉ của bạn sẽ không bị lộn xộn.

Tôi đã làm việc với / trên một số hệ thống ERP và gần như tất cả chúng đều sử dụng phương pháp này.

Bạn sẽ có một số dự phòng trong cơ sở dữ liệu của mình, nhưng đó là cách thực tế nhất IMHO.


Đây có lẽ là giải pháp đau đầu nhất. Chỉ khi bạn mong đợi rằng các kênh liên lạc trong tương lai sẽ yêu cầu các cột bổ sung và cơ sở dữ liệu của bạn quá lớn ALTER, việc sử dụng các thực thể trong các bảng riêng biệt có thể trở nên cần thiết. Đó là, đến lượt nó, gọi điện cho các chiến lược như "luôn luôn tham gia mới nhất địa chỉ / điện thoại / e-mail" trong cài đặt SELECTtruy vấn, được thử thách để giữ duy trì hiệu quả. Giữ nó đơn giản, nếu có thể.
Timo

@Timo "luôn luôn tham gia địa chỉ / điện thoại / e-mail mới nhất" không khó nếu bạn không chuẩn hóa dữ liệu của mình một chút bằng cách thêm một active-flag. Tất nhiên, bạn phải đảm bảo luôn luôn sử dụng and active = truetrong Joins của mình, luôn cập nhật cờ và thêm một điều khoản vào bảng của bạn để ví dụ như chỉ một e-mail cho mỗi khách hàng có thể đặt cờ này thành đúng.
lười

Điều này giới thiệu vấn đề hủy kích hoạt trước đó. Nếu bạn đã thay thế đối tượng Địa chỉ "hiện tại" của bạn trong mã và bạn truy cập mã truy cập dữ liệu của mình, thì nó sẽ không biết (1) có hay không một cái mới, cũng không (2) cái cũ tiềm năng là gì Một là. Vì vậy, mọi thao tác lưu sẽ phải thực hiện một cái gì đó phức tạp như "trước tiên và hủy tất cả các địa chỉ liên quan trong cơ sở dữ liệu", và sau đó lưu địa chỉ hiện tại với active=true. Đây không phải là những gì tôi sẽ gọi đơn giản, đó chính xác là lý do tại sao tôi thích giải pháp của bạn.
Timo

2

Tôi thấy 2 điều:

  1. Thay đổi mã Zip có ảnh hưởng đến hồ sơ lịch sử không? Tôi nghĩ rằng sẽ là hợp lý khi bản ghi lịch sử trỏ đến địa chỉ cũ, không thay đổi, vì vậy bạn biết bạn gửi nó đến địa chỉ sai.

  2. Khoảnh khắc MailingHistory có FK trên địa chỉ địa chỉ dừng lại là một đối tượng giá trị và trở thành thực thể. Các đối tượng giá trị không có danh tính, cho phép các thực thể khác tham chiếu danh tính này. Bạn có thể có địa chỉ trong một bảng với các bảng khác trỏ đến nó, nhưng chỉ có tác dụng là tiết kiệm không gian. Từ quan điểm tên miền, nếu hai thực thể có cùng loại đối tượng giá trị tham chiếu, thì chúng không chia sẻ bất kỳ loại thông tin nào.


2

IMO đối tượng địa chỉ là một thực thể trong miền của bạn. Nó được chia sẻ bởi nhiều thực thể, có bản sắc riêng và là duy nhất trên toàn hệ thống.

Evans nói:

Một đối tượng được xác định chủ yếu bởi danh tính của nó được gọi là một thực thể.


Nhận dạng tên miền, theo hiểu biết của tôi, không có gì để làm với bản sắc bền bỉ. Theo cuốn sách của ông Evan.
Pepito Fernandez

Bạn đúng rồi. Tôi chỉnh sửa câu trả lời của tôi. Ý tôi là Địa chỉ đối tượng có vấn đề trong miền cụ thể này, nó là duy nhất. IMO Khóa ngoài và Khóa chính là dấu hiệu cho thấy đây thực sự là một đối tượng duy nhất trong toàn bộ miền, do đó, nó có một danh tính.
lề

1
"đối tượng địa chỉ ... có danh tính riêng" - thuộc tính nào của địa chỉ xác định duy nhất địa chỉ đó? Không có thuộc tính duy nhất của một địa chỉ là duy nhất, nhưng sự kết hợp của các thuộc tính đóng vai trò là danh tính. Đây là định nghĩa của một đối tượng giá trị
MattDavey

@MattDavey: đó là một kết luận tốt, nhưng tôi cảm thấy bối rối khi Tony nói rằng "chúng tôi không muốn xóa hàng này, vì PK của địa chỉ đó là một FK trong bảng MailingHistory". Điều này có nghĩa với tôi rằng đối tượng Địa chỉ cũng có ý nghĩa bên ngoài Tập hợp 'Bảo hiểm'. Điều này cho tôi thấy rằng đối tượng 'Địa chỉ' không nên là ValueObject. Bạn nghĩ sao?
lề

Chúng ta có thể nói rằng các Đối tượng Giá trị luôn luôn là thành phần được sở hữu hoàn toàn (UML) không? Ngoài ra, một Đối tượng Giá trị sẽ vô nghĩa nếu không có Cha mẹ của nó và không thể chia sẻ giữa Cha mẹ?
Sudarshan
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.