วิธีจัดการข้อผิดพลาดหลังการตรวจสอบความถูกต้องในคำสั่ง (DDD + CQRS)


18

ตัวอย่างเช่นเมื่อคุณส่งแบบฟอร์มลงทะเบียนคุณจะต้องตรวจสอบในDomain Model( WriteModelในCQRS) ว่ามันอยู่ในสถานะที่ถูกต้อง (ตัวอย่างไวยากรณ์ที่อยู่อีเมลอายุ ฯลฯ )

จากนั้นคุณสร้างและส่งไปยังCommandCommand Bus

ฉันเข้าใจว่าคำสั่งไม่ควรส่งคืนสิ่งใด

ดังนั้นคุณจะจัดการกับข้อผิดพลาดได้Command Busอย่างไร (ตัวอย่างเช่นผู้ใช้ที่ลงทะเบียน 1 วินาทีก่อนหน้านี้ด้วยเหมือนกันusername/email)

คุณรู้ได้อย่างไรว่าคำสั่งนั้นล้มเหลวและคุณรู้ได้อย่างไรว่ามีข้อผิดพลาด?


2
คุณไม่ต้องการบัสเหตุการณ์ ทำไมทุกคนคิดว่าคุณต้องการบัสเหตุการณ์เมื่อใช้งาน CQRS ฉันไม่รู้ CQRS นั้นหมายความว่าคุณแยกการเขียนและอ่านแยกจากกันโดยสิ้นเชิง คุณมี CQRS ตราบเท่าที่คุณทำเช่นนั้น คำสั่งของคุณไม่จำเป็นต้องเป็นแบบอะซิงโครนัส หากคำสั่งแบบซิงโครนัสที่รายงานข้อผิดพลาดใช้ได้ผลสำหรับคุณให้ทำเช่นนั้น
Andy

1
คำสั่งที่ไม่ควรกลับอะไรเมื่อประสบความสำเร็จ แนวคิดเริ่มต้นจากCQSซึ่งมีความหมายว่าคำสั่งยังคงสามารถยกเว้นข้อผิดพลาด สิ่งที่คุณกำลังอธิบายคือคำสั่งทางเดียว ดูคำตอบนี้เกี่ยวกับสิ่งนั้น
Kasey Speakman

คำตอบ:


4

ฉันเข้าใจว่าคำสั่งไม่ควรส่งคืนสิ่งใด

นั่นคือมุมมองหนึ่ง แต่มันไม่ได้ตั้งอยู่ในหินทั้งหมด พิจารณาเขียน (PUT, POST, DELETE) ใน HTTP - ข้อความเหล่านี้ทั้งหมดเป็นคำสั่งในแง่ที่ว่าพวกเขาเป็นข้อความที่มีการร้องขอว่าสถานะการเปลี่ยนแปลงทรัพยากรและพวกเขากลับตอบสนองทั้งหมด

ดังนั้นคุณจะจัดการข้อผิดพลาดที่นอกเหนือจาก Command Bus ได้อย่างไร (ตัวอย่างเช่นผู้ใช้ที่ลงทะเบียน 1 วินาทีก่อนหน้านี้ด้วยชื่อผู้ใช้ / อีเมลเดียวกัน)

คุณรู้ได้อย่างไรว่าคำสั่งนั้นล้มเหลวและคุณรู้ได้อย่างไรว่ามีข้อผิดพลาด?

ดังนั้นในกรณีที่คุณกำลังสื่อสารโดยตรงกับตัวจัดการคำสั่งข้อความที่ส่งคืนเป็นวิธีที่เหมาะสมอย่างยิ่งที่จะยอมรับว่าคำสั่งนั้นได้รับและประมวลผลแล้ว

หากคุณใช้มิดเดิลแวร์ชิ้นหนึ่งเช่นรถบัสที่ป้องกันไม่ให้คุณสื่อสารกับเป้าหมายโดยตรงจากนั้นฉันขอแนะนำให้คุณดูรูปแบบการส่งข้อความแบบอะซิงโครนัส - คุณจะให้ตัวจัดการคำสั่งส่งข้อความกลับไปที่ โทร?

