วิธีการดึงข้อมูลควรส่งคืน 'null' หรือส่งข้อยกเว้นเมื่อไม่สามารถสร้างค่าส่งคืนได้หรือไม่ [ปิด]


503

ฉันมีวิธีการที่ควรส่งคืนวัตถุหากพบ

หากไม่พบฉันควร:

  1. ส่งคืน null
  2. โยนข้อยกเว้น
  3. อื่น ๆ

57
ไม่ว่าคุณจะทำอะไรก็ตาม ฉันคิดว่าประเด็นนี้สำคัญกว่าวิธีการใดที่ "ดีที่สุด"
Rik

6
ขึ้นอยู่กับสำนวนที่แพร่หลายของภาษาการเขียนโปรแกรม โปรดแท็กคำถามนี้ด้วยแท็กภาษาการเขียนโปรแกรม
30881 Teddy

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

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

คำตอบ:


484

หากคุณคาดหวังที่จะหาค่าอยู่เสมอให้โยนข้อยกเว้นหากไม่มีอยู่ ข้อยกเว้นจะหมายความว่ามีปัญหา

หากค่าอาจหายไปหรือมีอยู่และทั้งสองอย่างนั้นถูกต้องสำหรับแอปพลิเคชันตรรกะแล้วส่งคืนค่า null

สำคัญกว่า: คุณทำอะไรที่อื่นในรหัส? ความมั่นคงเป็นสิ่งสำคัญ


30
@Ken: +1 มันจะดีที่จะพูดถึงว่าถ้าคุณทำข้อยกเว้น แต่สามารถตรวจพบมันเบื้องต้น (เช่น HasItem (... )) จากนั้นผู้ใช้ควรให้วิธี Has * หรือมีการกล่าวว่า
user7116

4
แทนที่จะส่งคืนค่าหรือค่า Null เมื่อค่าหายไปให้ลองส่งคืนบางที <T> ดูmikehadlow.blogspot.nl/2011/01/monads-in-c-5-maybe.html
Erwin Rooijakkers

2
ใน @ErwinRooijakkers ทางเลือกการออกแบบในฐานะของ Java 8 คุณสามารถส่งคืนตัวเลือก <T>
José Andias

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

4
@crush ผมคิดว่าหลักแนวทางคือสิ่งที่พารามิเตอร์จะถูกส่งผ่านไปยังฟังก์ชัน หากคุณผ่านตัวตนเช่นเดียวกับที่คุณพูดถึงคีย์หลักมันควรจะถูกพิจารณาว่ายอดเยี่ยมถ้าไม่พบรายการนั้นเพราะมันบ่งบอกถึงสถานะที่ไม่สอดคล้องกันในระบบ ตัวอย่าง: GetPersonById(25)จะโยนถ้าคนนั้นถูกลบ แต่GetPeopleByHairColor("red")จะส่งกลับผลลัพธ์ที่ว่างเปล่า ดังนั้นฉันคิดว่าพารามิเตอร์พูดอะไรบางอย่างเกี่ยวกับความคาดหวัง
John Knoop

98

เพียงโยนข้อยกเว้นถ้ามันเป็นข้อผิดพลาดอย่างแท้จริง ถ้ามันเป็นพฤติกรรมที่คาดไว้สำหรับวัตถุที่ไม่มีอยู่กลับเป็นโมฆะ

มิฉะนั้นมันเป็นเรื่องของการตั้งค่า


4
ฉันไม่เห็นด้วย คุณสามารถโยนข้อยกเว้นเป็นรหัสสถานะ: "NotFoundException"
ACV

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

4
ฉันคิดว่าการจัดการเคสว่างนั้นง่ายกว่า "NotFoundException" คิดเกี่ยวกับจำนวนบรรทัดลองจับคุณต้องเขียนรอบทุกคำขอ retrival เดียวที่พ่น "NotFoundException" ... มันเจ็บปวดที่จะพร้อมรหัสทั้งหมดในสายตาของฉัน
visc

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

70

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

