คำสั่ง CQRS ควรจะตรวจสอบและแปลงเป็นวัตถุโดเมนอย่างไร?


22

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

แต่น่าเสียดายมากตั้งแต่ต้นฉันได้รับการดิ้นรนกับปัญหาที่ฉันควรวางตรรกะทางธุรกิจในสถาปัตยกรรมประเภทนี้

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

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

ดังนั้นคำถามที่แท้จริงคือตรรกะตรงไหน?

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

สมมติว่าการรวมCarใช้สององค์ประกอบ:

  • Transmission,
  • Engine.

วัตถุทั้งสองTransmissionและEngineค่าจะแสดงเป็นประเภทซุปเปอร์และมีตามประเภทย่อยAutomaticและManualการส่งสัญญาณหรือPetrolและElectricเครื่องยนต์ตามลำดับ

ในโดเมนนี้การใช้ชีวิตที่สร้างขึ้นอย่างประสบความสำเร็จTransmissionไม่ว่าจะเป็นAutomaticหรือManualหรือประเภทใดประเภทหนึ่งEngineก็ใช้ได้ดี แต่การCarรวมรวมจะมีกฎใหม่สองสามข้อใช้งานได้เฉพาะเมื่อTransmissionและEngineวัตถุถูกใช้ในบริบทเดียวกัน กล่าวคือ:

  • เมื่อรถใช้เครื่องยนต์ชนิดส่งได้รับอนุญาตเพียงอย่างเดียวคือElectricAutomatic
  • เมื่อรถใช้เครื่องยนต์มันอาจจะมีประเภทของการอย่างใดอย่างหนึ่งPetrolTransmission

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

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

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

ขณะนี้ฉันกำลังใช้คำสั่งและสร้างการรวมจากคำสั่งภายในตัวจัดการคำสั่งที่รับผิดชอบ แต่เมื่อฉันทำสิ่งนี้ฉันควรจะมีเครื่องมือตรวจสอบคำสั่งมันจะไม่มีอะไรเลยเพราะCreateCarคำสั่งควรมีอยู่แล้วมันจะมีส่วนประกอบที่ฉันรู้ว่าถูกต้องในกรณีที่แยกต่างหาก แต่การรวมอาจพูดแตกต่างกัน


ลองจินตนาการถึงสถานการณ์ที่แตกต่างกันที่ผสมกระบวนการตรวจสอบที่แตกต่างกัน - การสร้างผู้ใช้ใหม่โดยใช้CreateUserคำสั่ง

คำสั่งมีของผู้ใช้ซึ่งจะได้รับการสร้างและของพวกเขาIdEmail

ระบบระบุกฎต่อไปนี้สำหรับที่อยู่อีเมลของผู้ใช้:

  • ต้องไม่ซ้ำกัน,
  • ต้องไม่ว่างเปล่า
  • ต้องมีอักขระไม่เกิน 100 ตัว (ความยาวสูงสุดของคอลัมน์ db)

ในกรณีนี้แม้ว่าการมีอีเมลที่ไม่ซ้ำกันเป็นกฎทางธุรกิจการตรวจสอบในการรวมทำให้มีเหตุผลน้อยมากเพราะฉันจะต้องโหลดทั้งชุดของอีเมลปัจจุบันในระบบไปยังหน่วยความจำและตรวจสอบอีเมลในคำสั่ง เทียบกับการรวม ( Eeeek! Something, some , performance,. ) ด้วยเหตุนี้ฉันจะย้ายการตรวจสอบนี้ไปยังตัวตรวจสอบคำสั่งซึ่งจะUserRepositoryเป็นการอ้างอิงและใช้ที่เก็บเพื่อตรวจสอบว่ามีผู้ใช้ที่มีอีเมลในคำสั่งอยู่แล้ว

เมื่อพูดถึงเรื่องนี้มันก็สมเหตุสมผลที่จะใส่กฎอีเมลอีกสองฉบับในตัวตรวจสอบคำสั่งด้วยเช่นกัน แต่ฉันมีความรู้สึกว่ากฎควรจะปรากฏจริง ๆ ในการUserรวมและผู้ตรวจสอบคำสั่งควรตรวจสอบเกี่ยวกับเอกลักษณ์และหากการตรวจสอบสำเร็จฉันควรดำเนินการเพื่อสร้างการUserรวมในCreateUserCommandHandlerและส่งไปยังพื้นที่เก็บข้อมูลที่จะบันทึก

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

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


