2012-02-24 20 views
5

Tôi đang đọc sách của Eric Evans về DDD và tôi có câu hỏi cho câu sau đây. Làm thế nào để bạn thực hiện phương pháp equals() khi bạn không nên sử dụng các thuộc tính? Tôi đang sử dụng JPA và tôi có một thuộc tính id đó là duy nhất nhưng điều này không được thiết lập cho đến khi bạn thực sự tồn tại thực thể. Vậy bạn làm gì? Tôi đã thực hiện phương thức equals dựa trên các thuộc tính và tôi hiểu tại sao bạn không nên vì nó không thành công trong dự án của tôi.Các thực thể trong thiết kế điều khiển tên miền

Mục về thực thể:

Khi một đối tượng được phân biệt bởi bản sắc của nó, chứ không phải là thuộc tính của nó, làm cho chính này để định nghĩa của nó trong mô hình. Giữ nguyên định nghĩa lớp học đơn giản và tập trung vào tính liên tục của vòng đời và số . Xác định phương tiện phân biệt từng đối tượng bất kể biểu mẫu hoặc lịch sử của nó. Hãy cảnh giác với các yêu cầu gọi đối sánh đối tượng theo thuộc tính. Xác định một thao tác được đảm bảo để tạo ra một kết quả duy nhất cho mỗi đối tượng, có thể bằng cách gắn một biểu tượng được đảm bảo duy nhất. Phương tiện nhận dạng này có thể là đến từ bên ngoài hoặc có thể là mã định danh tùy ý được tạo bởi và cho hệ thống, nhưng phải tương ứng với nhận dạng sự phân biệt trong mô hình. Mô hình phải xác định nghĩa là điều tương tự.

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

+0

có thể trùng lặp, xem http://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemma – MRalwasser

+0

id hoạt động tốt đối với tôi: http://stackoverflow.com/questions/7579404/using-auto-generated-id-of-hibenate-entity-object-in-the-equals-and-hashcode-met – NimChimpsky

Trả lời

1

Couple phương pháp tiếp cận có thể:

  • Sử dụng một chìa khóa kinh doanh. Đây là phương pháp 'tuân thủ DDD' nhiều nhất. Xem xét kỹ các yêu cầu về miền và doanh nghiệp. Ví dụ, doanh nghiệp của bạn xác định Khách hàng như thế nào? Họ có sử dụng Số an sinh xã hội hoặc số điện thoại không? Doanh nghiệp của bạn sẽ giải quyết vấn đề này như thế nào nếu nó được dựa trên giấy (không có máy tính)? Nếu không có khóa kinh doanh tự nhiên, hãy tạo đại diện. Chọn khóa kinh doanh là cuối cùng và sử dụng nó trong equals(). Có một phần trong cuốn sách DDD dành riêng cho vấn đề cụ thể này.

  • Đối với các trường hợp không có khóa kinh doanh tự nhiên, bạn có thể tạo UUID. Điều này cũng sẽ có một lợi thế trong hệ thống phân tán trong trường hợp này bạn không cần phải dựa vào tài nguyên tập trung (và có khả năng không có) như cơ sở dữ liệu để tạo ra một id mới.

  • Ngoài ra còn có tùy chọn chỉ dựa trên mặc định equals() cho các lớp tổ chức.Nó sẽ so sánh hai vị trí bộ nhớ và nó là đủ trong hầu hết các trường hợp vì Unit Of Work (Hibernate Session) giữ cho tất cả các thực thể (mẫu ORM này được gọi là Identity Map). Đây không phải là đáng tin cậy bởi vì nó sẽ phá vỡ nếu bạn sử dụng các thực thể không chỉ giới hạn phạm vi của một Hibernate Session (đề suy nghĩ, các thực thể tách rời vv)

Điều thú vị đủ, 'chính thức' DDD mẫu sử dụng rất nhẹ khuôn khổ nơi mỗi lớp thực thể có nguồn gốc từ giao diện Entity với một phương pháp:

boolean sameIdentityAs(T other) 
// Entities compare by identity, not by attributes. 
+0

Giả sử thực thể là Câu hỏi. Tôi sẽ sử dụng cái gì? Tôi đã dựa vào id được tạo cho đến bây giờ. – LuckyLuke

+0

Tùy thuộc vào miền của bạn, có thể là văn bản của câu hỏi đó (trong trường hợp đó có thể là Giá trị không phải là Thực thể), nhưng có nhiều khả năng giống như số câu hỏi. Thực sự phụ thuộc vào miền của bạn. – Dmitry

1

Nếu đối tượng không phải là dai dẳng chưa, sau đó là có bất kỳ tác hại khi so sánh 2 đối tượng dựa trên các thuộc tính của họ?

Tôi không chắc tại sao điều này không thành công trong dự án của bạn, nhưng theo kinh nghiệm của tôi, so sánh dựa trên thuộc tính hầu như luôn trơn trượt nếu thuộc tính của bạn không phải là cuối cùng. Điều đó có nghĩa là, 2 đối tượng bằng nhau bây giờ, có thể không bằng nhau sau một thời gian. Thật tồi tệ.

Do hầu hết các lớp Java được viết cùng với các trình truy cập của chúng, bằng các thuộc tính so sánh được cho là một ý tưởng tồi.

Tuy nhiên, trước hết tôi có thể kiểm tra xem trường ID có phải là không null hay không. Nếu nó là null, tôi sẽ quay trở lại so sánh thuộc tính. Nếu nó không phải là null, sau đó chỉ cần sử dụng nó và không làm bất cứ điều gì khác. Điều này có nghĩa không?

+2

Đây là một điều nguy hiểm để làm. Nếu bạn lưu trữ đối tượng trong một HashSet trước khi gán ID của nó, thì HashSet sẽ bị hỏng. –

+0

Chắc chắn. Nhưng, sau đó, tôi sẽ giả sử bạn sẽ kiên trì đối tượng để có được id. Trong trường hợp đó, tôi thường thích nhận được đối tượng tồn tại được trả về và sử dụng nó. Về cơ bản, không làm thay đổi trạng thái của đối tượng được sử dụng trong kiểm tra bình đẳng. – Pavan

+0

Nếu bạn so sánh các đối tượng dựa trên các thuộc tính của nó thì nó hoạt động như một đối tượng giá trị không phải là một thực thể. Đối tượng giá trị và thực thể có ngữ nghĩa khá khác nhau trong DDD, do đó bạn không nên căn cứ vào tính bình đẳng của thực thể trên các thuộc tính. –

1

với Person lớp với các thuộc tính name, surname. Khi Người ở tuổi 21 thay đổi tên của nó thì nó vẫn là cùng một Người (bằng với số true)? Nếu bạn viết bằng cơ sở trên các thuộc tính, thì đó sẽ không phải là cùng một người, do đó, theo cách của tôi, cách tốt nhất là kiểm tra tính bình đẳng của các thực thể dựa trên số nhận dạng doanh nghiệp của họ (duy nhất và không thay đổi trong toàn bộ vòng đời thực thể).

0

Một giải pháp khác có thể là sử dụng trường UUID trong pháp nhân của bạn.

Trong trường hợp này, bạn có thể sử dụng UUID làm khóa chính hoặc chỉ cho bằng.

@Entity 
public class YourEntity{ 

    @Id 
    private String uuid = UUID.randomUUID().toString(); 

    // getter only... 

}