แนวคิดหนึ่งคือการสมัครสมาชิกผลลัพธ์ของคำสั่ง สิ่งนี้ยืมมาจากแนวคิดบางอย่างในรูปแบบการรวมองค์กรของ Hohpe แนวคิดพื้นฐานคือเนื่องจากไคลเอนต์คุ้นเคยกับข้อความคำสั่งที่ถูกส่งจึงอยู่ในตำแหน่งที่ดีในการสมัครรับข่าวสารใหม่ ๆ ที่เผยแพร่อันเป็นผลมาจากข้อความคำสั่ง ตัวจัดการคำสั่งหลังจากบันทึกข้อมูลลงในสมุดบันทึกเผยแพร่กิจกรรมที่ประกาศว่าการเปลี่ยนแปลงสำเร็จและลูกค้าสมัครรับกิจกรรมเหล่านั้น - รับรู้เหตุการณ์ที่ถูกต้องโดยพิจารณาถึงความบังเอิญของตัวระบุต่าง ๆ ในข้อความ (รหัสสาเหตุรหัสสหสัมพันธ์และอื่น ๆ )

วิธีการทางเลือกนั้นค่อนข้างตรงไปกว่า หนึ่งจะรวมอยู่ในข้อความโทรกลับซึ่งสามารถเรียกใช้โดยจัดการคำสั่งหลังจากข้อความได้รับการจัดการเรียบร้อยแล้ว

ทางเลือกที่คล้ายกันมากคือการจองพื้นที่ในข้อความคำสั่งสำหรับตัวจัดการคำสั่งเพื่อเขียนการตอบรับ - เนื่องจากไคลเอนต์มีข้อความคำสั่งเป็นปัญหาวงจรเสร็จสมบูรณ์แล้ว คิดว่า " คำสัญญา " หรือ " อนาคตที่สมบูรณ์" ข้อความแจ้งให้ตัวจัดการคำสั่งทราบตำแหน่งที่จะเขียนการตอบรับ การทำเช่นนั้นจะส่งสัญญาณไปยังไคลเอนต์ (latch นับถอยหลัง) ที่มีการตอบรับ

และแน่นอนว่าคุณมีตัวเลือกเพิ่มเติมในการลบมิดเดิลแวร์ที่ดูเหมือนว่าจะได้รับไปในทางที่จะทำสิ่งที่ถูกต้องได้ง่ายๆ

ตัวอย่างเช่นผู้ใช้ที่ลงทะเบียน 1 วินาทีก่อนหน้านี้ด้วยชื่อผู้ใช้ / อีเมลเดียวกัน

หากคุณจัดการกับการลงทะเบียนผู้ใช้ idempotently นั่นไม่จำเป็นว่าจะเป็นข้อผิดพลาด - การทำซ้ำข้อความจนกว่าจะพบการตอบสนองเป็นวิธีการทั่วไปเพื่อให้มั่นใจว่ามีการส่งมอบอย่างน้อยหนึ่งครั้ง


2

ตัวอย่างเช่นเมื่อคุณส่งแบบฟอร์มลงทะเบียนคุณจะต้องตรวจสอบในรูปแบบโดเมน (WriteModel ใน CQRS) ว่ามันอยู่ในสถานะที่ถูกต้อง (ตัวอย่างไวยากรณ์ที่อยู่อีเมลอายุ ฯลฯ )

การตรวจสอบมีหลายประเภท การตรวจสอบความถูกต้องเมื่อคุณตรวจสอบไวยากรณ์ที่อยู่อีเมลและรูปแบบอายุเป็นประเภทการตรวจสอบความถูกต้องที่คำสั่งสามารถทำได้ นี่ไม่ใช่ปัญหาโดเมนจริงๆ อาจดูเหมือนว่าเพราะผู้เชี่ยวชาญด้านโดเมนบางคนจะบอกคุณเกี่ยวกับข้อมูลจำเพาะเหล่านั้น แต่คุณควรทำการตรวจสอบความถูกต้องแบบนี้ในการสร้างคำสั่ง ในความเป็นจริงแนวคิดทั่วไปคือการตรวจสอบความถูกต้องโดยเร็วที่สุดเพราะหลังจากที่คำสั่งถูกสร้างขึ้นและส่งไปยัง BUS มันมีความซับซ้อนในการดำเนินการ

ดังนั้นคุณจะจัดการข้อผิดพลาดที่นอกเหนือจาก Command Bus ได้อย่างไร (ตัวอย่างเช่นผู้ใช้ที่ลงทะเบียน 1 วินาทีก่อนหน้านี้ด้วยชื่อผู้ใช้ / อีเมลเดียวกัน)

