มีชุมชนขนาดใหญ่ของคนที่ใช้ CQRS เพื่อใช้โดเมนของพวกเขา ความรู้สึกของฉันคือถ้าส่วนต่อประสานของที่เก็บของคุณคล้ายกับวิธีปฏิบัติที่ดีที่สุดที่พวกเขาใช้คุณจะไม่หลงทางมากเกินไป
ตามสิ่งที่ฉันเห็น ...
1) ตัวจัดการคำสั่งมักใช้ที่เก็บเพื่อโหลดการรวมผ่านที่เก็บ คำสั่งกำหนดเป้าหมายอินสแตนซ์เฉพาะของการรวม; ที่เก็บโหลดรูทตาม ID ไม่มีที่ฉันเห็นกรณีที่คำสั่งทำงานกับชุดรวม (ก่อนอื่นคุณต้องเรียกใช้แบบสอบถามเพื่อรับชุดรวมจากนั้นระบุชุดรวบรวมและออกคำสั่งให้แต่ละ
ดังนั้นในบริบทที่คุณจะปรับเปลี่ยนการรวมฉันคาดว่าที่เก็บจะส่งคืนเอนทิตี (หรือที่เรียกว่า root รวม)
2) ตัวจัดการคิวรีไม่ได้แตะมวลรวมเลย แต่จะทำงานร่วมกับการคาดการณ์ของวัตถุรวม - ค่าที่อธิบายสถานะของการรวม / การรวม ณ เวลาใดเวลาหนึ่ง ดังนั้นคิดว่า ProjectionDTO แทนที่จะเป็น AggregateDTO และคุณมีความคิดที่ถูกต้อง
ในบริบทที่คุณกำลังเรียกใช้คิวรีกับการรวมกันเพื่อเตรียมการแสดงและอื่น ๆ ฉันคาดว่าจะเห็น DTO หรือคอลเลกชัน DTO ส่งคืนแทนที่จะเป็นเอนทิตี
การgetCustomerByProperty
โทรทั้งหมดของคุณดูเหมือนจะเป็นข้อความค้นหาถึงฉันดังนั้นมันจะอยู่ในหมวดหมู่หลัง ฉันอาจต้องการใช้จุดเริ่มต้นเดียวเพื่อสร้างคอลเลกชันดังนั้นฉันจะดูว่า
getCustomersThatSatisfy(Specification spec)
เป็นทางเลือกที่สมเหตุสมผล ตัวจัดการเคียวรีจะสร้างข้อกำหนดที่เหมาะสมจากพารามิเตอร์ที่กำหนดและส่งข้อมูลจำเพาะนั้นไปยังที่เก็บ ข้อเสียคือลายเซ็นจริง ๆ แนะนำว่าพื้นที่เก็บข้อมูลเป็นคอลเลกชันในหน่วยความจำ ไม่ชัดเจนสำหรับฉันว่าเพรดิเคตจะซื้อคุณมากถ้าที่เก็บเป็นเพียงนามธรรมของการเรียกใช้คำสั่ง SQL กับฐานข้อมูลเชิงสัมพันธ์
มีรูปแบบบางอย่างที่สามารถช่วยได้ ตัวอย่างเช่นแทนที่จะสร้างข้อกำหนดด้วยตนเองให้ส่งคำอธิบายข้อ จำกัด ของพื้นที่เก็บข้อมูลและอนุญาตให้การนำพื้นที่เก็บข้อมูลไปใช้เพื่อตัดสินใจว่าจะทำอย่างไร
คำเตือน: จาวาชอบตรวจจับการพิมพ์
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);
}
}
โดยสรุป: ตัวเลือกระหว่างการให้ผลรวมและการนำเสนอ DTO นั้นขึ้นอยู่กับสิ่งที่คุณคาดหวังว่าผู้บริโภคจะทำ ฉันเดาว่าจะเป็นการนำไปปฏิบัติอย่างเป็นรูปธรรมอย่างหนึ่งซึ่งสนับสนุนอินเทอร์เฟซสำหรับแต่ละบริบท
GetCustomerByName('John Smith')
ถ้าคุณมี John Smith ยี่สิบคนในฐานข้อมูลของคุณ ดูเหมือนว่าคุณสมมติว่าไม่มีคนสองคนที่มีชื่อเหมือนกัน