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


25

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

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

  1. อย่างไร้เดียงสาdata transfer objects (DTO)ที่ได้มาจากการรวมกันของแบบจำลองโดเมนจะไม่มีคีย์หลัก
  2. DTO ที่เข้ามาจะไม่มีคีย์หลัก

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

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

  1. ความสามารถในการระบุวัตถุที่คุณต้องจัดการกับคุณลักษณะอื่น ๆ
  2. รับคีย์หลักกลับใน DTO; เช่นการกำจัด PK เมื่อทำการแมปจากการมีอยู่ไปยังโดเมนจากนั้นทำการรวม PK อีกครั้งเมื่อทำการแมปจากโดเมนไปยัง DTO

แก้ไข: มาสร้างคอนกรีตกันเถอะ

กล่าวว่ารูปแบบโดเมนของฉันคือVoIPProviderซึ่งรวมถึงสาขาที่ชอบName, Description, URLเช่นเดียวกับการอ้างอิงเช่นProviderType, และPhysicalAddressTransactions

ตอนนี้สมมติว่าฉันต้องการสร้างบริการบนเว็บที่จะอนุญาตให้ผู้ใช้ที่มีสิทธิ์จัดการVoIPProviderได้

บางทีรหัสที่ใช้งานง่ายอาจไม่มีประโยชน์ในกรณีนี้ ท้ายที่สุดแล้วผู้ให้บริการ VoIP เป็น บริษัท ที่มีชื่อแตกต่างกันในแง่ของคอมพิวเตอร์และแตกต่างกันในแง่ของเหตุผลทางธุรกิจ ดังนั้นจึงอาจเพียงพอที่จะกล่าวได้ว่ามีความเป็นเอกลักษณ์ที่VoIPProviderถูกกำหนดโดย(Name, URL)สมบูรณ์ ดังนั้นตอนนี้สมมติว่าฉันต้องการวิธีการPUT api/providers/voipเพื่อให้ผู้ใช้ที่มีสิทธิ์สามารถอัพเดตVoIPผู้ให้บริการได้ พวกเขาส่งขึ้นVoIPProviderDTOซึ่งรวมถึงจำนวนมาก แต่ไม่ทั้งหมดของฟิลด์จากVoIPProviderรวมทั้งบางแฟบที่อาจเกิดขึ้น อย่างไรก็ตามฉันไม่สามารถอ่านใจของพวกเขาและพวกเขายังต้องบอกฉันว่าผู้ให้บริการรายใดที่เรากำลังพูดถึง

ดูเหมือนว่าฉันมีตัวเลือก 2 (อาจจะ 3):

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

1
ชี้ไปที่ไตร่ตรอง: บ่อยครั้งที่การสื่อสารกับผู้เชี่ยวชาญด้านโดเมนแย่ลงเมื่อใช้ PK ตัวแทนเมื่อมีคีย์ธุรกิจที่ดีอยู่ ดูเหมือนว่าเราจะทำงานให้กับกรอบ ORM แทนวิธีอื่น
Tulains Córdova

@ user61852 ดีโดยไม่คำนึงถึง ORM แม้ว่าคุณจะอยู่ในระดับต่ำจริงๆคุณยังต้องมีคีย์หลักในการใช้งานเลเยอร์ฐานข้อมูล ดังนั้นฉันจึงเห็นพ้องกันว่าตัวแทนตัวแทน PK จะให้คุณได้เปรียบกว่า PK จริง ๆ ที่ใช้โดยกลไกการคงอยู่ที่เฉพาะเจาะจง แต่ถ้า PK นั้นแสดงถึงวัตถุทางธุรกิจที่มีความหมายจริง ๆ แล้วมันจำเป็นต้องมีเอกลักษณ์ มันไม่
tacos_tacos_tacos

1
ข้อดีทั้งหมดของตัวแทนเสมือนมีความเกี่ยวข้องกับคอมพิวเตอร์และไม่เกี่ยวข้องกับมนุษย์
Tulains Córdova

2
@ user61852: ฉันเห็นด้วย 100% (ฉันเขียนบางอย่างที่แตกต่างออกไปหรือเปล่า) สำหรับวิธีการสื่อสารให้ใช้ "รหัสธุรกิจ" เพิ่มข้อ จำกัด ที่ไม่ซ้ำกันสำหรับคีย์ธุรกิจใด ๆ เช่นกัน แต่หลีกเลี่ยงการใช้คีย์ธุรกิจเพื่อนำการอ้างอิงฐานข้อมูลไปใช้จริง
Doc Brown

