Có một cộng đồng khá lớn những người sử dụng CQRS để triển khai các miền của họ. Cảm giác của tôi là, nếu giao diện của kho lưu trữ của bạn tương tự như các thực tiễn tốt nhất được sử dụng bởi chúng, thì bạn sẽ không đi quá xa.
Dựa trên những gì tôi đã thấy ...
1) Trình xử lý lệnh thường sử dụng kho lưu trữ để tải tổng hợp thông qua kho lưu trữ. Các lệnh nhắm đến một thể hiện cụ thể duy nhất của tổng hợp; kho lưu trữ tải gốc bằng ID. Không có gì, tôi có thể thấy, một trường hợp các lệnh được chạy với một tập hợp tổng hợp (thay vào đó, trước tiên bạn sẽ chạy truy vấn để lấy tập hợp tổng hợp, sau đó liệt kê tập hợp và đưa ra lệnh cho từng tập hợp.
Do đó, trong bối cảnh bạn sẽ sửa đổi tổng hợp, tôi mong muốn kho lưu trữ trả về thực thể (còn gọi là gốc tổng hợp).
2) Trình xử lý truy vấn hoàn toàn không chạm vào tập hợp; thay vào đó, chúng làm việc với các phép chiếu của tập hợp - các đối tượng giá trị mô tả trạng thái của tập hợp / tập hợp tại một thời điểm nào đó. Vì vậy, hãy nghĩ ProjectionDTO, thay vì AggregateDTO, và bạn có ý tưởng đúng.
Trong bối cảnh nơi bạn sẽ chạy các truy vấn dựa trên tổng hợp, chuẩn bị hiển thị, v.v., tôi mong đợi sẽ thấy một DTO hoặc bộ sưu tập DTO, được trả về, thay vì một thực thể.
Tất cả các getCustomerByProperty
cuộc gọi của bạn trông giống như các truy vấn đối với tôi, vì vậy chúng sẽ rơi vào loại sau. Có lẽ tôi muốn sử dụng một điểm vào duy nhất để tạo bộ sưu tập, vì vậy tôi sẽ tìm kiếm xem
getCustomersThatSatisfy(Specification spec)
là một lựa chọn hợp lý; các trình xử lý truy vấn sau đó sẽ xây dựng các đặc tả thích hợp từ các tham số đã cho và chuyển đặc tả đó vào kho lưu trữ. Nhược điểm là chữ ký thực sự gợi ý rằng kho lưu trữ là một bộ sưu tập trong bộ nhớ; Tôi không rõ ràng rằng vị ngữ mua cho bạn nhiều nếu kho lưu trữ chỉ là một bản tóm tắt của việc chạy một câu lệnh SQL đối với cơ sở dữ liệu quan hệ.
Có một số mô hình có thể giúp đỡ, mặc dù. Ví dụ, thay vì xây dựng đặc tả bằng tay, hãy chuyển đến kho lưu trữ một mô tả về các ràng buộc và cho phép thực hiện kho lưu trữ để quyết định những việc cần làm.
Cảnh báo: java giống như gõ được phát hiện
interface CustomerRepository {
interface ConstraintBuilder {
void setLastName();
void setFirstName();
}
interface ConstraintDescriptor {
void copyTo(ConstraintBuilder builder);
}
List<CustomerProjection> getCustomersThatSatisfy(ConstraintDescriptor descriptor);
}
SQLBackedCustomerRepository implements CustomerRepository {
List<CustomerProjection> getCustomersThatSatisfy(ConstraintDescriptor descriptor) {
WhereClauseBuilder builder = new WhereClauseBuilder();
descriptor.copyTo(builder);
Query q = createQuery(builder.build());
//...
}
}
CollectionBackedCustomerRepository implements CustomerRepository {
List<CustomerProjection> getCustomersThatSatisfy(ConstraintDescriptor descriptor) {
PredicateBuilder builder = new PredicateBuilder();
descriptor.copyTo(builder);
Predicate p = builder.build();
// ...
}
class MatchLastName implements CustomerRepository.ConstraintDescriptor {
private final lastName;
// ...
void copyTo(CustomerRepository.ConstraintBuilder builder) {
builder.setLastName(this.lastName);
}
}
Tóm lại: sự lựa chọn giữa việc cung cấp tổng hợp và cung cấp DTO phụ thuộc vào những gì bạn đang mong đợi người tiêu dùng sẽ làm với nó. Tôi đoán sẽ là một triển khai cụ thể hỗ trợ một giao diện cho từng bối cảnh.
GetCustomerByName('John Smith')
trở lại nếu bạn có hai mươi John Smith trong cơ sở dữ liệu của bạn? Có vẻ như bạn cho rằng không có hai người có cùng tên.