ไม่ว่าคุณจะทำอะไรฉันขอแนะนำให้ใช้ตัวเลือกที่สาม: ส่งคืนสตริงที่ระบุว่า "WTF"


บวกหนึ่งเพราะในสมัยก่อนฉันทำอย่างนั้นมากกว่าสองครั้งเป็นการแก้ไข "ชั่วขณะ" สกปรกอย่างรวดเร็ว ... ไม่มีความคิดที่ดี พิเศษถ้ามันจะถูกตรวจสอบถ้าคุณเป็นนักเรียน
rciafardone

14
ฉันกำลังจะลงคะแนนเนื่องจากตัวเลือก WTF ดูน่ากลัวสำหรับฉัน ... แต่เห็นได้ชัดว่าฉันมีหัวใจ
แต่งตัวประหลาด

5
โยนWtfExcepti😲nใหม่
Kamafeather

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

51

ถ้า null ไม่เคยระบุถึงข้อผิดพลาดแล้วเพียงแค่กลับ null

ถ้า null เป็นข้อผิดพลาดเสมอให้ทำการยกเว้น

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

เป็นการยากที่จะใช้รูทีนทดลองในทางที่ผิด มันง่ายมากที่จะลืมตรวจสอบค่าว่าง

ดังนั้นเมื่อ null เป็นข้อผิดพลาดคุณเพิ่งเขียน

object o = FindObject();

เมื่อโมฆะไม่ใช่ข้อผิดพลาดคุณสามารถรหัสสิ่งที่ต้องการ

