พฤติกรรมที่คาดหวังเมื่อมีการร้องขอสำหรับคอลเลกชันจะมีรายการศูนย์


13

สมมติว่าคุณได้รับสิ่งต่อไปนี้ ...

List<Thing> theThings = fubar.Things.All();

หากไม่มีอะไรจะกลับคุณจะคาดหวังอะไรกับสิ่งเหล่านี้ทั้งหมด () จะกลับมา?

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

ฉันเห็นด้วยกับการตอบสนองโดยเฉพาะอย่างยิ่งผู้ที่แนะนำการเก็บสะสมที่ว่างเปล่า ผู้ขายระบุ API ด้วยการโทรหลายครั้งคล้ายกับตัวอย่างด้านบน ผู้ขายที่ทำรายได้ 4.6 ล้านเหรียญสหรัฐผ่านทาง API ของพวกเขาเมื่อปีที่แล้วคือ BTW พวกเขาทำสิ่งที่ฉันไม่เห็นด้วยโดยพื้นฐาน - พวกเขามีข้อยกเว้น


ดูเหมือนจะเป็นฉันทามติที่มั่นคง [ที่นี่] [1]: การรวบรวมที่ว่างเปล่า เสมอ. [1]: stackoverflow.com/questions/1969993/…
Jesse C. ตัวแบ่งส่วนข้อมูล

ประเภทข้อมูลมีไว้เพื่อThingsอะไร? ถ้ามันทำให้ความรู้สึกที่จะมีThingsnull ฟิลด์กลับแล้วมันทำให้รู้สึกสำหรับคุณที่จะได้รับข้อยกเว้นเพราะคุณไม่ได้ตรวจสอบ null All()ก่อนที่จะเรียกร้องให้ อย่างไรก็ตามฉันเห็นด้วยกับคนที่คิดว่าfubar.Thingsควรส่งคืนคอลเล็กชันที่ว่างเปล่าแทนที่จะเป็นโมฆะ
โคลิน D

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

พวกเขา OMG ส่งข้อยกเว้น ... ! o_O
Stuart Marks

ตอนนี้คำถามที่น่าสนใจมากขึ้นก็คือเหตุผลอะไรในโลกที่ทุกคนอาจจะต้องโยนในกรณีทั่วไปหรือสิ่งที่ทำให้เป็นกรณีพิเศษเพื่อรับประกันการขว้างปา ??
Martin Ba

คำตอบ:


29

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

List<Thing> theThings = fubar.Things.All();
if (theThings != null) {
    for (Thing t : theThings) {
        t.doSomething();
    }
}

พวกเขาจะสามารถเขียนสิ่งนี้:

List<Thing> theThings = fubar.Things.All();
for (Thing t : theThings) {
    t.doSomething();
}

ส่วนของโค้ดที่สองนี้สั้นกว่าและอ่านง่ายกว่าเนื่องจากระดับการซ้อนต่ำกว่าหนึ่ง


2
ฉันคิดว่าฉันจะเข้าใจแนวคิดได้ง่ายขึ้นเช่นกันเนื่องจาก 'ชุดว่างเปล่า' (ไม่มีรายการ) Null คือ 'ไม่มีชุด' ซึ่งแตกต่างกันมาก (สิ่งนี้ควรครอบคลุมสิ่งต่าง ๆ ที่เป็นไปไม่ได้ในเชิงตรรกะ - ชุดของรายการทั้งหมดที่เป็นเลขคี่ซึ่งควรเป็นค่าว่างไม่ใช่ค่าว่าง) ฉันไม่แน่ใจว่าสิ่งที่ (เหตุผล) จะเป็นชุดโมฆะ ... (แม้ว่าคุณจะเจ้าชู้บนเกาะสมบัติของคุณเป็นชุดที่ว่างเปล่าไม่ว่างหนึ่ง)
Clockwork-Muse

@ X-Zero แต่ถ้าคุณเจ้าชู้เจ้าตัว "สมบัติในกระเป๋าเป้สะพายหลัง" อาจส่งคืนเซตว่างเนื่องจากคุณไม่มีกระเป๋าเป้สะพายหลัง มันอาจจะเป็น BackpackNotFoundException แต่ถ้ามันเป็นอย่างแท้จริงที่ไม่คาดคิด มันควรจะเป็นสภาวะปกติในการพูดเกมการอยู่รอดของเกาะ
Izkata

เช็คว่างเป็นพิเศษคือสิ่งที่ช่วยให้ฉันนอนหลับตอนกลางคืน
Joel B

6

ฉันคาดหวังรายการที่ว่างเปล่า theThingsจะยังคงเป็นวัตถุ แต่theThings.CountหรือจะกลับมาtheThings.size()0


5

ปัญหาการออกแบบเช่นนั้นได้รับการจัดการโดยรูปแบบวัตถุ Null

... แทนที่จะใช้การอ้างอิงแบบ null เพื่อถ่ายทอดการไม่มีวัตถุ (ตัวอย่างเช่นลูกค้าที่ไม่มีอยู่จริง) จะใช้วัตถุที่ใช้อินเทอร์เฟซที่คาดไว้ แต่มีเมธอดว่างเปล่า ข้อดีของวิธีการนี้ในการใช้งานเริ่มต้นคือวัตถุ Null สามารถคาดเดาได้มากและไม่มีผลข้างเคียง: ไม่ทำอะไรเลย

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

ข้อเสนอแนะสามารถใช้ได้โดยเฉพาะในกรณีของคุณ (กลับมาListเมื่อไม่มีThings) คือ:

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


3

คุณควร IMHO ส่งคืนค่าว่าง ฉันไม่รู้เกี่ยวกับ C # แต่ใน Java เรามีสิ่งนี้:

  List list = Collections.EMPTY_LIST;
  Set set = Collections.EMPTY_SET;
  Map map = Collections.EMPTY_MAP;

  // For the type-safe 
  List<String> s = Collections.emptyList();
  Set<Long> l = Collections.emptySet();
  Map<Date> d = Collections.emptyMap();

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html


1
เทียบเท่า C # คือEnumerable.Empty<T>()ซึ่งส่งคืนค่าว่างIEnumerable<T>(ดูmsdn.microsoft.com/en-us/library/bb341042.aspx )
Avner Shahar-Kashtan

1
เอกสารปัจจุบันอยู่ที่นี่: docs.oracle.com/javase/7/docs/api/java/util/Collections.htmlตอนนี้เอกสาร 1.4.2 มีอายุประมาณสิบปีแล้ว
Stuart Marks

2

ฉันจะกลับคอลเลกชันที่ว่างเปล่ามากกว่าการส่งกลับค่า null เพราะวิธีที่คุณสามารถหลีกเลี่ยงการเขียนการตรวจสอบเป็นโมฆะในรหัสโทร


2

โซลูชันทั้งสองหมายถึงสิ่งต่าง ๆ

หากมีเพียงศูนย์ของสิ่งที่คุณจะกลับมาคุณมักจะกลับคอลเลกชันว่าง! นำกรณีของรายการไดเรกทอรี หากไม่มีไฟล์ในไดเร็กทอรีคุณจะส่งคืนคอลเล็กชันไฟล์ว่าง

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


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