วิธีการออกแบบขอบเขตรวม?


10

ฉันต้องการเขียนแอปพลิเคชันเช่นอีคอมเมิร์ซ

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

หมวดหมู่ - นี่คือสิ่งที่ "อิเล็กทรอนิกส์> сomputers" เช่นประเภทของผลิตภัณฑ์ С Categories มีรายการคุณสมบัติ (รายการ <คุณสมบัติ>)

คุณสมบัติ - หน่วยงานอิสระที่มีชื่อหน่วยการวัดประเภทข้อมูล ตัวอย่างเช่น "ชื่อ", "น้ำหนัก", "ขนาดหน้าจอ" คุณสมบัติเดียวกันสามารถมีผลิตภัณฑ์ที่แตกต่างกัน

ผลิตภัณฑ์ - มีชื่อและรายการค่าที่เกี่ยวข้องกับคุณสมบัติ ค่าเป็นวัตถุที่มีเพียงฟิลด์ค่าและรหัสฟิลด์ของทรัพย์สิน

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

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

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

ตัวเลือกในการออกแบบกรณีธุรกิจนี้มีอะไรบ้าง


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

คุณพูดถูกแล้ว ฉันเพิ่มคำอธิบายบางอย่าง
cephei

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

คำตอบ:


7

ในมุมมองของ DDD, Category, ProductและPropertyเป็นหน่วยงานที่พวกเขาสอดคล้องกับวัตถุทั้งหมดที่มีเอกลักษณ์ของตัวเองของพวกเขา

ตัวเลือก 1: การออกแบบดั้งเดิมของคุณ

คุณทำให้Categoryรากของการรวมเดียว ในอีกด้านหนึ่งนี้ทำให้รู้สึกเพราะรวมจะให้สอดคล้องเมื่อวัตถุมีการแก้ไขและProductต้องมีPropertiesของCategory:

ป้อนคำอธิบายรูปภาพที่นี่

แต่ในอีกด้านหนึ่งการรวมเดี่ยวหมายความว่าวัตถุทั้งหมดของมันเกี่ยวข้องกับรูทที่เป็นเจ้าของและการอ้างอิงภายนอกทั้งหมดจะต้องทำผ่านรูทรวมนี้ นี่ก็หมายความว่า:

  • หนึ่งที่เฉพาะเจาะจงเป็นเพียงหนึ่งเดียวและProduct Categoryหากถูกลบเพื่อให้มีของมันCategoryProducts
  • ที่เฉพาะเจาะจงเป็นเพียงหนึ่งเดียวและProperty Categoryถ้าอย่างนั้นถ้า "หน้าจอทีวี" และ "หน้าจอคอมพิวเตอร์" เป็นสองประเภท "หน้าจอทีวี: ขนาด" และ "หน้าจอคอมพิวเตอร์: ขนาด" จะเป็นคุณสมบัติที่แตกต่างกันสองแบบ

จุดที่สองไม่ตรงกับคำบรรยายของคุณ: " แต่ฉันควรทำอย่างไรเมื่อฉันเพิ่งเพิ่มใหม่Propertyที่ไม่ได้อยู่ในหมวดหมู่ใด ๆ " และยังไม่ชัดเจนว่าPropertiesสามารถใช้ในแบบเดียวกันได้Categoriesหรือไม่

ตัวเลือก 2: คุณสมบัตินอกการรวม

หากมีPropertyอยู่เป็นอิสระจากCategoriesนั้นจะต้องอยู่นอกการรวม และเช่นเดียวกันหากคุณต้องการแบ่งปันPropertiesระหว่างกันCategories(ซึ่งเหมาะสมสำหรับความสูงความกว้างขนาด ฯลฯ ... ) ดูเหมือนว่าจะเป็นกรณีนี้

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

ป้อนคำอธิบายรูปภาพที่นี่

โปรดทราบว่าการออกแบบนี้ไม่ได้ป้องกันคุณที่จะมีList<Property>ในที่Categoryมีความหมายการอ้างอิง (เช่น java): การอ้างอิงแต่ละรายการในรายการหมายถึงPropertyวัตถุที่ใช้ร่วมกันได้ในพื้นที่เก็บข้อมูล

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

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

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