if (TryFindObject(out object o)
  // Do something with o
else
  // o was not found

1
นี่จะเป็นข้อเสนอแนะที่มีประโยชน์มากขึ้นถ้า C # ให้ tuples จริงดังนั้นเราจึงสามารถหลีกเลี่ยงการใช้พารามิเตอร์ [ออก] ยังนี่คือรูปแบบที่ต้องการดังนั้น +1
Erik Forbes

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

ทำให้ฉันนึกถึงfindและfindOrFailจาก Laravel Eloquent
vivoconunxino

@ErikForbes ฉันรู้ว่าความคิดเห็นของคุณเก่า แต่คำตอบจะไม่ได้รับการกำหนดวัตถุหลายคุณสมบัติที่จะกลับมาจากTryFindObjectวิธีการ? Tuples ดูกระบวนทัศน์ที่ขี้เกียจสำหรับโปรแกรมเมอร์ที่ไม่ต้องการใช้เวลาในการกำหนดวัตถุที่ห่อหุ้มหลายค่า นั่นคือสิ่งสำคัญ tuples ทั้งหมดอยู่ที่หลักอย่างไรก็ตาม
บดขยี้

@crush - ตัวอักษร Tuple ที่มีชื่อเป็นตัวเลือก IMO นี่คือลิงก์ไปยัง async Try Get pattern with tuples stackoverflow.com/questions/1626597/…
ttugates

26

ฉันแค่อยากจะสรุปตัวเลือกต่าง ๆ ที่กล่าวถึงก่อนหน้านี้แล้วก็โยนตัวใหม่ใน:

  1. ส่งคืน null
  2. โยนข้อยกเว้น
  3. ใช้รูปแบบวัตถุ null
  4. จัดเตรียมพารามิเตอร์บูลีนให้คุณวิธีดังนั้นผู้เรียกสามารถเลือกได้หากเขาต้องการให้คุณยกเว้น
  5. จัดเตรียมพารามิเตอร์พิเศษดังนั้นผู้เรียกสามารถตั้งค่าที่จะรับกลับมาหากไม่พบค่า

หรือคุณอาจรวมตัวเลือกเหล่านี้:

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

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

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

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


ฉันชอบชื่อฟังก์ชั่นที่ชัดเจนโดยเฉพาะ orCreate และ orDefault
marcovtwout

5
ส่วนใหญ่นี้สามารถเขียนได้มากขึ้นอย่างหมดจดด้วยExpected<T> findObject(String)ที่Expected<T>มีฟังก์ชั่นorNull(), orThrow(), ,orSupplied(Supplier<T> supplier) orDefault(T default)ข้อมูลนี้ได้จากการจัดการข้อผิดพลาด
WorldSEnder

ฉันไม่รู้เกี่ยวกับคาดหวัง <T> จนกระทั่งตอนนี้ ฉันดูเหมือนจะค่อนข้างใหม่และอาจไม่มีอยู่เมื่อฉันเขียนคำตอบดั้งเดิม บางทีคุณควรแสดงความคิดเห็นเป็นคำตอบที่เหมาะสม
Lena Schimmel

นอกจากนี้คาดว่า <T> เป็นเทมเพลต C ++ มีการใช้งานของมันในภาษาเชิงวัตถุอื่น ๆ เช่นกัน?
Lena Schimmel

ใน Java 8 การคืนค่าตัวเลือก <T> (เรียกว่าอาจ <T> และอื่น ๆ ในภาษาอื่น) เป็นตัวเลือกเช่นกัน สิ่งนี้บ่งชี้อย่างชัดเจนถึงผู้โทรว่าไม่มีความเป็นไปได้ที่จะส่งคืนและจะไม่คอมไพล์หากผู้โทรไม่ได้จัดการความเป็นไปได้นั้นซึ่งตรงกันข้ามกับ null ซึ่ง (ใน Java ต่อไป) จะรวบรวมแม้ว่าผู้โทรจะไม่ตรวจสอบ .
ผู้ชายบางคน

18

ใช้รูปแบบวัตถุ null หรือโยนข้อยกเว้น


นี่คือคำตอบที่แท้จริง การคืนค่า Null เป็นนิสัยที่น่ากลัวของโปรแกรมเมอร์ที่ขี้เกียจ
jeremyjjbrown

ฉันไม่อยากเชื่อเลยว่าคำตอบนี้ยังไม่ได้รับการโหวตให้อยู่ด้านบน นี่คือคำตอบที่แท้จริงและวิธีการอย่างใดอย่างหนึ่งเป็นเรื่องง่ายและช่วยประหยัด code-bloat หรือ NPE จำนวนมาก
ความหายนะ


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

3
วัตถุ null จะทำงานอย่างไรสำหรับการค้นหาเอนทิตี เช่นPerson somePerson = personRepository.find("does-not-exist");สมมติว่าวิธีการนี้ส่งกลับวัตถุ null สำหรับ does-not-existID อะไรจะเป็นพฤติกรรมที่ถูกต้องเพื่อsomePerson.getAge()? ตอนนี้ฉันยังไม่มั่นใจว่ารูปแบบวัตถุ null เป็นโซลูชันที่เหมาะสมสำหรับการค้นหาเอนทิตี
Abdull


13

ข้อดีของการโยนข้อยกเว้น:

  1. การควบคุมการไหลที่สะอาดขึ้นในรหัสการโทรของคุณ การตรวจสอบ null injects สาขาตามเงื่อนไขซึ่งถูกจัดการโดยลอง / catch การตรวจหา null ไม่ได้ระบุว่าคุณกำลังตรวจสอบอะไรอยู่ - คุณกำลังตรวจสอบ null เพราะคุณกำลังมองหาข้อผิดพลาดที่คุณคาดหวังหรือคุณกำลังตรวจสอบ null เพื่อให้คุณไม่ส่งต่อไปยัง downchain เพิ่มเติม ?
  2. ลบความกำกวมของความหมาย "null" null เป็นตัวแทนของข้อผิดพลาดหรือเป็นโมฆะจริงเก็บไว้ในค่าหรือไม่ ยากที่จะบอกว่าเมื่อคุณมีสิ่งหนึ่งที่จะทำให้ความมุ่งมั่นหลุดออกไป
  3. ปรับปรุงความสอดคล้องระหว่างพฤติกรรมของเมธอดในแอปพลิเคชัน โดยทั่วไปแล้วข้อยกเว้นจะปรากฏในลายเซ็นเมธอดดังนั้นคุณจะสามารถเข้าใจได้ดีขึ้นว่าขอบกรณีวิธีการในบัญชีแอปพลิเคชันสำหรับอะไรและข้อมูลใดที่แอปพลิเคชันของคุณสามารถตอบสนองด้วยวิธีที่คาดการณ์ได้

สำหรับคำอธิบายเพิ่มเติมกับตัวอย่างดู: http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/


2
+1 เนื่องจากจุด 2 นั้นยอดเยี่ยม - null ไม่มีความหมายเดียวกับที่ไม่พบ สิ่งนี้มีความสำคัญมากขึ้นเมื่อจัดการกับภาษาแบบไดนามิกที่ Null อาจเป็นวัตถุที่ถูกจัดเก็บ / ดึงโดยฟังก์ชั่น - และในกรณีนั้น
Adam Terrey

1
+1 สำหรับจุด # 2 เป็นข้อผิดพลาดหรือไม่? เป็นโมฆะสิ่งที่เก็บไว้สำหรับคีย์ที่กำหนด? เป็นโมฆะบ่งบอกว่าคีย์ไม่อยู่? นี่เป็นคำถามที่แท้จริงที่ทำให้ชัดเจนว่าการส่งคืน null นั้นแทบไม่เคยถูกต้องเลย นี้น่าจะเป็นคำตอบที่ดีที่สุดที่นี่เป็นคนอื่นได้รับเพียงแค่ขว้างปาขึ้นคลุมเครือ "ถ้ามันพิเศษโยน"
ปิ๊

12

มันขึ้นอยู่กับว่าภาษาและรหัสของคุณส่งเสริม: LBYL (ดูก่อนที่คุณจะกระโดด) หรือ EAFP (ง่ายต่อการขอการให้อภัยมากกว่าการอนุญาต)

LBYL บอกว่าคุณควรตรวจสอบค่า (ดังนั้นส่งคืน null)
EAFP บอกให้ลองใช้การดำเนินการและดูว่ามันล้มเหลวหรือไม่ (โยนข้อยกเว้น)

แม้ว่าฉันเห็นด้วยกับข้างต้น .. ข้อยกเว้นควรใช้สำหรับเงื่อนไขพิเศษ / ข้อผิดพลาดและการคืนค่าเป็นโมฆะจะดีที่สุดเมื่อใช้เช็ค


EAFP vs. LBYL ใน Python:
http://mail.python.org/pipermail/python-list/2003-May/205182.html ( เว็บเอกสารเก่า )


3
ในบางกรณี EAFP เป็นวิธีการที่มีความหมายเพียงอย่างเดียว ยกตัวอย่างเช่นในแผนที่ / พจนานุกรมพร้อมกันไม่มีวิธีถามว่าการทำแผนที่จะมีอยู่เมื่อมีการร้องขอหรือไม่
supercat

11

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

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

-Alan


5

ข้อยกเว้นเกี่ยวข้องกับการออกแบบตามสัญญา

อินเทอร์เฟซของวัตถุเป็นสัญญาระหว่างวัตถุสองรายการผู้โทรต้องเป็นไปตามสัญญามิฉะนั้นผู้รับอาจจะล้มเหลวโดยมีข้อยกเว้น มีสัญญาที่เป็นไปได้สองข้อ

1) วิธีการป้อนข้อมูลทั้งหมดที่ถูกต้องซึ่งในกรณีนี้คุณจะต้องกลับเป็นโมฆะเมื่อวัตถุไม่พบ

