วิธี DDD ในการดำเนินงาน CRUD ขั้นพื้นฐานในแอปพลิเคชันโดเมนเป็นศูนย์กลางที่ซับซ้อน


9

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

เรากำลังใช้ ORM (Entity framework) เพื่อคงอยู่

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

ในวิธี DDD โดยใช้เลเยอร์ดูเหมือนว่าการดำเนินการ CRUD จะผ่านชั้นโดเมน แต่อย่างน้อยในกรณีของเราสิ่งนี้ดูเหมือนจะไม่สมเหตุสมผล

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

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

ดังนั้นโดยพื้นฐานแล้วฉันกำลังแมปโมเดลข้อมูลกับโมเดลโดเมนดังนั้นจึงสามารถแมปกลับไปยังตัวแบบข้อมูลเพื่อคงอยู่ได้ มันสมเหตุสมผลแค่ไหน?

คำตอบ:


9

ลองจินตนาการว่าคุณใช้การสร้างหน้าการสร้างบัญชีของคุณในการโพสต์แบบฟอร์มไปยังวัตถุ EF โดยตรงจากนั้นจะบันทึกลงในฐานข้อมูล

ให้สมมติเพิ่มเติมว่าฐานข้อมูลมีข้อ จำกัด ต่าง ๆ ที่ป้องกันการป้อนข้อมูลผิดอย่างสมบูรณ์ บัญชีมักมีลูกค้า ฯลฯ

ดูเหมือนว่าทุกอย่างจะโอเค แต่แล้วธุรกิจก็สร้างกฎใหม่

  • บัญชีที่สร้างในวันพฤหัสบดีจะได้รับอัตราดอกเบี้ย 2% (สมมติว่าอัตราดอกเบี้ยเป็นหนึ่งในฟิลด์บัญชี)

ตอนนี้คุณต้องวางตรรกะนี้ที่ไหนสักแห่งและคุณไม่มีวัตถุโดเมนที่จะนำมันมา

DDD ถือว่าคุณมีกฎเหล่านี้อยู่เสมอและคุณอาจจะทำเช่นนั้น การสร้างบัญชีจะต้องมีการตรวจสอบต่าง ๆ บันทึกการตรวจสอบและอื่น ๆ ไม่ใช่เพียงแค่ 'เขียนแถวไปยังฐานข้อมูล'

วางแผนโดเมนของคุณออกสมมติว่าไม่มีการติดตาหรือ MVC ควบคุมด้วยเหตุผลพิเศษ. ให้แน่ใจว่าคุณสามารถจับภาพทั้งหมดของความต้องการและพวกเขาทั้งหมดในรูปแบบโดเมน


3
นั่นเป็นวิธีที่ดีในการวาง ฉันเกลียดการหากฎเกณฑ์ทางธุรกิจผสมกับรายละเอียดฐานข้อมูล +1
candied_orange

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

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

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

..... หรืออาจจะมีรูปแบบบัญชีการลงทุนในโดเมนเป็น overkill สำหรับการดำเนินการ CRUD และควรมีบางคุณสมบัติการตรวจสอบความถูกต้องใช้หรืออะไร
wired_in

7

มันสมเหตุสมผลแค่ไหน?

คำตอบสั้น ๆ : มันไม่ได้

คำตอบที่ยาวกว่า: รูปแบบเฮฟวี่เวทสำหรับการพัฒนาแบบจำลองโดเมนไม่ได้ใช้กับส่วนต่าง ๆ ของโซลูชันของคุณที่เป็นเพียงฐานข้อมูล

อุดี Dahan มีข้อสังเกตที่น่าสนใจซึ่งอาจช่วยชี้แจงเรื่องนี้

Dahan คิดว่าบริการต้องมีทั้งฟังก์ชั่นและข้อมูลบางอย่าง หากไม่มีข้อมูลแสดงว่าเป็นเพียงฟังก์ชัน หากสิ่งที่มันทำคือการดำเนินการ CRUD กับข้อมูลแล้วมันเป็นฐานข้อมูล

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

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

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

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

ในวิธี DDD โดยใช้เลเยอร์ดูเหมือนว่าการดำเนินการ CRUD จะผ่านชั้นโดเมน แต่อย่างน้อยในกรณีของเราสิ่งนี้ดูเหมือนจะไม่สมเหตุสมผล

ที่เหมาะสมสำหรับกรณีที่ฐานข้อมูลเป็นหนังสือของการบันทึก

Ouarzy วางวิธีนี้

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

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

เราใช้โมเดลโดเมนเพื่อจัดการข้อมูลที่อยู่ภายในโดเมน ข้อมูลจากภายนอกโดเมนมีการจัดการที่อื่นแล้ว - เราเพิ่งแคชสำเนา

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

ดังนั้นเราอาจมีบริบทที่ถูก จำกัด สองจุดที่นี่? แต่ละแบบที่แตกต่างกันสำหรับinvestment account

อาจจะ. ฉันลังเลที่จะติดแท็กมันเป็นบริบทที่มีขอบเขตเพราะมันไม่ชัดเจนว่ากระเป๋าอื่น ๆ มาพร้อมกับกระเป๋าใบนั้น อาจเป็นได้ว่าคุณมีสองบริบทมันอาจเป็นบริบทหนึ่งที่มีความแตกต่างเล็กน้อยในภาษาที่แพร่หลายที่คุณยังไม่ได้เลือก

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

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


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

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