ตัวเลือก 3: หมวดหมู่ทรัพย์สินและผลิตภัณฑ์ในการรวมที่แตกต่างกัน

ฉันแค่สงสัยว่าการสันนิษฐานว่าเป็นProductของหนึ่งเดียวCategoryก่อตั้งขึ้น:

  • ฉันมักเห็นร้านค้าออนไลน์เสนอหนึ่งภายใต้หลายProduct Categoriesตัวอย่างเช่นคุณจะพบ "แล็ปท็อปยี่ห้อ X รุ่น Y" ภายใต้หมวดหมู่ "แล็ปท็อป" และหมวดหมู่ "คอมพิวเตอร์" และ "เครื่องพิมพ์มัลติฟังก์ชั่น Z" ภายใต้หมวดหมู่ "เครื่องพิมพ์", "สแกนเนอร์" และ "แฟกซ์"
  • เป็นไปไม่ได้ไหมที่มีคนสร้างProductครั้งแรกและต่อมากำหนดให้กับหมวดหมู่และเติมค่า?
  • หากคุณต้องการแบ่งหมวดหมู่คุณจะลบผลิตภัณฑ์จริง ๆ แล้วสร้างหมวดหมู่ใหม่ภายใต้หมวดหมู่ใหม่หรือไม่

มันจะไม่ลดความซับซ้อนของการรวมและคุณจะมีกฎมากขึ้นที่ขยายการรวม แต่ระบบของคุณจะเป็นหลักฐานในอนาคตมากขึ้น


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

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

การตอบคำถามของคุณสิ่งแรกที่มาถึงใจคือว่าผมสามารถสร้างนิติบุคคลพิเศษและมันจะเป็นของFeature Productและเอนทิตีนี้จะไม่เข้าร่วมในการค้นหา พูดว่าอะไรนะ ?
cephei

@zetetic ทำไมไม่! ฉันได้ทิ้งคุณค่าไว้ในขณะนี้พวกเขาอยู่ในผลิตภัณฑ์และจะเชื่อมโยงคุณสมบัติกับหมวดหมู่ หมวดหมู่มีคุณสมบัติ n (ส่วนหนึ่งของการรวม) คุณสมบัติจะกำหนดคุณสมบัติ m (แต่ลิงก์จะต้องผ่านคุณสมบัติหมวดหมู่ ->) จากนั้นคุณได้สลายความสัมพันธ์แบบหลายต่อหลายคนเป็นองค์ประกอบที่จัดการได้มากขึ้นโดยชี้แจงขอบเขตรวม สุดท้ายเกี่ยวกับการฉีดพื้นที่เก็บข้อมูล: นี้ไม่จำเป็นถ้าคุณอ้างอิงมวลอื่น ๆ โดยตัวตน (อ่านบทความนี้informit.com/articles/article.aspx?p=2020371&seqNum=4 )
Christophe

5

ตามที่เห็นคุณสามารถแก้ปัญหานี้ได้สองวิธี:

หมวดหมู่เป็นผลิตภัณฑ์ชนิดพิเศษ

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

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

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

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

ความสัมพันธ์หลายต่อหลายคน

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

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

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

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

ข้อสรุป

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

โชคดี!


ขอบคุณสำหรับคำตอบที่ละเอียดและน่าสนใจ! ที่ระดับฐานข้อมูลที่ฉันได้สร้างแบบจำลองแล้วตามที่คุณอธิบายในกรณีที่สองรูปแบบนี้เรียกว่า entity – attribute – value แต่ฉันติดอยู่ที่ระดับรหัสนั่นคือคำจำกัดความของมวลรวม ในกรณีส่วนใหญ่เอนทิตีเหล่านี้จะใช้ร่วมกัน มันเป็นไปได้ที่จะรวมกันเป็นหนึ่งรวม แต่มีบางกรณีที่ชอบกรอกไดเรกทอรีซึ่งโดยความรู้สึกจะถูกตีออกจากการรวม
cephei
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.