1การทำงานในฐานะนักพัฒนา PHP ที่รับผิดชอบในการสร้างระบบ RESTful การตีความ CQRS ของฉันเบี่ยงเบนไปเล็กน้อยจากวิธีการประมวลผลคำสั่ง asyncมาตรฐานเช่นบางครั้งส่งคืนผลลัพธ์จากคำสั่งเนื่องจากต้องการคำสั่งประมวลผลแบบซิงโครนัส


ต้องการรหัสตัวอย่างฉันคิดว่า วัตถุคำสั่งของคุณมีลักษณะอย่างไรและคุณสร้างมันขึ้นที่ใด
Ewan

@Ewan ฉันจะเพิ่มตัวอย่างโค้ดในวันนี้หรือพรุ่งนี้ ออกเดินทางในอีกไม่กี่นาที
Andy

การเป็นโปรแกรมเมอร์ PHP ฉันขอแนะนำให้ดูการใช้งาน CQRS + ES ของฉัน: github.com/xprt64/cqrs-es
Constantin Galbenu

@ConstantinGALBENU เราควรพิจารณาการตีความ CQRS ของ Greg Young ให้ถูกต้อง (ซึ่งเราน่าจะเข้าใจ) จากนั้นความเข้าใจของคุณเกี่ยวกับ CQRS นั้นไม่ถูกต้อง - หรืออย่างน้อยการใช้ PHP ของคุณก็คือ คำสั่งจะไม่ได้รับการจัดการโดยมวลรวมโดยตรง คำสั่งจะถูกจัดการโดยตัวจัดการคำสั่งซึ่งอาจสร้างการเปลี่ยนแปลงในการรวมซึ่งจากนั้นผลิตเหตุการณ์ที่จะใช้สำหรับการจำลองสถานะ
Andy

ฉันไม่คิดว่าการตีความของเราแตกต่าง คุณต้องขุดให้มากขึ้นใน DDD (ที่ระดับยุทธวิธีของมวลรวม) หรือเปิดตาของคุณให้กว้างขึ้น มีอย่างน้อยสองรูปแบบของการใช้ CQRS ฉันใช้หนึ่งในนั้น การใช้งานของฉันคล้ายกับโมเดล Actor มากขึ้นและทำให้เลเยอร์แอปพลิเคชันบางมากซึ่งเป็นสิ่งที่ดีเสมอ CommandDispatcherผมตั้งข้อสังเกตว่ามีเป็นจำนวนมากของการทำสำเนารหัสภายในบริการแอปเหล่านั้นและตัดสินใจที่จะเปลี่ยนพวกเขาด้วย
Constantin Galbenu

คำตอบ:


22

คำตอบต่อไปนี้อยู่ในบริบทของสไตล์ CQRS ซึ่งได้รับการโปรโมตโดยcqrs.nuซึ่งคำสั่งมาถึงการรวมโดยตรง ในรูปแบบสถาปัตยกรรมนี้แอปพลิเคชันบริการจะถูกแทนที่ด้วยองค์ประกอบโครงสร้างพื้นฐาน ( CommandDispatcher ) ที่ระบุรวมโหลดโหลดส่งคำสั่งแล้วยังคงรวม (เป็นชุดของเหตุการณ์หากใช้การจัดหากิจกรรม)

ดังนั้นคำถามที่แท้จริงคือตรรกะตรงไหน?

