ตัวระบุเทียบกับวัตถุโดเมนเป็นพารามิเตอร์วิธีการ


10

มีข้อโต้แย้งวัตถุประสงค์สำหรับหรือต่อต้านการใช้วัตถุกับ ID ที่ไม่ซ้ำกันเป็นพารามิเตอร์วิธีการ / ฟังก์ชั่น? (และสมาชิกของวัตถุอื่น ๆ ?) เป็นพิเศษในบริบทของภาษาที่พิมพ์แบบคงที่ (C # / Java / Scala)

ข้อดีของวัตถุเอง:

  • โทร typesafe เพิ่มเติม ด้วย IDs มีความเสี่ยงในการเรียงลำดับอาร์กิวเมนต์อย่างไม่ถูกต้อง สิ่งนี้สามารถบรรเทาได้ด้วยการรักษาคลาส 'มินิ' สำหรับแต่ละคลาสที่เก็บ ID ของคลาสนั้นเท่านั้น
  • รับเพียงครั้งเดียวจากการคงอยู่ไม่จำเป็นต้องกลับมาอีก
  • ด้วย ID หากการเปลี่ยนแปลงประเภท id บอกว่า int -> long จะต้องมีการเปลี่ยนแปลงทั่วกระดานโดยอาจเกิดข้อผิดพลาด .. (courtey: https://softwareengineering.stackexchange.com/a/284734/145808 )

ข้อดีของการใช้ ID:

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

การผสมผสานของเทคนิคเหล่านี้เท่าที่ฉันเห็นมีเพียงข้อเสียของทั้งสองและข้อดีของทั้งสองอย่าง

ระบุว่านี่เป็นปัญหาที่กำหนดไว้อย่างชัดเจนฉันหวังว่าจะมีคำตอบที่ตรงตามวัตถุประสงค์และไม่ใช่ - "ฉันคิดว่า" หรือ "ฉันชอบ" ประเภท ... :-)

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

แก้ไข: บริบทเพิ่มเติมบางอย่าง บอกว่าฉันมีระบบการจัดการหนังสือ แบบจำลองของฉันคือ:

Book: { id: Int, isbn: String, donatedBy: Member, borrowedBy: Member }
Member: {id: Int, name: String}

Table- wishlist: { isbn: String, memberId: Int}
Table- borrows:  { id: Int, memberId: Int}  

Method: 
isInWishList( book: Book, member: Member ) vs isInWishList( bookId: Int,  memberId: Int)

handleBorrowRequest( memberId: Int, book: Book ){ 
   //the login system doesn't actually get the entire member structure, only the member id. I don't need the full member yet. can run a query to verify that the memberId has less than max allowed books for borrowing. 
}

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

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


คุณสามารถแก้ไขคำถามของคุณด้วยบริบทที่มากกว่านี้ได้หรือไม่? มันยังไม่ชัดเจนว่าเป็นสถานการณ์อะไร ฉันจะเดาว่าคุณกำลังพูดถึงวัตถุที่จัดการโดยระบบ ORM (เช่น Hibernate) และโดย "mini-class" คุณหมายถึงพร็อกซีโหลดวัตถุขี้เกียจ
Darien

2
อาจเกี่ยวข้องกัน programmers.stackexchange.com/questions/284634/…
hjk

การเพิ่มเป็นความคิดเห็นที่นี่ (จนกว่าฉันจะได้รับบริบทเพียงพอที่จะขยายไปยังคำตอบแบบเต็ม): หากคุณเป็นรหัสประจำตัวที่เข้ารหัสยากในรหัสของคุณ (ไม่ต้องใหญ่) คุณจะต้องโหลดค่า ID ของคุณ จากที่ไหนสักแห่งใช่ไหม "ส่วนใหญ่เวลา" ก็ค่อนข้างคลุมเครือ IMHO ...
hjk

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

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

คำตอบ:


8

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

ตัวอย่างเช่น Doctrine2 ORM ของ PHP มีการEntityManager::getReferenceสร้างพร็อกซีที่โหลดอย่างเกียจคร้านให้กับเอนทิตีโดยใช้ id ที่ระบุ ฉันไม่รู้ว่า ORM อื่น ๆ ทำเช่นนั้นได้อย่างไร แต่มันตรงกับแนวคิดของ "มินิคลาส" ที่คุณพูดถึง สำหรับเจตนารมณ์และวัตถุประสงค์ส่วนใหญ่นี่คือเอนทิตีแบบไฮเดรตอย่างเต็มที่ดังนั้นคุณสามารถส่งผ่านไปและใช้งานได้เหมือนกัน

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

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

  1. ประเภทความปลอดภัย
  2. ความรู้น้อยที่ต้องการโดยผู้โทร นักพัฒนา 6 เดือนลงมาบรรทัดไม่สามารถผ่านผิดใน id ของนิติบุคคลที่ไม่ถูกต้อง
  3. ลดต้นทุนการปรับโครงสร้างใหม่ หากวิธีการหนึ่งคือการเปลี่ยนแปลงที่ต้องใช้ข้อมูล 2 ส่วนจากเอนทิตีไม่มีค่าใช้จ่ายในการเปลี่ยนผู้โทรเพื่อให้มันโดยสันนิษฐานว่าผู้โทรได้รับเอนทิตีแบบไฮเดรตอย่างเต็มที่เพื่อเริ่มต้น
  4. จำเป็นต้องมีการตรวจสอบความถูกต้องน้อยลงต่อวิธี วิธีการหลายวิธีสามารถสันนิษฐานได้ว่าเอนทิตีที่ได้รับมีอยู่ในฐานข้อมูล (เพราะมาจาก ORM) และไม่จำเป็นต้องตรวจสอบรหัสอีกต่อไป
  5. (อาจเกิดขึ้น) การเรียกฐานข้อมูลน้อยลง หากคุณผ่าน ID ถึง 3 วิธีและแต่ละวิธีต้องตรวจสอบความถูกต้องหรือดึงข้อมูลเพิ่มเติมในเอนทิตีนั่นคือฐานข้อมูล 3 ครั้งที่มีการเรียกใช้วิธีการดึงข้อมูลเอนทิตีและ 2 ครั้ง

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


การแคชไม่ได้มีขนาดที่ดีเมื่อมีแอปพลิเคชันหลายตัวทำงาน ฉันมีแคชของตัวเองในสถานที่ แม้ว่าคะแนนจะยอดเยี่ยม
0fnt

ฉันเดาอีกจุดหนึ่งต่อ ID คือการใช้ ID หมายถึงการเรียกการคงอยู่นอกเหนือจากการตรวจสอบสำหรับการรับวัตถุจริงเกินไป
0fnt

3

สำหรับคำถามประเภทนี้ฉันได้มอบหมายให้วิธีใดวิธีหนึ่งในการสื่อสารความตั้งใจของฉันในฐานะโปรแกรมเมอร์และทำให้งานของ "Future Greg" ง่ายที่สุด

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

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

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

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

public boolean isInWishList(int bookId, int memberId) {
    // ...
}

public boolean isInWishList(Book book, Member member) {
    return isInWishList(book.getId(), member.getId());
}

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

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