การตรวจสอบแบบนี้มีการพูดคุยกันมากมายในชุมชน CQRS ตั้งแต่เริ่มต้นของ CQRS จะทำยังไงดี? มันถกเถียงกันมาก ฉันใช้วิธีการต่อไปนี้เป็นการส่วนตัว: ก่อนที่คำสั่งจะถูกส่งไปที่ BUS ฉันจะทำเครื่องหมายชื่อผู้ใช้ / อีเมลตามที่ได้รับจากส่วนกลาง (เช่นข้อ จำกัด ของดัชนีเฉพาะในชื่อผู้ใช้ / อีเมล) หลังจากนั้นฉันก็ส่งคำสั่ง ข้อเสียคือถ้าคำสั่งล้มเหลวในช่วงเวลาสั้น ๆ ที่มีการใช้ชื่อผู้ใช้และไม่ได้ใช้ สิ่งนี้เป็นที่ยอมรับได้สำหรับธุรกิจของฉันซึ่งเป็นไปได้สำหรับธุรกิจของคุณ

คุณรู้ได้อย่างไรว่าคำสั่งนั้นล้มเหลวและคุณรู้ได้อย่างไรว่ามีข้อผิดพลาด?

หากคำสั่งแบบอะซิงโครนัสถูกปฏิเสธโดยการรวมเนื่องจากค่าคงที่ของโดเมนการวัดบางอย่างจะต้องดำเนินการโดยการออกคำสั่งการชดเชยซึ่งจะแจ้งผู้ออกคำสั่งอย่างใด (เช่นส่งอีเมลคำอธิบายว่าคำสั่งล้มเหลว)

ปัญหาของอีเมลซ้ำคือคุณไม่สามารถส่งอีเมลได้เพราะที่อยู่อีเมลนั้นเป็นของบุคคลอื่นนั่นคือสาเหตุที่ฉันตรวจสอบก่อนที่จะส่งคำสั่งไปที่รถบัส


1

ควรตรวจสอบความถูกต้องในมัณฑนากร จากนั้นคำสั่งใด ๆ ที่ต้องการการตรวจสอบความถูกต้องสามารถตกแต่งได้เช่นนี้

การตรวจสอบสามารถจัดการได้โดยมีข้อยกเว้นหากการส่งคืนโมฆะของคุณด้วยคำสั่งของคุณเพื่อให้สามารถรับได้ด้วยการโทรแบบซิงก์หรือแบบอะซิงก์พร้อมกับผลลัพธ์งานที่ส่งคืน

ความเป็นไปได้อีกอย่างก็คือคิดว่าการตรวจสอบความถูกต้องเป็นประเภทของ "คิวรี" ซึ่งจะส่งคืนผลลัพธ์การตรวจสอบ รันเคียวรีตรวจสอบความถูกต้องจากนั้นถ้าผ่านให้รันคำสั่ง นี่จะเป็นอีกทางเลือกในการตกแต่งภายใน


ฉันชอบวิธีการยกเว้นเพราะเป็นวิธีที่สะอาดที่สุด แต่ข้อยกเว้นนี้ไม่หนักเกินไปใช่ไหม
EresDev

1
HI @EresDev - ใช่พวกเขาหนัก แต่ฉันไม่รู้ว่าข้อมูลของคุณ "ถูกต้อง" ยังไง ให้พูดจาก 1,000 รายการ 2 ไม่ถูกต้อง ข้อยกเว้นอาจทำงานได้เนื่องจากเป็นเงื่อนไขที่ยอดเยี่ยมอย่างแท้จริง ตอนนี้ให้พิจารณา 1,000 รายการโดย 200 ไม่ถูกต้อง ด้วยสาเหตุดังกล่าวควรหลีกเลี่ยงข้อยกเว้นเนื่องจาก 20% ของข้อมูลของคุณไม่ถูกต้อง ดังนั้นฉันขอแนะนำให้คุณตัดสินใจว่าจะเลือกวิธีการนี้หรือไม่โดยพิจารณาจากความถูกต้องของข้อมูลปัจจุบันของคุณ :)
Jon Raynor

ฉันจะเพิ่มสิ่งนี้โดยบอกว่าถ้าเราเก็บตัวอย่างของแบบฟอร์มลงทะเบียนซึ่งฉันคิดว่าผู้ใช้ 50% หรือมากกว่านั้นใส่ข้อมูลที่ไม่ถูกต้องก่อนอื่นข้อยกเว้นก็ยังคงใช้ได้ ในแบ็กเอนด์ของเว็บแอปพลิเคชันคุณส่วนใหญ่ได้รับข้อมูลที่ถูกต้องเพราะส่วนหน้ายังทำการตรวจสอบ คุณจะได้รับหากมีบางสิ่งที่ไม่ผ่านการตรวจสอบความถูกต้องของส่วนหน้าโดยโอกาสที่หาได้ยากหรือหากมีคนหลงกล ดังนั้นข้อยกเว้นจะไม่เป็นไรมากในกรณีนี้
EresDev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.