2013-06-04 17 views
5

Chúng tôi đang cố gắng áp dụng Thiết kế theo hướng miền trong dự án của chúng tôi lần đầu tiên. Vấn đề tôi gặp phải là liên quan giữa các thực thể. Làm thế nào để bạn làm đúng?Cách đúng để triển khai các hiệp hội trong DDD?

Giả sử, tôi có các thực thể EmployeeContract, một liên kết một-nhiều đơn giản. Làm thế nào để tôi mô hình hóa nó?

Tùy chọn 1: Tổng hợp.

Vấn đề: Vấn đề ở đây là, nếu tôi hiểu chính xác, tất cả các thực thể trong tổng hợp phải được tải khi một đối tượng tổng hợp được tạo. Tôi không thể lười biếng tải các thực thể khi chúng là cần thiết vì nó sẽ yêu cầu tham chiếu đến một kho lưu trữ từ một thực thể, mà dường như là xấu. Nhưng lấy tất cả các hợp đồng của nhân viên từ cơ sở dữ liệu mỗi lần sẽ là một vấn đề hiệu suất lớn.

Phương án 2: Tìm nạp các hợp đồng của nhân viên bằng cách sử dụng một kho lưu trữ (ví dụ ContractRepository.GetContractsForEmployee()) và thêm EmployeeId tài sản để Contract lớp.

Sự cố: khiến bạn khó đưa bất kỳ logic nghiệp vụ nào vào thực thể. Tôi muốn có một phương pháp, ví dụ: Employee.Dismiss(), nhưng cũng cần phải cập nhật hợp đồng của nhân viên. Điều này có nghĩa là tôi sẽ cần phải đặt logic này trong một dịch vụ. Vấn đề là, tôi không thể nghĩ nhiều logic chỉ hoạt động trên Employee và do đó mô hình sẽ trở nên hơi thiếu máu, với hầu hết các logic bên trong các dịch vụ.

Làm cách nào để giải quyết các vấn đề này trong DDD?

+1

Khi bạn đang nghĩ 'một liên kết đơn giản tới nhiều' bạn không làm DDD, bạn đang làm thiết kế lược đồ cơ sở dữ liệu. Các hiệp hội giữa các thực thể nên là hành vi. Một nhân viên không thể loại bỏ chính nó, nó phải được bác bỏ (bởi một thực thể khác có quyền làm điều đó). Tùy chọn 2 là đúng. Bạn không cần phải nghĩ ra nhiều hành vi cho một thực thể. Nếu một đối tượng miền là rất đơn giản trong kinh doanh thực tế, mô hình nó theo cách đó. Nó quan trọng như thế nào miền định nghĩa khái niệm (ngữ nghĩa) và không có bao nhiêu phương pháp đối tượng có. – MikeSW

+0

MikeSW là chính xác. Một khía cạnh rất quan trọng của DDD là Ngôn ngữ phổ biến. Cách bạn nói về miền PHẢI là cách mà Chuyên gia miền nói về Miền nếu không mã sẽ trở nên khó xử và không trực quan. Nghe có vẻ tầm thường nhưng nếu bạn nhận được quyền này thì thực thể bắt đầu đề xuất hành vi. ví dụ. Employee.Resign(); Contract.Terminate(); – Asher

Trả lời

2

Đây chỉ là việc tôi thực hiện nó ... mà không biết miền của bạn.

Đầu tiên, here là tài nguyên tốt để đọc (một phần về Tổng hợp và Rễ).

Trong thuật ngữ DDD, EmployeeContract đều là đối tượng (vì cả hai đều có nhận dạng).

"Uẩn vẽ một ranh giới xung quanh một hoặc nhiều thực thể và cũng:. Mỗi tổng hợp có gốc Entity, đó là thành viên duy nhất của Uẩn rằng bất kỳ đối tượng bên ngoài Uẩn được phép giữ một tham chiếu đến."

Câu hỏi đặt ra là: làm EmployeeContract dạng một tổng hợp, với Employee là thực thể gốc Rõ ràng là không, bởi vì các đơn vị miền khác cũng có thể có một tham chiếu đến một contract, và id hợp đồng là duy nhất trên toàn cầu, chứ không phải? . chỉ trong vòng một Customer

Vì vậy, có tính đến các quy tắc, EmployeeContract đều nguồn gốc tổng hợp

Sau đó:. "rễ chỉ tổng hợp có thể thu được trực tiếp với các truy vấn; vì vậy đây có nghĩa là chúng ta nên có một kho lưu trữ cho mỗi gốc tổng hợp."

Vì vậy, trong trường hợp này, chúng ta có một EmployeeRepositoryContractRepository.

Lấy tất cả những điều này vào tài khoản, tôi sẽ không thêm một mối quan hệ giữa Sau khi tất cả, nếu bạn cần một số Employee, bạn cũng không nhất thiết cần số contracts của mình nữa, cả hai đều là các khía cạnh khác nhau. sử dụng số ContractRepository để nhận các hợp đồng mà bạn quan tâm. Và nếu bạn cần uld thêm một dịch vụ miền có trách nhiệm tổng hợp nhân viên và hợp đồng nếu cần.

Nếu bạn cũng xác định thực thể Company, thì việc loại bỏ nhân viên có thể là công việc của thực thể đó.

0

Bạn cần phải tìm những bất biến thực sự của mình.

Ở đây bạn có thể có một bất biến như: bạn không thể loại bỏ Employee đã bị loại bỏ.

Nếu đây là bất biến thực sự duy nhất, thì bạn có thể tạo một tổng hợp Employee, chỉ có ID của các hợp đồng liên quan.

Contract sẽ là một tổng hợp khác (nếu cần).

Nếu phương thức dismiss() thành công, bạn có thể tải các hợp đồng cần thiết và thực hiện các thay đổi cần thiết.

1

Gần đây, chúng tôi cũng tham gia vào phương pháp DDD. Nếu tôi được làm điều đó, tôi sẽ phải như sau (các thuộc tính được đơn giản hóa cho ngắn gọn):

public class Employee() { 

    String name; 
    Set<ContractNumber> contracts; 

    public void addContract(ContractNumber contractNumber) { 
     this.contracts.add(contractNumber); 
    } 

} 

public class Contract() { 
    ContractNumber contractNumber; 
    Date effectiveDate; 
} 

public class ContractNumber() { 
    String contractNumber; 
} 

ContractNumber là một đối tượng giá trị gia tăng mà được gọi từ bên trong nhân viên. Trong ví dụ này, Employee nằm trong một BoundedContext giao dịch với Employees và các hợp đồng tương ứng của họ. Có thể có các đại diện khác của nhân viên trong các bối cảnh bị ràng buộc khác.

Như được thảo luận trong các câu trả lời khác, sẽ có kho lưu trữ cho cả nhân viên và hợp đồng.