2

ในโดเมนของคุณคุณไม่จำเป็นต้องรู้ว่าฐานข้อมูลยังมีอยู่

โดเมนของคุณเกี่ยวกับกฎเกณฑ์ทางธุรกิจ สิ่งที่ต้องอยู่รอดเมื่อ บริษัท ที่สร้างฐานข้อมูลของคุณพ้นจากธุรกิจ นั่นคือถ้าคุณต้องการให้ บริษัท ของคุณอยู่รอด เป็นเรื่องที่ดีมากเมื่อกฎเหล่านั้นไม่สนใจว่าคุณได้เปลี่ยนแปลงวิธีการคงอยู่ของข้อมูล

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

ลุงบ๊อบกล่าวถึงสิ่งที่จะนำข้อมูลของคุณไปใช้:

โดยทั่วไปข้อมูลที่ข้ามขอบเขตคือโครงสร้างข้อมูลอย่างง่าย คุณสามารถใช้โครงสร้างพื้นฐานหรือวัตถุการถ่ายโอนข้อมูลง่าย ๆ ถ้าคุณต้องการ หรือข้อมูลสามารถเป็นข้อโต้แย้งในการเรียกใช้ฟังก์ชัน หรือคุณสามารถบรรจุลงใน hashmap หรือสร้างลงในวัตถุ

สิ่งสำคัญคือโครงสร้างข้อมูลที่แยกได้ง่ายถูกส่งผ่านข้ามขอบเขต เราไม่ต้องการโกงและส่งผ่านเอนทิตีหรือแถวฐานข้อมูล เราไม่ต้องการให้โครงสร้างข้อมูลมีการพึ่งพาใด ๆ ที่ละเมิดกฎการพึ่งพา

[…] เมื่อเราส่งข้อมูลข้ามขอบเขตมันจะอยู่ในรูปแบบที่สะดวกที่สุดสำหรับวงใน

สถาปัตยกรรมที่สะอาด

เขายังอธิบายว่าเลเยอร์ภายนอกของคุณควรเป็นปลั๊กอินไปยังเลเยอร์ภายในของคุณได้อย่างไร

ทำความสะอาดแผ่นโกงสถาปัตยกรรม

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

ไม่ว่าคุณจะตัดสินใจว่าโดเมนของคุณเป็นเพียงฐานข้อมูลเท่านั้น ในกรณีนี้ภาษาโดเมนของคุณคือ SQL ถ้าเป็นเช่นนั้นก็ดี แต่อย่าคาดหวังว่าคุณจะปฏิบัติตามกฎเกณฑ์ทางธุรกิจเพื่อเอาชีวิตรอดจากการเปลี่ยนแปลง คุณจะต้องเขียนใหม่ทั้งหมด


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

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

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

ฉันพยายามที่จะบอกว่าข้อมูลดิบที่เราได้รับจากผู้ใช้สำหรับบัญชีการลงทุนไม่ใช่วิธีที่เราใช้แทนบัญชีการลงทุนนั้นในส่วนหลักของแอปพลิเคชันของเราเช่นเมื่อมันถูกใช้สำหรับ calcs ตัวอย่างเช่นเราอาจมีอินพุตบูลีนที่เราบันทึกในฐานข้อมูลชื่อ IsManagedAccount ผู้ใช้ให้ข้อมูลกับเราผ่านปุ่มตัวเลือกบนหน้าจอแก้ไข ดังนั้นการแสดงจากฐานข้อมูลลงไปที่หน้าจอคือ 1 ถึง 1 เมื่อเราสร้างโมเดลโดเมนของเราในแอปพลิเคชั่นในภายหลังเราอาจมีคลาส ManagedAccount ดังนั้นจึงไม่มีคุณสมบัติบูลีน โครงสร้างทั้งสองนั้นมีความแตกต่างกันอย่างมากมาย
wired_in

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

1

การใช้ทฤษฎี DDD:

มีบริบทที่ถูกผูกมัดสองรายการในโดเมนนั้น:

  • การคำนวณบัญชีการลงทุน แบบจำลองทางคณิตศาสตร์ของบัญชีการลงทุนเป็นองค์ประกอบหนึ่งที่อาจรวมกัน
  • การเงินหลัก บัญชีการลงทุนของลูกค้าเป็นหนึ่งในหน่วยงาน

บริบทที่ถูกผูกมัดแต่ละคนสามารถมีการออกแบบสถาปัตยกรรมที่แตกต่างกัน

ตัวอย่าง:

บัญชีการลงทุนของลูกค้าเป็นเอนทิตี (อาจจะรวมขึ้นอยู่กับโดเมน) และการคงอยู่ของข้อมูลจะทำผ่านทางพื้นที่เก็บข้อมูลของเอนทิตี (RDB หรือฐานข้อมูลประเภทอื่นเช่นฐานข้อมูล OO)

ไม่มีวิธี DDD ในการปฏิบัติการ CRUD เมื่อต้องการให้เขตข้อมูล DB เชื่อมโยงกับข้อมูลของวัตถุแตกหลักการออกแบบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.