Tôi có nên sử dụng một gốc tổng hợp khi thiết kế kho lưu trữ của tôi?


8

Tôi có một thực thể được gọi là Master, bao gồm một số thực thể Slave.

Chỉ có thể có một Master trong cơ sở dữ liệu của tôi và tôi muốn truy vấn các kho lưu trữ để lấy Slave cho một id nhất định.

Ban đầu tôi đã tạo một SlaveRep repository và truy vấn nó bằng id. Điều đó có vẻ tốt và hoạt động và các nhà phát triển khác có thể sử dụng kho lưu trữ của tôi.

Sau đó, tôi nghĩ về các gốc tổng hợp và tạo một MasterRep repository và trả về Master và sau đó thực hiện một vòng lặp trên đó để có được thực thể Slave cần thiết. Vấn đề tôi cảm thấy ở đây là một khi tôi phơi bày điều này với các nhà phát triển khác, họ sẽ phải làm điều tương tự, vì vậy tôi thông qua việc có một phương thức trên MasterRep repository có tên GetSlaveByID (id chuỗi) và sau đó tôi có thể lấy Slave trực tiếp (ẩn chức năng vòng lặp ).

Bây giờ, kho lưu trữ của tôi có nên trả lại Slave ngay cả khi nó được gọi là MasterRep repository không? Và quan trọng hơn đó là cách đúng đắn để đi?

Tôi đang trong giai đoạn đầu cố gắng áp dụng DDD và TDD nên có lẽ có rất nhiều điều tôi cần suy nghĩ trước khi quyết định đó là cách tôi đoán đúng.

Câu trả lời:


9

Theo cách thiết kế hướng tên miền của Eric Evans, bạn nên tránh các kho lưu trữ cho các gốc không tổng hợp.

Ông nói rõ:

Chỉ có thể lấy Rễ tổng hợp trực tiếp với các truy vấn cơ sở dữ liệu. Mọi thứ khác phải được thực hiện thông qua truyền tải.

Nhưng nó cũng có nghĩa là, kho lưu trữ cho root phải đáp ứng đầy đủ tất cả các yêu cầu. Nếu bạn cần truy cập trực tiếp vào các phần của tổng hợp, thì một đối tượng gốc tổng hợp hoặc kho lưu trữ của nó chịu trách nhiệm thực hiện điều đó.

Vì vậy, hoàn toàn ổn khi có các phương thức như sau trong kho lưu trữ gốc tổng hợp:

Slave GetSlave(string id)

Nhưng chữ ký này hơi nguy hiểm, vì danh tính của trẻ em trong DDD chỉ có ý nghĩa trong bối cảnh của một đối tượng gốc thực sự và nông cạn mà không có gốc.

Điều này dẫn chúng ta đến một cách tiếp cận DDD tốt hơn và tốt hơn để triển khai trong kho lưu trữ:

Slave GetSlaveOfMaster(Master master, string slaveId)
// or
Slave GetSlaveOfMaster(Identity masterId, Identity slaveId)

Nhưng tôi có lẽ thậm chí sẽ không có phương thức này trên kho lưu trữ mà trên chính thực thể chủ để truy cập nhanh vào các nô lệ. Thậm chí có thể tiếp xúc như một hashtable. Đó là cách tiếp cận sạch nhất tôi có thể nghĩ ra.

//within the Master entity
Slave GetSlave(Identity slaveId);

Đợi đã, đây không phải là kết thúc của câu chuyện. Nếu bạn cần tìm nạp nô lệ mà không có kiến ​​thức về chủ, thì bạn nên suy nghĩ về tập hợp và mô hình đối tượng của bạn. Có lẽ bạn cần một tổng hợp thứ hai trong đó nô lệ là một gốc và sau đó bạn nên có một kho lưu trữ tùy chỉnh cho chúng. Các nô lệ sau đó không chỉ là con của chủ, mà là một hệ thống phân cấp riêng biệt có thể cũng có liên quan đến chủ. Điều quan trọng là phải biết liệu một đối tượng nô lệ có thể tồn tại mà không cần một chủ nhân hay không. Nếu nó có thể, thì một tổng hợp riêng có lẽ là cách để đi.


Cảm ơn bạn rất nhiều cho tất cả các thông tin. Tôi sẽ cố gắng giữ cuốn sách của Eric để hiểu thêm.
JD01

bạn đã đề cập đến một tổng hợp thứ hai, điều này có thể? Bạn đang nói rằng chúng ta có chủ như là một tổng hợp gốc và cũng là nô lệ trong cùng một mô hình?
JD01

1
@ JD01: Hoàn toàn đúng. Bạn có thể có một tập hợp nô lệ riêng trong đó nô lệ là gốc. Điều này phù hợp với DDD miễn là bạn nhớ rằng chỉ có các đối tượng gốc được tiếp xúc. Điều đó có nghĩa là bạn không thể có một lớp thứ ba không phải là một gốc và là một phần của nhiều tập hợp. Nhưng bạn có thể có một tập hợp nô lệ cũng được tham chiếu từ tập hợp chính khi còn nhỏ. Tuy nhiên, đây thường là nơi mọi thứ trở nên phức tạp (các mối quan hệ phức tạp, v.v.). Chúng tôi cố gắng đơn giản hóa điều đó ở đây bằng cách chỉ tham chiếu các đối tượng DTO khi một số root cần tham chiếu một root khác. DTO là chỉ đọc và không thể thay đổi.
Falcon

1
@ JD01: Tất nhiên các tham chiếu DTO đó có thể được trao đổi, nhưng bản thân các DTO là bất biến. Vì vậy, nếu tôi nhận được SlaveDto từ Master, tôi không thể thay đổi nó. Khi tôi muốn thay đổi nó, tôi phải lấy tổng hợp của chính nó và thay đổi nó trong đó. Những DTO đó chỉ chứa dữ liệu phẳng, không có cấu trúc phân cấp và chỉ những gì cần thiết.
Falcon

1
@ JD01: Ngoài ra, bạn nên tự hỏi mình nếu một nô lệ có thể tồn tại mà không có chủ. Nếu nó không thể, thì nó không phải là một gốc tổng hợp. Xem cập nhật nhỏ của tôi.
Falcon

1

Nói chung, trong ranh giới tổng hợp chỉ nên có một kho lưu trữ. Và - như Falcon đã nói - bạn có thể kết thúc với hai tập hợp riêng, chủ và nô lệ.

Tuy nhiên, có vẻ như trọng tâm chính trong câu hỏi của bạn là truy xuất dữ liệu, trong khi trong DDD thì đó phải là hành vi. Ranh giới tổng hợp là hệ quả của các ràng buộc áp đặt bởi hành vi (những thứ thay đổi cùng nhau và bất biến được thi hành), cấu trúc bên trong của tổng hợp là hệ quả của lựa chọn đó.

Ví dụ: nếu bạn nhóm các thứ chính xác theo nhu cầu thay đổi cùng nhau, sẽ không có quá nhiều nhu cầu gọi một Kho lưu trữ bên ngoài. Hầu hết các trường hợp, dữ liệu cần thiết cho hoạt động kinh doanh trong Tập hợp phải nằm trong ranh giới tổng hợp, nhu cầu truy cập các tập hợp khác nhau có lẽ là mùi của ranh giới không nhất quán.

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.