การออกแบบโดเมนขับเคลื่อน - พึ่งพาภายนอกในปัญหาเอ็นติตี้


22

ฉันต้องการเริ่มต้น Domain-Driven-Design แต่มีปัญหาหลายอย่างที่ฉันต้องการแก้ไขก่อนเริ่มต้น :)

ลองนึกภาพฉันมีกลุ่มและผู้ใช้และเมื่อผู้ใช้ต้องการเข้าร่วมกลุ่มฉันกำลังเรียกgroupsService.AddUserToGroup(group, user)วิธี ใน DDD ฉันควรทำgroup.JoinUser(user)ซึ่งดูดีทีเดียว

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

ตัวอย่างอาจเป็น - ข้อ จำกัด ที่ผู้ใช้สามารถเข้าร่วมได้สูงสุด 3 กลุ่มเท่านั้น วิธีนี้จะต้องใช้การเรียก DB จากภายในกลุ่มวิธีใช้ JoinUser เพื่อตรวจสอบความถูกต้องนี้

แต่ความจริงที่ว่า Entity นั้นขึ้นอยู่กับบริการ / คลาสภายนอกบางอย่างนั้นดูไม่ดีนัก

วิธีที่เหมาะสมในการจัดการกับสิ่งนี้ใน DDD คืออะไร?

คำตอบ:


15

ลองนึกภาพว่าฉันมีกลุ่มและผู้ใช้และเมื่อผู้ใช้ต้องการเข้าร่วมกลุ่มฉันกำลังเรียกใช้วิธี groupsService.AddUserToGroup (กลุ่มผู้ใช้) ใน DDD ฉันควรทำ group.JoinUser (ผู้ใช้) ซึ่งดูดีทีเดียว

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

ปัญหาปรากฏขึ้นหากฉันมีกฎการตรวจสอบความถูกต้องสำหรับการเพิ่มผู้ใช้ ...

กฎการตรวจสอบจะเป็นของโมเดลโดเมน! ควรห่อหุ้มไว้ในวัตถุโดเมน (เอนทิตี ฯลฯ )

... หรืองานภายนอกบางอย่างจำเป็นต้องเริ่มต้นเมื่อมีการเพิ่มผู้ใช้ในกลุ่ม การมีงานเหล่านี้จะนำไปสู่เอนทิตีที่มีการอ้างอิงภายนอก

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

แต่ความจริงที่ว่า Entity นั้นขึ้นอยู่กับบริการ / คลาสภายนอกบางอย่างนั้นดูไม่ดีนัก

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

วิธีที่เหมาะสมในการจัดการกับสิ่งนี้ใน DDD คืออะไร?

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

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

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

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


แต่ถ้าเราย้ายตรรกะจำนวนมากนอกเอนทิตีสิ่งที่ควรเก็บไว้ข้างใน?
SiberianGuy

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

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

1
ขอบคุณสำหรับคำตอบของคุณเหยี่ยว! Btw ฉันพยายามใช้บริการไร้สัญชาติอยู่เสมอดังนั้นฉันจึงเข้าใกล้ DDD ได้หนึ่งก้าว :) สมมุติว่าในโดเมนการดำเนินการของ UserJoinsToGroup นี้เป็นของกลุ่ม ปัญหาคือว่าเพื่อตรวจสอบการดำเนินงานที่ฉันต้องรู้ในจำนวนกลุ่มที่ผู้ใช้มีส่วนร่วมอยู่แล้ว (เพื่อปฏิเสธการดำเนินการหากมีอยู่แล้ว> 3) หากต้องการทราบว่าฉันต้องการสอบถามฐานข้อมูล ฉันจะทำสิ่งนั้นจากเอนทิตีของกลุ่มได้อย่างไร ฉันได้ตัวอย่างบางมากขึ้นเมื่อฉันต้องการที่จะสัมผัสฐานข้อมูลในการดำเนินงานที่ควรตามธรรมชาติเป็นของนิติบุคคล (ฉันจะโพสต์ไว้ถ้าจำเป็น :))
Shaddix

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

3

วิธีที่ฉันจะเข้าถึงปัญหาของการตรวจสอบคือวิธีนี้: สร้างบริการโดเมนที่เรียกว่าMembershipService:

class MembershipService : IMembershipService
{
   public MembershipService(IGroupRepository groupRepository)
   { 
     _groupRepository = groupRepository;
   }
   public int NumberOfGroupsAssignedTo(UserId userId)
   {
        return _groupsRepository.NumberOfGroupsAssignedTo(userId);
   }
}

IMemberShipServiceความต้องการนิติบุคคลกลุ่มจะได้รับการฉีดด้วย สามารถทำได้ในระดับชั้นเรียนหรือระดับวิธีการ สมมติว่าเราทำได้ในระดับวิธี

class Group{

   public void JoinUser(User user, IMembershipService membershipService)
   {
       if(membershipService.NumberOfGroupsAssignedTo(user.UserId) >= 3)
         throw new BusinessException("User assigned to more than 3 groups. Cannot proceed");

       // do some more stuff
   }
}

บริการแอปพลิเคชัน: GroupServiceสามารถฉีดIMemberShipServiceโดยใช้การสร้างคอนสตรัคเตอร์ซึ่งสามารถส่งผ่านไปยังJoinUserวิธีการGroupเรียน


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