ตรรกะ (การตรวจสอบ) มีหลายประเภท แนวคิดทั่วไปคือการดำเนินการตรรกะเร็วที่สุด - ล้มเหลวอย่างรวดเร็วถ้าคุณต้องการ ดังนั้นสถานการณ์มีดังนี้:

  • โครงสร้างของวัตถุคำสั่งนั้น คอนสตรัคของคำสั่งมีฟิลด์ที่จำเป็นบางอย่างที่จะต้องมีอยู่สำหรับคำสั่งที่จะสร้าง; นี่เป็นการตรวจสอบครั้งแรกและเร็วที่สุด เห็นได้ชัดว่ามีอยู่ในคำสั่ง
  • การตรวจสอบความถูกต้องของฟิลด์ระดับต่ำเช่นความว่างเปล่าของบางฟิลด์ (เช่นชื่อผู้ใช้) หรือรูปแบบ (ที่อยู่อีเมลที่ถูกต้อง) การตรวจสอบประเภทนี้ควรมีอยู่ในคำสั่งของตัวเองในตัวสร้าง มีอีกรูปแบบหนึ่งของการมีisValidวิธีการ แต่สิ่งนี้ดูไม่มีประโยชน์สำหรับฉันเพราะมีคนจำต้องเรียกวิธีนี้เมื่อจริง ๆ แล้วการสร้างคำสั่งที่ประสบความสำเร็จน่าจะเพียงพอแล้ว
  • แยกcommand validatorsคลาสที่มีความรับผิดชอบในการตรวจสอบคำสั่ง ฉันใช้การตรวจสอบประเภทนี้เมื่อฉันต้องการตรวจสอบข้อมูลจากหลายแหล่งรวมหรือแหล่งภายนอก คุณสามารถใช้สิ่งนี้เพื่อตรวจสอบเอกลักษณ์ของชื่อผู้ใช้ Command validatorsอาจมีการพึ่งพาการฉีดใด ๆ เช่นที่เก็บ โปรดทราบว่าการตรวจสอบความถูกต้องนี้จะสอดคล้องกับการสรุปรวม (เช่นเมื่อผู้ใช้ถูกสร้างขึ้นผู้ใช้อื่นที่มีชื่อผู้ใช้เดียวกันสามารถสร้างได้ในระหว่างนี้)! นอกจากนี้อย่าพยายามวางตรรกะที่นี่ที่ควรจะอยู่ในการรวม! เครื่องมือตรวจสอบคำสั่งนั้นแตกต่างจากผู้จัดการ Sagas / Process ซึ่งสร้างคำสั่งตามเหตุการณ์
  • วิธีการรวมที่ได้รับและประมวลผลคำสั่ง นี่เป็นการตรวจสอบล่าสุด (ชนิด) ที่เกิดขึ้น การรวมข้อมูลจะแยกข้อมูลจากคำสั่งและใช้ตรรกะทางธุรกิจหลักที่ยอมรับ (ทำการเปลี่ยนแปลงสถานะของมัน) หรือปฏิเสธ ตรรกะนี้มีการตรวจสอบในลักษณะที่สอดคล้องที่แข็งแกร่ง นี่คือด่านสุดท้ายของการป้องกัน ในตัวอย่างของคุณWhen a car uses Electric engine the only allowed transmission type is Automaticควรตรวจสอบกฎที่นี่

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

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

การทำงานในฐานะนักพัฒนา PHP ที่รับผิดชอบในการสร้างระบบ RESTful การตีความ CQRS ของฉันเบี่ยงเบนไปเล็กน้อยจากวิธีการประมวลผลคำสั่ง async มาตรฐานเช่นบางครั้งส่งคืนผลลัพธ์จากคำสั่งเนื่องจากต้องการประมวลผลคำสั่งแบบซิงโครนัส

ฉันเป็นโปรแกรมเมอร์ PHP และฉันจะไม่ส่งคืนสิ่งใดจากเครื่องมือจัดการคำสั่งของฉัน (วิธีการรวมในรูปแบบhandleSomeCommand) อย่างไรก็ตามฉันมักจะส่งคืนข้อมูลไปยังไคลเอนต์ / เบราว์เซอร์ในHTTP responseตัวอย่างเช่น ID ของรากรวมที่สร้างขึ้นใหม่หรือบางสิ่งบางอย่างจากรูปแบบการอ่าน แต่ฉันไม่เคยกลับ (จริงๆไม่เคย ) อะไรจากวิธีการรวมคำสั่งของฉัน ความจริงง่ายๆที่คำสั่งได้รับการยอมรับ (และประมวลผล - เรากำลังพูดถึงการประมวลผล PHP แบบซิงโครนัสใช่มั้ย?!) ก็เพียงพอแล้ว

เรากลับสิ่งที่เบราว์เซอร์ (และ CQRS ยังคงทำโดยหนังสือ) เพราะCQRS ไม่ได้เป็นสถาปัตยกรรมระดับสูง

ตัวอย่างของการทำงานของตัวตรวจสอบความถูกต้องของคำสั่ง:

พา ธ ของคำสั่งผ่านตัวตรวจสอบคำสั่งผ่านไปยังส่วนรวม


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

@ king-side-slide ไม่ได้ถ้าคุณมีEmailAddressวัตถุค่าที่ตรวจสอบตัวเอง
Constantin Galbenu

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