2) การป้อนข้อมูลบางอย่างเท่านั้นที่ถูกต้องคือสิ่งที่ส่งผลให้วัตถุที่พบ ในกรณีนี้คุณต้องเสนอวิธีที่สองที่ช่วยให้ผู้โทรตรวจสอบว่าอินพุตนั้นถูกต้องหรือไม่ ตัวอย่างเช่น

is_present(key)
find(key) throws Exception

หากคุณให้ทั้งสองวิธีของสัญญาฉบับที่ 2 คุณจะได้รับอนุญาตให้ทำการยกเว้นยกเว้นไม่พบสิ่งใดเลย!


4

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


4

ขึ้นอยู่กับความหมายของวัตถุที่ไม่พบ

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

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

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


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

4

นี่เป็นคำแนะนำเพิ่มเติมอีกสองสามข้อ

หากส่งคืนคอลเล็กชันให้หลีกเลี่ยงการส่งคืน null ให้ส่งคืนคอลเล็กชันว่างซึ่งทำให้การจัดการง่ายขึ้นโดยไม่มีการตรวจสอบ null ก่อน

. NET API หลายตัวใช้รูปแบบของพารามิเตอร์ thrownOnError ซึ่งให้ตัวเลือกแก่ผู้โทรว่าเป็นสถานการณ์ที่พิเศษจริง ๆ หรือไม่หากไม่พบวัตถุ Type.GetType เป็นตัวอย่างของสิ่งนี้ รูปแบบทั่วไปอื่นที่มี BCL คือรูปแบบ TryGet ที่ส่งคืนบูลีนและค่าจะถูกส่งผ่านพารามิเตอร์เอาต์พุต