2
รหัสธุรกิจจะไม่ซ้ำกันตลอดไป - จนกว่าจะไม่มี หากคุณใช้รหัสธุรกิจเป็นหลักเมื่อเกิดเหตุการณ์นี้ขึ้นการเปลี่ยนแปลงในกฎเกณฑ์ทางธุรกิจจะทำให้สิ่งต่างๆเพิ่มขึ้น
psr

คำตอบ:


31

นี่คือวิธีที่เราแก้ปัญหานี้ (ตั้งแต่มากกว่า 15 ปีเมื่อแม้แต่คำว่า "การออกแบบที่ขับเคลื่อนด้วยโดเมน" ไม่ได้คิดค้นขึ้นมา):

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

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

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

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


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

1
@tacos_tacos_tacos: ลองทำตัวอย่าง VoIPProvider ของคุณ ฉันจะเพิ่ม "VoIPProviderID" ลงใน DTO ของคุณอย่างน้อยในส่วน "การนำไปใช้" (ถ้าคุณมีรุ่นกราฟิกสำหรับผู้เชี่ยวชาญโดเมนของคุณด้วยฉันอาจจะไม่แสดงที่นี่) สำหรับวัตถุประสงค์ในการอัปเดตวิธีมาตรฐานในการระบุ VoIPProvider เฉพาะควรเป็น "VoIPProviderID" ที่คุณดึงมาเมื่อดึงข้อมูลจากฐานข้อมูล หากผู้ใช้ API ของคุณต้องการการระบุด้วย (ชื่อ, URL) ให้ระบุเพิ่มเติม ...
Doc Brown

... และหากประสิทธิภาพดูเหมือนจะกลายเป็นปัญหาที่แท้จริงและสามารถวัดได้คุณสามารถพิจารณาทำแผนที่แคช (ชื่อ, URL) ไปยัง VoIPProProviderID ที่ใดที่หนึ่ง แต่ฉันจะไม่แนะนำให้ใช้การเพิ่มประสิทธิภาพเช่นนี้ล่วงหน้าก่อนกำหนด
Doc Brown

