DDD - รวมรูทกับลูกจำนวนมาก


10

ฉันจะนำคำถามนี้โดยบอกว่าฉันค่อนข้างใหม่สำหรับ DDD ดังนั้นฉันอาจทำผิดพลาดพื้นฐานบางอย่างที่นี่!

ฉันทำงานในโครงการที่เกี่ยวข้องกับแนวคิดของบัญชีและธุรกรรม (ในแง่การเงิน) บัญชีสามารถมีธุรกรรมจำนวนมากได้

สำหรับฉันแล้วดูเหมือนว่าบัญชีและธุรกรรมเป็นทั้งสองอย่างและบัญชีนั้นเป็นรากรวมที่มีธุรกรรมเนื่องจากไม่สามารถทำธุรกรรมได้หากไม่มีบัญชี

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

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

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

คำตอบ:


9

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

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

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


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

7

tl; dr - ทำผิดกฎถ้าคุณต้องการ DDD ไม่สามารถแก้ปัญหาทั้งหมดได้ ในความเป็นจริงแนวคิดเกี่ยวกับวัตถุที่ให้นั้นเป็นคำแนะนำที่ดีและเป็นการเริ่มต้นที่ดี แต่ตัวเลือกที่ไม่ดีจริงๆสำหรับปัญหาทางธุรกิจบางอย่าง คิดว่ามันเป็นคำใบ้สำหรับวิธีการทำสิ่งต่าง ๆ


สำหรับปัญหาในการโหลดลูกทุกคน (ธุรกรรม) กับผู้ปกครอง (บัญชี) - ดูเหมือนว่าคุณพบปัญหา n + 1 (สิ่งที่เป็น google) ซึ่ง ORM จำนวนมากได้แก้ไขแล้ว

คุณสามารถแก้ปัญหาได้โดยการโหลดลูก ๆ (ธุรกรรม) ขี้เกียจ - เมื่อจำเป็นเท่านั้น

แต่ดูเหมือนคุณรู้อยู่แล้วด้วยการกล่าวถึงว่าคุณสามารถใช้ TransactionRepository เพื่อแก้ไขปัญหา

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

ดังนั้นคุณสามารถตั้งค่าการอนุญาต แต่คุณต้องเรียกใช้ 'บัญชี' เป็นกระบวนการแยกต่างหาก

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

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

คำตอบที่แท้จริงคือเริ่มยืน SOA ที่ทำงานของฉันเราดูวิดีโอ Udi Dahan 'Distributed computing' และซื้อ nServiceBus (ทางเลือกของเรา) สร้างบริการสำหรับบัญชี - ด้วยกระบวนการของตัวเอง, คิวข้อความ, การเข้าถึงฐานข้อมูลความสัมพันธ์เท่านั้นที่สามารถมองเห็นได้และ ... วิโอลา, คุณสามารถ hardcode คำสั่ง SQL ในโปรแกรมและแม้แต่โยนโคโบสคริปธุรกรรมสองรายการ แน่นอน) แต่จริงจังกับการแยกข้อกังวลมากกว่าคนที่หัวสูง OO / Java ที่ฉลาดที่สุดเท่าที่จะทำได้

ฉันขอแนะนำให้สร้างแบบจำลองมันดีอยู่ดี คุณสามารถได้รับประโยชน์จากการรวมรูทที่นี่โดยไม่มีปัญหาด้วยการดูแลบริการเป็น countext mini-bounded

แน่นอนว่ามันมีข้อเสียเปรียบ คุณไม่สามารถเพียงแค่ RPC (webservice, SOAP หรือ REST) ​​เข้าและออกจากบริการและระหว่างพวกเขาหรือคุณได้รับ SOA antipattern ที่เรียกว่า 'ปม' เนื่องจากการมีเพศสัมพันธ์ชั่วคราว คุณต้องใช้ผกผันของรูปแบบการสื่อสารหรือที่เรียกว่า 'Pub-Sub' ซึ่งมันเหมือนกับตัวจัดการเหตุการณ์และตัวสร้างเหตุการณ์ แต่ (1) ระหว่างกระบวนการ (ซึ่งคุณสามารถวางบนเครื่องแยกต่างหากหากพวกเขากำลังโหลดมากเกินไป)

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

หนังสือ "SOA Patterns" โดย Arnon Rotem-Gal-Oz ตอบคำถามมากมายเกี่ยวกับเรื่องนี้ รวมถึงการใช้ 'รูปแบบบริการที่ใช้งาน' เพื่อทำซ้ำข้อมูลจากบริการภายนอกเป็นของคุณเองเมื่อเกิดความต้องการ (จำเป็นต้องใช้ RPC จำนวนมากหรือลิงก์ไม่น่าเชื่อถือ / ไม่อยู่ในระบบนิเวศเผยแพร่ / สมัครสมาชิก)

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

ในท้ายที่สุดแม้ว่าทุกสิ่งไม่สามารถจำแนกออกเป็นบริการเดียวอย่างถูกต้อง โลกไม่ได้ทำงานกับรหัสราวีโอลี่! ดังนั้นคุณจะต้องทำลายกฎ แม้ว่าคุณจะไม่ต้องทำก็ตาม devs ใหม่ในโครงการจะทำเมื่อคุณออกจากโครงการ แต่ไม่ต้องกังวลหากคุณทำสิ่งที่คุณทำได้ 85% ที่เป็นไปตามกฎจะทำให้โปรแกรมนั้นสามารถบำรุงรักษาได้มากขึ้น

ว้าวนั่นมันนาน


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