คุณสามารถพิจารณารูปแบบวัตถุ Null ในบางสถานการณ์ซึ่งอาจเป็นค่าเริ่มต้นหรือรุ่นที่ไม่มีพฤติกรรม ที่สำคัญคือหลีกเลี่ยงการตรวจสอบเป็นโมฆะตลอดทั้งฐานรหัส ดูที่นี่สำหรับข้อมูลเพิ่มเติมhttp://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx


3

ในบางฟังก์ชั่นฉันเพิ่มพารามิเตอร์:

..., bool verify = true)

True หมายถึง throw, false หมายถึงส่งคืนค่าข้อผิดพลาดที่ส่งคืน วิธีนี้ใครก็ตามที่ใช้ฟังก์ชั่นนี้มีทั้งสองตัวเลือก ค่าเริ่มต้นควรเป็นจริงเพื่อประโยชน์ของผู้ที่ลืมเกี่ยวกับการจัดการข้อผิดพลาด


3

ส่งคืน null แทนการโยนข้อยกเว้นและบันทึกความเป็นไปได้ของค่าส่งคืน null ในเอกสาร API อย่างชัดเจน หากรหัสการโทรไม่เป็นไปตาม API และตรวจสอบกรณีที่เป็นโมฆะมันจะส่งผลให้เกิด "การยกเว้นตัวชี้โมฆะ" บางประเภท :)

ใน C ++ ฉันคิดได้สามวิธีในการตั้งค่าวิธีการค้นหาวัตถุ

ตัวเลือก A

Object *findObject(Key &key);

ส่งคืน null เมื่อไม่พบวัตถุ ดีและเรียบง่าย ฉันจะไปกับคนนี้ แนวทางอื่น ๆ ด้านล่างนี้สำหรับผู้ที่ไม่ได้เกลียดชัง

ตัวเลือก B

void findObject(Key &key, Object &found);

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

ตัวเลือก C

bool findObject(Key &key, Object &found);

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