1
บางครั้งคีย์ธรรมชาติดูเหมือนจะน่าสนใจจริงๆ แต่มันง่ายเกินไปที่จะถูกเผา (เช่น "อ๊ะตอนนี้ฉันมีผู้เช่าหลายคน
Casey

1
@corsiKa: ในบริบทของสิ่งที่ OP ถามฉันขอแนะนำอย่างยิ่งให้มีรหัสที่สร้างอัตโนมัติอย่างสมบูรณ์ "OrderID" (ซึ่งไม่ได้พิมพ์ลงบนใบเสร็จรับเงินใด ๆ แต่ใช้สำหรับสิ่งภายในเช่นการอ้างอิงฐานข้อมูล) และรหัสธุรกิจแยกต่างหาก "OrderNumber" (ซึ่งสามารถมีบางสิ่งบางอย่างเช่นปีปัจจุบันซึ่งสามารถใช้สำหรับการเรียงลำดับและการกรองซึ่งสามารถเปลี่ยนแปลง / แก้ไขได้ในภายหลังและสามารถพิมพ์ลงบนใบเสร็จรับเงิน) OP ขอให้ "การออกแบบโดเมนขับเคลื่อน", "OrderNumber" เป็นส่วนหนึ่งของรูปแบบโดเมนในขณะที่ "OrderID" เป็นเพียงรายละเอียดการใช้งาน
Doc Brown

4

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

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


เมื่อฉันต้องการทำการดำเนินการที่เกี่ยวข้องกับอินสแตนซ์เฉพาะของวัตถุโดเมนที่ยังคงอยู่ฉันต้องสามารถรวมใน DTO อย่างชัดเจน (ผ่านคีย์บางประเภทไม่ว่าจะเป็นรหัสหลักหรือรหัสที่เป็นมิตรกับผู้ใช้ที่เป็นเอกลักษณ์ ไปยังตารางนั้นและอาจเป็นดัชนีบนโต๊ะ) หรือโดยปริยาย (ผ่านบางส่วนของเขตข้อมูลที่มีค่าที่ไม่ซ้ำกันระบุระเบียนเฉพาะ) ... และยิ่งไปกว่านั้นในทางปฏิบัติฉันจะต้องส่งใน DTO การติดตามการเปลี่ยนแปลงบางรูปแบบถ้าฉันต้องทำอย่างอื่น (OriginalVal กับ NewVal สำหรับฟิลด์ทั้งหมดที่ระบุบันทึก) ใช่ไหม
tacos_tacos_tacos

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

แน่นอนว่าเราสามารถมี PK บนหลายคอลัมน์ได้เช่นกัน แต่สำหรับฉันมันกำลังรั่วอะไรบางอย่างเกี่ยวกับ databaswe (ที่เก็บข้อมูล) ซึ่งไม่ควรทำอะไรกับหัวใจ & วิญญาณองค์กรธุรกิจ หากฟิลด์ tuple บางส่วนของเอนทิตีธุรกิจเกิดขึ้นเพื่อขยาย PK สำหรับ DB นั้นยอดเยี่ยม แต่มันไม่ควรจะเป็นอย่างอื่นด้วยใช่ไหม?
tacos_tacos_tacos

คุณคิดมาก ดัชนีที่ไม่ซ้ำกันนั้นเป็นสิ่งประดิษฐ์ของ DB schema มากเท่ากับ PK คิดแบบนี้ - PK เป็นเพียงดัชนีเฉพาะ (หรือหลัก) แรก มัน 'พิเศษ' เพราะโดยทั่วไปคุณต้องการเพียง 1 ดัชนีดังกล่าว
gbjbaanb

จริง แต่วัตถุโดเมนที่มีความหมายใด ๆ ควรสามารถระบุได้อย่างเคร่งครัดจากสาขาที่เกี่ยวข้องกับธุรกิจอย่างน้อยหนึ่งรายการ ความจริงที่ว่าสิ่งนี้กำหนดดัชนีในฐานข้อมูลนั้นมีเหตุผลด้านประสิทธิภาพมากกว่าที่จะใช้ในการสืบค้นฐานข้อมูลได้อย่างง่ายดาย ... ฉันต้องการ PK แบบหนึ่งคอลัมน์มากกว่าดัชนีที่ไม่ซ้ำกัน 6 คอลัมน์และพวกเขาตอบสนองวัตถุประสงค์ที่แตกต่างกันจริงๆ - นอกจากนี้ยังมี PK (หรือดัชนีที่มีจำนวนฟิลด์น้อย) เพื่อความสะดวกของ DBA / DBD ใช่ไหม
tacos_tacos_tacos

4

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

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


ดีข้อความเป็นตัวอย่างมาก แต่แม้แล้วเราจะได้รู้ว่าMessageSender, MessageRecipient, TimeSent- ที่ควรจะเป็นที่ไม่ซ้ำกัน
tacos_tacos_tacos

1
@tacos_tacos_tacos แล้วคุณจะสร้าง FKs ไปยังตารางอื่นได้อย่างไร ควรเป็น MessageSenderId ซึ่งอาจจับคู่กับตารางผู้ใช้บน UserId คุณไม่ต้องการใช้ชื่อผู้ใช้เป็นกุญแจสำคัญระหว่างตารางเนื่องจากอาจเปลี่ยนแปลงได้และกลายเป็นฝันร้ายของการบำรุงรักษา นี่คือเหตุผลที่คุณมักเข้าร่วมตารางโดยใช้คีย์หลักไม่ใช่คอลัมน์อื่น (มีข้อยกเว้นอย่างแน่นอน) โครงสร้าง db นี้ยังคงต้องถูกบังคับใช้ ตอนนี้คุณสามารถไปที่โมเดล CQRS สำหรับแอปของคุณ ... ซึ่งในกรณีนี้การเปลี่ยนแปลงกฎ โดยเฉพาะถ้าคุณใช้การจัดหากิจกรรม
CaffGeek

4

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

ฉันเห็นคุณตอบด้วยความคิดเห็น: MessageSender, MessageRecipient, TimeSent (สำหรับข้อความ) คุณยังสามารถมีความคลุมเครือด้วยวิธีนี้ (ตัวอย่างเช่นเมื่อระบบสร้างข้อความที่กระตุ้นให้เกิดสิ่งที่เกิดขึ้นบ่อยครั้ง) และคุณจะตรวจสอบ MessageSender และ MessageRecipient ที่นี่ได้อย่างไร สมมติว่าคุณตรวจสอบพวกเขาโดยใช้ FirstName, นามสกุล, DateOfBirth ในที่สุดคุณจะพบกับสถานการณ์ที่คุณมีคนเกิดมา 2 คนในวันเดียวกันด้วยชื่อเดียวกัน tacostacostacos-America-1980-Doc Brown-France-1965-23/5/2014-11:43:54.003UTC+200ไม่พูดถึงว่าคุณจะทำงานในสถานการณ์ที่คุณมีข้อความชื่อ นั่นคือสัตว์ประหลาดชื่อและคุณยังไม่มีการรับประกันว่าคุณจะมีเพียงหนึ่งในนั้น

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

คุณไม่จำเป็นต้องแสดง ID ของคุณต่อผู้ใช้ คุณสามารถซ่อนสิ่งนั้นได้ (ในกรณีที่จำเป็นผ่าน URL)

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

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

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

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


1

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

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

การใช้ GUID เป็นไปตามเงื่อนไขบางประการอย่างไรก็ตามตัวระบุเช่น GUID อาจยากต่อการตรวจสอบกลับเข้าไปในวัตถุแม้ในระบบของคุณดังนั้นคีย์ที่ทึบแสงถึงแม้ระบบของคุณเช่น GUID จะต้องใช้งานหากลูกค้าวิเคราะห์ URI / ตัวระบุเท่านั้น เสี่ยงต่อความปลอดภัย

กลับไปที่ตัวอย่าง VoIP ของคุณบอกว่าผู้ให้บริการ VoIP สามารถกำหนดได้ไม่ซ้ำกันโดย (VoIPProviderID) หรือ (ชื่อ, URL) หรือโดย (GUID) เมื่อระบบภายนอกจำเป็นต้องอัปเดตผู้ให้บริการ VoIP เพียงแค่ส่งผ่าน PUT / provider / by-id / 1234 หรือPUT /provider/foo-voip/bar-domain.comหรือPUT /3F2504E0-4F89-41D3-9A0C-0305E82C3301และระบบของคุณจะเข้าใจว่าระบบภายนอกต้องการอัปเดต VoIPProvider URI เหล่านี้สร้างขึ้นโดยระบบของคุณและมีเพียงระบบของคุณที่ต้องเข้าใจว่าสิ่งเหล่านั้นหมายถึงสิ่งเดียวกัน ระบบภายนอกควรปฏิบัติต่อสิ่งใดก็ตามที่อยู่ใน URI โดยพื้นฐานPUT <whatever>แล้ว

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

เมื่อระบบของคุณใช้ URI เพื่ออ้างถึงวัตถุในลักษณะดังกล่าวคุณจะไม่รั่วไหลใด ๆ เกี่ยวกับวิธีการใช้ระบบของคุณ คุณสร้าง URI และไคลเอนต์ก็ส่งมันกลับมาให้คุณ


0

ฉันจะต้องกำหนดเป้าหมายแถลงการณ์ที่ไม่ถูกต้องและไร้เดียงสานี้

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

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

จากนั้นเราจะได้เป็นความจริงที่ว่าชื่อ บริษัท เป็นไม่ได้ที่ไม่ซ้ำกันจากระยะไกลที่แสดงโดยสถานที่สำคัญแอปเปิ้ลกับแอปเปิ้ล

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

สำหรับการอ้างอิงฉันต้องการวิธีdjangoจัดการสิ่งนี้:

class VoipProvider(models.Model):
    name=fields.TextField()
    address=fields.TextField()

class Customer(models.Model):
    name=fields.TextField()
    address=fields.TextField()
    voipProvider=fields.ForeignKeyField(VoipProvider)

ด้วยวิธีนี้รายละเอียดของผู้ให้บริการของลูกค้าสามารถเข้าถึงได้ในรหัสโดยใช้:

myCustomer.voipProvider.name #returns the name of the customers VOIP Provider.

ในขณะที่ไม่สามารถมองเห็นคีย์หลัก / ต่างประเทศได้กุญแจเหล่านั้นจะอยู่ในนั้นและสามารถใช้เพื่อเข้าถึงรายการต่างๆ แต่ถูกย่อให้อยู่


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

0

ฉันคิดว่าเรามักจะมองปัญหานี้อย่างไม่ถูกต้องจากมุมมองของฐานข้อมูล: โอ้ไม่มีคีย์ธรรมชาติดังนั้นเราต้องสร้างคีย์ตัวแทน โอ้ไม่เราไม่สามารถเปิดเผยกุญแจตัวแทนกลับเข้าไปในวัตถุโดเมนที่รั่ว ฯลฯ

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

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

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

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