แนวคิดของ "ตัวตรวจสอบคำสั่ง" ก็ไม่จำเป็นเช่นกัน เป้าหมายไม่ใช่เพื่อป้องกันการสร้างและส่งคำสั่งที่ไม่ถูกต้อง เป้าหมายคือเพื่อป้องกันพวกเขาจากการดำเนินการ ตัวอย่างเช่นฉันสามารถส่งผ่านข้อมูลใด ๆ ที่ฉันต้องการด้วย URL หากไม่ถูกต้องระบบจะปฏิเสธคำขอของฉัน คำสั่งยังคงสร้างและส่งออกไป หากคำสั่งนั้นต้องการการรวมที่หลากหลายเพื่อการตรวจสอบความถูกต้อง (เช่นการรวบรวมผู้ใช้เพื่อตรวจสอบความเป็นเอกลักษณ์ของอีเมล) บริการโดเมนจะเหมาะสมกว่า วัตถุเช่น "ตัวตรวจสอบความถูกต้อง x" มักจะเป็นสัญลักษณ์ของแบบจำลองโลหิตจางที่ข้อมูลถูกแยกออกจากพฤติกรรม
สไลด์ข้างกษัตริย์

1
@ UserCanPlaceOrdersOnlyIfHeIsNotLockedValidatorคิงแบบสไลด์ด้านข้างเช่นคอนกรีต คุณจะเห็นว่านี่เป็นโดเมนแยกต่างหากของคำสั่งซื้อดังนั้นจึงไม่สามารถตรวจสอบได้โดย OrderAggregate เอง
Constantin Galbenu

6

หลักฐานพื้นฐานหนึ่งของ DDD คือโมเดลโดเมนตรวจสอบตัวเอง นี่เป็นแนวคิดที่สำคัญเพราะจะช่วยยกระดับโดเมนของคุณในฐานะผู้รับผิดชอบในการตรวจสอบให้แน่ใจว่ามีการบังคับใช้กฎเกณฑ์ทางธุรกิจของคุณ นอกจากนี้ยังช่วยให้รูปแบบโดเมนของคุณเป็นจุดสนใจสำหรับการพัฒนา

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

เพียงแค่ขยายตัวอย่างของคุณเพื่อรวมChangeEmailคำสั่งเราสามารถอธิบายได้อย่างสมบูรณ์ว่าทำไมคุณไม่ต้องการตรรกะทางธุรกิจใด ๆ ของคุณในโครงสร้างพื้นฐานคำสั่งของคุณเพราะคุณจะต้องทำซ้ำกฎของคุณ:

  • อีเมลต้องไม่ว่างเปล่า
  • อีเมลต้องไม่เกิน 100 ตัวอักษร
  • อีเมลต้องไม่ซ้ำกัน

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

อ้า! โดยที่ในใจมันจะกลายเป็นที่ชัดเจนอย่างมากว่าUserRepository(ของคุณเก็บในหน่วยความจำของคุณUsers) อาจเป็นผู้สมัครที่ดีกว่าสำหรับการบังคับใช้ค่าคงที่นี้ วิธีการ "บันทึก" น่าจะเป็นสถานที่ที่เหมาะสมที่สุดในการรวมเช็ค (ซึ่งคุณสามารถUserEmailAlreadyExistsยกเว้นได้) อีกวิธีหนึ่งโดเมนUserServiceสามารถรับผิดชอบในการสร้างใหม่Usersและอัปเดตแอตทริบิวต์ของพวกเขา

การล้มเหลวอย่างรวดเร็วเป็นวิธีการที่ดี แต่สามารถทำได้เฉพาะที่และเวลาที่เหมาะสมกับรุ่นที่เหลือ มันอาจเป็นการดึงดูดอย่างยิ่งในการตรวจสอบพารามิเตอร์ในวิธีการบริการแอปพลิเคชัน (หรือคำสั่ง) ก่อนที่จะดำเนินการเพิ่มเติมเพื่อพยายามที่จะตรวจจับความล้มเหลวเมื่อคุณ (นักพัฒนา) ทราบว่าการโทรจะล้มเหลว แต่ในการทำเช่นนั้นคุณจะมีความรู้ที่ซ้ำกัน (และรั่วไหล) ในลักษณะที่อาจต้องมีการปรับปรุงมากกว่าหนึ่งรหัสเมื่อกฎทางธุรกิจเปลี่ยนไป


2
ฉันเห็นด้วยกับสิ่งนี้ การอ่านของฉันจนถึงขณะนี้ (ที่ไม่มี CQRS) บอกฉันว่าการตรวจสอบควรอยู่ในรูปแบบโดเมนเพื่อปกป้องค่าคงที่ ตอนนี้ฉันกำลังอ่าน CQRS มันกำลังบอกให้ฉันใส่การตรวจสอบในวัตถุคำสั่ง ดูเหมือนว่าจะเป็นเคาน์เตอร์ที่เข้าใจง่าย คุณรู้จักตัวอย่างใดบ้างเช่นใน GitHub ที่มีการตรวจสอบความถูกต้องในรูปแบบโดเมนแทนคำสั่ง? +1
w0051977
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.