if (!findObject(myKey, myObj)) { ...

3

อ้างถึงกรณีที่ไม่มีการพิจารณาว่าเป็นโมฆะพฤติกรรมพิเศษฉันแน่นอนสำหรับวิธีลองมันชัดเจนไม่จำเป็นต้อง "อ่านหนังสือ" หรือ "ดูก่อนที่คุณจะกระโดด" ตามที่ได้กล่าวไว้ที่นี่

ดังนั้นโดยทั่วไป:

bool TryFindObject(RequestParam request, out ResponseParam response)

และนี่หมายความว่ารหัสของผู้ใช้จะชัดเจนเช่นกัน

...
if(TryFindObject(request, out response)
{
  handleSuccess(response)
}
else
{
  handleFailure()
}
...

2

หากเป็นสิ่งสำคัญที่รหัสลูกค้าจะต้องทราบความแตกต่างระหว่างพบและไม่พบและนี่ควรจะเป็นพฤติกรรมประจำ รหัสลูกค้าสามารถตัดสินใจได้ว่าจะทำอย่างไร


2

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


2

หรือคืนตัวเลือก

ตัวเลือกนั้นเป็นคลาสของคอนเทนเนอร์ที่บังคับให้ไคลเอ็นต์จัดการเคสเคส Scala มีแนวคิดนี้ค้นหา API

จากนั้นคุณมีวิธีการเช่น T getOrElse (ค่า T ถ้า IfNull) บนวัตถุนี้พวกเขาทั้งคืนวัตถุที่พบหรือ allternative ลูกค้า specifieces


2

ชอบกลับ null -

หากผู้เรียกใช้โดยไม่ตรวจสอบข้อยกเว้นจะเกิดขึ้นตรงนั้น

หากผู้โทรไม่ได้ใช้จริง ๆ อย่าเสียภาษีเขาtry/ catchบล็อก


2

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


1

ตราบใดที่มันควรจะส่งคืนการอ้างอิงไปยังวัตถุการคืนค่า NULL ควรจะดี

อย่างไรก็ตามหากมันคืนเลือดทั้งหมด (เช่นใน C ++ ถ้าคุณทำ: 'return blah;' แทนที่จะ 'return & blah;' (หรือ 'blah' เป็นตัวชี้) คุณจะไม่สามารถส่งค่า NULL ได้เนื่องจากเป็น ไม่ใช่ของประเภท 'วัตถุ' ในกรณีนั้นการโยนข้อยกเว้นหรือส่งคืนวัตถุเปล่าที่ไม่มีชุดธงที่ประสบความสำเร็จคือฉันจะเข้าหาปัญหาได้อย่างไร


1

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


1

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

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


1

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



1

หากวิธีการส่งกลับคอลเลกชันแล้วส่งกลับคอลเลกชันที่ว่างเปล่า (เช่นที่กล่าวข้างต้น) แต่โปรดอย่า Collections.EMPTY_LIST หรือเช่นนั้น! (ในกรณีของ Java)

หากวิธีการ retrives วัตถุเดียวแล้วคุณมีตัวเลือกบางอย่าง

  1. หากวิธีการควรหาผลลัพธ์เสมอและเป็นกรณียกเว้นจริงที่จะไม่พบวัตถุคุณควรโยนข้อยกเว้น (ใน Java: โปรดยกเว้นข้อ จำกัด )
  2. (Java เท่านั้น) หากคุณสามารถยอมรับได้ว่าวิธีการโยนข้อยกเว้นที่ตรวจสอบแล้วให้โยน ObjectNotFoundException ที่เฉพาะเจาะจงของโครงการหรือสิ่งที่คล้ายกัน ในกรณีนี้คอมไพเลอร์บอกว่าคุณถ้าคุณลืมจัดการข้อยกเว้น (นี่คือการจัดการสิ่งที่ฉันไม่พบใน Java)
  3. ถ้าคุณบอกว่ามันใช้ได้จริง ๆ ถ้าไม่พบวัตถุและชื่อเมธอดของคุณเหมือนกับ findBookForAuthorOrReturnNull (.. ) คุณสามารถคืนค่าว่างได้ ในกรณีนี้ขอแนะนำอย่างยิ่งให้ใช้การตรวจสอบแบบคงที่หรือการตรวจสอบคอมไพเลอร์บางอย่างซึ่งจะป้องกันไม่ให้เกิดการซ้ำของผลลัพธ์โดยไม่มีการตรวจสอบเป็นโมฆะ ในกรณีของ Java มันสามารถเป็นเช่น FindBugs (ดู DefaultAnnotation ที่http://findbugs.sourceforge.net/manual/annotations.html ) หรือ IntelliJ-Checking

ระวังถ้าคุณตัดสินใจคืนค่าว่าง หากคุณไม่ได้เป็นโปรแกรมเมอร์คนเดียวในโครงการคุณจะได้รับ NullPointerExceptions (ใน Java หรือภาษาอื่น ๆ ) ในเวลาทำงาน! ดังนั้นอย่าส่งคืนค่า Null ซึ่งไม่ได้ตรวจสอบ ณ เวลารวบรวม


nullไม่ได้ถ้ารหัสถูกเขียนอย่างถูกต้องที่จะคาดหวัง ดูคำตอบที่ได้รับการโหวตมากที่สุด
Andrew Barber เมื่อ

แต่เฉพาะในกรณีที่คุณมั่นใจในเวลารวบรวมว่ามีการตรวจสอบค่า Null ทั้งหมด สิ่งนี้สามารถทำได้โดยใช้ FindBugs @NutNull ที่ระดับแพ็คเกจและทำเครื่องหมายวิธีการของคุณว่า "อาจคืนค่าว่าง" หรือใช้ภาษาอย่าง Kotlin หรือ Nice แต่มันง่ายกว่าที่จะไม่คืนค่าว่าง
iuzuz

"เรียบง่าย" บางที แต่บ่อยครั้งไม่ถูกต้องธรรมดา
แอนดรูว์บาร์เบอร์

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

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

1

หากคุณกำลังใช้ห้องสมุดหรือระดับที่พ่นยกเว้นอื่นคุณควรrethrowมัน นี่คือตัวอย่าง Example2.java เป็นเหมือนห้องสมุดและ Example.java ใช้เป็นวัตถุ Main.java เป็นตัวอย่างในการจัดการข้อยกเว้นนี้ คุณควรแสดงข้อความที่มีความหมายและ (ถ้าจำเป็น) การติดตามสแต็กกับผู้ใช้ในด้านการโทร

Main.java

public class Main {
public static void main(String[] args) {
    Example example = new Example();

    try {
        Example2 obj = example.doExample();

        if(obj == null){
            System.out.println("Hey object is null!");
        }
    } catch (Exception e) {
        System.out.println("Congratulations, you caught the exception!");
        System.out.println("Here is stack trace:");
        e.printStackTrace();
    }
}
}

Example.java

/**
 * Example.java
 * @author Seval
 * @date 10/22/2014
 */
public class Example {
    /**
     * Returns Example2 object
     * If there is no Example2 object, throws exception
     * 
     * @return obj Example2
     * @throws Exception
     */
    public Example2 doExample() throws Exception {
        try {
            // Get the object
            Example2 obj = new Example2();

            return obj;

        } catch (Exception e) {
            // Log the exception and rethrow
            // Log.logException(e);
            throw e;
        }

    }
}

Example2.java

 /**
 * Example2.java
 * @author Seval
 *
 */
public class Example2 {
    /**
     * Constructor of Example2
     * @throws Exception
     */
    public Example2() throws Exception{
        throw new Exception("Please set the \"obj\"");
    }

}

หากข้อยกเว้นที่จะถูกโยนออกจากฟังก์ชั่นไม่ใช่ข้อยกเว้นแบบรันไทม์และผู้เรียกคาดว่าจะจัดการมัน (แทนที่จะเป็นแค่การยกเลิกโปรแกรม) จากนั้นแทนที่จะโยนข้อยกเว้นจากระบบย่อยภายในที่ผู้เรียกไม่สามารถคาดหวังได้ มันจะดีกว่าที่จะห่อข้อยกเว้นภายในด้วยข้อยกเว้นที่ตรวจสอบภายนอกในขณะที่ 'ผูก' ข้อยกเว้นภายในเพื่อให้การดีบักบางคนสามารถหาสาเหตุที่ข้อยกเว้นภายนอกถูกโยนทิ้ง ตัวอย่างเช่น example1 สามารถใช้ 'Throw MyCheckedException ใหม่ ("โปรดตั้งค่า \" obj \ "", e)' เพื่อรวม 'e' ในข้อยกเว้นที่ส่งออกไป
ผู้ชายบางคน

0

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

  • พบวัตถุ; ส่งคืนวัตถุ
  • ไม่พบวัตถุ โยนข้อยกเว้น

มิฉะนั้นส่งคืน null

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