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


21

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


1
ที่เกี่ยวข้อง: stackoverflow.com/questions/3989264/…

2
ภาษาบางภาษาขัดข้องเป็นโมฆะดีกว่าภาษาอื่น สำหรับ "โค้ดที่ได้รับการจัดการ" เช่น. Net / Java การอ้างอิงแบบ null เป็นเพียงปัญหาประเภทอื่นในขณะที่โค้ดเนทีฟอื่น ๆ อาจไม่จัดการสิ่งนี้อย่างสง่างาม (คุณไม่ได้กล่าวถึงภาษาเฉพาะ) แม้ในโลกที่มีการจัดการบางครั้งคุณต้องการที่จะเขียนรหัสที่ไม่ปลอดภัย (ฝังตัว? อาวุธ?) และบางครั้งคุณต้องการที่จะเลวทรามดังอย่างเร็วที่สุด (การทดสอบหน่วย) โค้ดทั้งสองประเภทสามารถเรียกใช้ในไลบรารีเดียวกันซึ่งอาจเป็นปัญหา โดยทั่วไปฉันคิดว่ารหัสที่พยายามไม่ทำร้ายความรู้สึกของคอมพิวเตอร์เป็นความคิดที่ไม่ดี ความปลอดภัยล้มเหลวเป็นเรื่องยากอยู่แล้ว
งาน

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

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

คำตอบ:


24

การอ้างอิงแบบ Null ไม่ได้ "หลบเลี่ยง" มากกว่าข้อยกเว้นอย่างน้อยก็มีใครบางคนที่ฉันรู้จักหรือเคยอ่าน ฉันคิดว่าคุณเข้าใจผิดเกี่ยวกับภูมิปัญญาดั้งเดิม

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

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

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

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

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


5
จริงๆแล้วมีภาษาที่ไม่มี null หรือไม่มีและไม่จำเป็นต้อง "แทนที่ด้วยอย่างอื่น" การอ้างอิงที่เป็นโมฆะบ่งบอกว่าอาจมีบางอย่างที่นั่นหรืออาจไม่มี หากคุณต้องการให้ผู้ใช้ตรวจสอบอย่างชัดเจนว่ามีบางอย่างที่นั่นแสดงว่าคุณได้แก้ไขปัญหาแล้ว ดูตัวอย่างเซลล์สำหรับชีวิตจริง
Johanna Larsson

3
@ErikKronberg ใช่ "ความผิดพลาดพันล้านดอลล่าร์" และเรื่องไร้สาระทั้งหมดขบวนพาเหรดของผู้คนวิ่งเหยาะๆและอ้างว่ามันสดใหม่และน่าหลงใหลไม่สิ้นสุดนั่นคือเหตุผลที่ลบความคิดเห็นก่อนหน้านี้ออก การแทนที่การปฏิวัติเหล่านี้ที่ผู้คนไม่เคยพลาดที่จะนำมาใช้นั้นมักจะมีความแตกต่างของ Null Object, Option หรือ Contract ซึ่งไม่ได้กำจัดข้อผิดพลาดทางตรรกะอย่างน่าอัศจรรย์พวกเขาเพียงแค่เลื่อนหรือเลื่อนขั้นตามลำดับ อย่างไรก็ตามนี้จะเห็นได้ชัดคำถามเกี่ยวกับการเขียนโปรแกรมภาษาที่ทำมีnullดังนั้นจริงๆ Haskell ไม่เกี่ยวข้องสวยที่นี่
Aaronaught

1
คุณกำลังเถียงอย่างจริงจังว่าไม่จำเป็นต้องทำการทดสอบแบบ Null หรือไม่?
Johanna Larsson

3
@ErikKronberg: ใช่ฉัน "เถียงอย่างจริงจัง" ว่าการทดสอบ null ไม่แตกต่างจาก (a) โดยเฉพาะการออกแบบแอปพลิเคชันทุกระดับของพฤติกรรมของ Null Object (b) ต้องจับคู่รูปแบบ ตัวเลือกตลอดเวลาหรือ (c) ไม่อนุญาตให้ผู้พูดพูดว่า "ฉันไม่รู้" และบังคับให้มีข้อยกเว้นหรือล้มเหลว มีเหตุผลว่าทำไมnullต้องอดทนเป็นอย่างดีมานานและคนส่วนใหญ่ที่พูดอย่างอื่นดูเหมือนจะเป็นนักวิชาการที่มีประสบการณ์น้อยในการออกแบบแอพในโลกแห่งความเป็นจริงที่มีข้อ จำกัด เช่นความต้องการที่ไม่สมบูรณ์
Aaronaught

3
@Aaraught: บางครั้งฉันหวังว่าจะมีปุ่ม downvote สำหรับความคิดเห็น ไม่มีเหตุผลที่จะพูดจาโผงผางเช่นนั้น
Michael Shaw

11

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


4
ความล้มเหลวในการจัดการค่า NULL นั้นจะเป็นการเพิกเฉยต่ออินเทอร์เฟซระหว่างรหัสของคุณกับสิ่งใดก็ตามที่ส่งคืน นักพัฒนาที่จะทำผิดพลาดนั้นจะทำให้คนอื่น ๆ ในภาษาที่ไม่ได้เป็น NULL
Blrfl

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

@ Job: ถ้าคุณไม่มี debugger คุณทราบหรือไม่ว่า 99.99% ของเวลาที่แอปพลิเคชันของคุณกำลังทำงานในสภาพแวดล้อมการเปิดตัว เมื่อเกิดเหตุการณ์นี้ขึ้นคุณจะต้องการให้คุณใช้ข้อยกเว้นที่มีความหมายมากกว่านี้ แอปของคุณอาจยังต้องล้มเหลวและสร้างความรำคาญให้ผู้ใช้ แต่อย่างน้อยมันจะส่งออกข้อมูลการแก้ไขข้อบกพร่องที่จะช่วยให้คุณสามารถติดตามปัญหาได้ทันที
Aaronaught

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

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

8

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

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

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


พิจารณาคลาสย่อย Uninitialized ด้วยสตริงการระบุและวิธีการทั้งหมดจะโยนข้อยกเว้น หากหนึ่งในสิ่งเหล่านี้ปรากฏขึ้นคุณจะรู้ว่าเกิดอะไรขึ้น บนระบบฝังตัวที่มีหน่วยความจำ จำกัด เวอร์ชันการผลิตของ Uninitialized factory สามารถส่งคืนค่าว่างได้
Jim Balter

3
@Jim Balter: ฉันคิดว่าฉันสับสนว่ามันจะช่วยในทางปฏิบัติอย่างไร ในโปรแกรมที่ไม่เกี่ยวกับเรื่องไร้สาระคุณจะต้องจัดการกับค่าที่อาจไม่สามารถเริ่มต้นได้ ดังนั้นจึงต้องมีวิธีที่จะบ่งบอกถึงค่าเริ่มต้น ดังนั้นคุณยังต้องตรวจสอบเรื่องนี้ก่อนที่จะดำเนินการต่อไป ดังนั้นแทนที่จะเป็นความผิดพลาดที่อาจเกิดขึ้นตอนนี้คุณอาจทำงานกับข้อมูลที่ไม่ถูกต้อง
Ed S.

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

1
@Jim Balter: ใช่ฉันยังไม่เห็นความแตกต่างในทางปฏิบัติและฉันไม่เห็นว่ามันจะทำให้ชีวิตง่ายขึ้นสำหรับคนที่เขียนโปรแกรมจริงนอกสถาบันการศึกษา ไม่ได้หมายความว่าไม่มีประโยชน์เลยเพียง แต่ดูเหมือนว่าพวกเขาจะไม่ปรากฏชัดเจนต่อฉัน
Ed S.

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

5

โทนีฮอร์ที่สร้างความคิดของการอ้างอิงโมฆะในสถานที่แรกที่เรียกว่าความผิดพลาดหนึ่งล้านดอลลาร์

ปัญหาไม่ได้เกี่ยวกับการอ้างอิงที่เป็นโมฆะต่อการค้นหา แต่เกี่ยวกับการขาดการตรวจสอบประเภทที่เหมาะสมในภาษาที่ปลอดภัย (ส่วนใหญ่) ประเภทการพิมพ์

การขาดการสนับสนุนจากภาษานี้หมายความว่าบั๊ก "บั๊ก - โมฆะ" อาจแฝงตัวอยู่ในโปรแกรมเป็นเวลานานก่อนที่จะถูกตรวจจับ นั่นคือลักษณะของข้อบกพร่องแน่นอน แต่ "โมฆะบั๊ก" เป็นที่รู้กันว่าสามารถหลีกเลี่ยงได้

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

ในภาษาอื่นมีคำถามเกี่ยวกับวิธีจัดการกับมันเสมอ

ใน Java หรือ C # คุณจะได้รับข้อยกเว้นหากคุณพยายามเรียกใช้เมธอดในการอ้างอิงแบบ null และอาจไม่เป็นไร ดังนั้นโปรแกรมเมอร์ Java หรือ C # ส่วนใหญ่จึงคุ้นเคยกับสิ่งนี้และไม่เข้าใจว่าทำไมจึงต้องการทำอย่างอื่น (และหัวเราะที่ C ++)

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

จริงๆแล้วมันคือการถกเถียงข้อผิดพลาดรหัส / ข้อยกเว้นเก่า แต่คราวนี้ด้วยSentinel Valueแทนข้อผิดพลาดรหัส

แล้วแต่ความเหมาะสมที่สุดขึ้นอยู่กับสถานการณ์และความหมายที่คุณกำลังมองหา


แม่นยำ. nullมันเป็นความชั่วร้ายเพราะมันsubverts ระบบการพิมพ์ (ได้รับทางเลือกมีข้อเสียเปรียบในความฟุ้งซ่านอย่างน้อยในบางภาษา.)
หอยทากวิศวกรรม

2

คุณไม่สามารถแนบข้อความแสดงข้อผิดพลาดที่มนุษย์อ่านได้เข้ากับตัวชี้โมฆะ

(อย่างไรก็ตามคุณสามารถฝากข้อความข้อผิดพลาดไว้ในไฟล์บันทึก)

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

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


2

การคืนค่า NULL (หรือศูนย์ตัวเลขหรือบูลีน false) เพื่อส่งสัญญาณข้อผิดพลาดนั้นผิดทั้งในเชิงเทคนิคและเชิงแนวคิด

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

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

ในอดีตมีการรายงานข้อผิดพลาดด้วยวิธีนี้เนื่องจากภาษาการเขียนโปรแกรมเช่น C ไม่มีการจัดการข้อยกเว้นอยู่ในภาษาและวิธีที่แนะนำ (โดยใช้การข้ามแบบยาว) นั้นค่อนข้างลำบาก

นอกจากนี้ยังมีปัญหาด้านการบำรุงรักษาด้วยข้อยกเว้นคุณต้องเขียนโค้ดเพิ่มเติมเพื่อจัดการกับความล้มเหลว ถ้าคุณทำไม่ได้โปรแกรมจะล้มเหลวเร็วและแรง (ซึ่งถือว่าดี) หากคุณคืนค่า NULL เป็นสัญญาณข้อผิดพลาดพฤติกรรมเริ่มต้นของโปรแกรมคือการละเว้นข้อผิดพลาดและดำเนินการต่อจนกว่าจะนำไปสู่ปัญหาอื่น ๆ ตามทาง - ข้อมูลเสียหาย segfaults, NullReferenceExceptions ขึ้นอยู่กับภาษา ในการส่งสัญญาณข้อผิดพลาดเร็วและดังคุณต้องเขียนรหัสพิเศษและเดาว่า: อะไรคือส่วนที่เหลือเมื่อคุณถึงกำหนด


1

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

หากคุณอนุญาตให้พอยน์เตอร์พอยน์เตอร์เป็นกรณีที่ถูกต้องนั่นเป็นกรณีพิเศษ คุณต้องการตรรกะการจัดการกรณีพิเศษซึ่งมักจะอยู่ในสถานที่ต่าง ๆ มากมาย นั่นเป็นความซับซ้อนพิเศษ

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

ความซับซ้อนมากขึ้นมักหมายถึงข้อผิดพลาดเพิ่มเติม

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

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


1

เจาะจงไปที่ C ++ แต่มีการอ้างอิงแบบ null จะถูกหลีกเลี่ยงเพราะความหมายแบบ null ใน C ++ นั้นสัมพันธ์กับชนิดของตัวชี้ มันค่อนข้างสมเหตุสมผลสำหรับฟังก์ชั่นเปิดไฟล์ที่จะล้มเหลวและส่งกลับตัวชี้โมฆะ; ในความเป็นจริงfopen()ฟังก์ชั่นทำตรงนั้น


อันที่จริงถ้าคุณพบว่าตัวเองมีการอ้างอิงที่ว่างใน C ++ มันเป็นเพราะโปรแกรมของคุณจะเสียแล้ว
Kaz Dragon

1

มันขึ้นอยู่กับภาษา

ตัวอย่างเช่น Objective-C ช่วยให้คุณส่งข้อความไปยังวัตถุ null (ไม่มี) โดยไม่มีปัญหา การเรียกไปที่ศูนย์จะส่งกลับศูนย์เช่นกันและถือว่าเป็นคุณสมบัติภาษา

ฉันชอบมันเป็นการส่วนตัวเนื่องจากคุณสามารถพึ่งพาพฤติกรรมนั้นและหลีกเลี่ยงการif(obj == null)สร้างซ้อนซ้อนที่ซับซ้อนทั้งหมด

ตัวอย่างเช่น

if (myObject != nil && [myObject doSomething])
{
    ...
}

สามารถย่อให้เหลือ:

if ([myObject doSomething])
{
    ...
}

กล่าวโดยสรุปจะทำให้โค้ดของคุณอ่านง่ายขึ้น


0

ฉันไม่บีบแตรไม่ว่าคุณจะคืนค่าว่างหรือโยนข้อยกเว้นตราบใดที่คุณบันทึกไว้


และยังตั้งชื่อมันหรือGetAddressMaybe GetSpouseNameOrNull

-1

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

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


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

-1

การอ้างอิงแบบ Null มักจะมีประโยชน์มากตัวอย่างเช่นองค์ประกอบในรายการที่เชื่อมโยงสามารถมีตัวตายตัวแทนบางตัวหรือไม่มีตัวตายตัวแทน ใช้nullสำหรับ "ไม่มีตัวตายตัวแทน" เป็นเรื่องปกติอย่างสมบูรณ์ หรือบุคคลสามารถมีคู่ครองหรือไม่ - ใช้nullสำหรับ "คนไม่มีคู่สมรส" เป็นธรรมชาติอย่างสมบูรณ์แบบเป็นธรรมชาติมากกว่าการมีบางคน "ไม่มีคู่สมรส" - ค่าพิเศษที่Person.Spouseสมาชิกสามารถอ้างถึง

แต่: ค่าจำนวนมากไม่ใช่ตัวเลือก ในโปรแกรม OOP ทั่วไปฉันจะบอกว่ามากกว่าครึ่งของการอ้างอิงไม่สามารถเกิดขึ้นได้nullหลังจากการเริ่มต้นมิฉะนั้นโปรแกรมจะล้มเหลว มิฉะนั้นจะต้องมีการif (x != null)ตรวจสอบโค้ด เหตุใดการอ้างอิงทุกรายการจึงควรเป็นโมฆะโดยค่าเริ่มต้น มันควรจะเป็นวิธีอื่น ๆ : ตัวแปรควรไม่เป็นโมฆะโดยค่าเริ่มต้นและคุณควรจะต้องพูดว่า "โอ้และค่านี้ก็ควรจะเป็นnullเช่นกัน"


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

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

-1

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


ไม่ฉันไม่ได้หมายถึงข้อยกเว้นการอ้างอิงว่างเปล่า ในทุกภาษาฉันรู้ว่าไม่ได้กำหนดค่าเริ่มต้น แต่ตัวแปรที่ประกาศไว้เป็นรูปแบบของค่าที่เป็นโมฆะ
davidk01

แต่คำถามของคุณไม่เกี่ยวกับตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้น และมีภาษาที่ไม่ได้ใช้ค่า null สำหรับตัวแปรที่ไม่มีการกำหนดค่าเริ่มต้น แต่ให้ใช้อ็อบเจกต์ wrapper แทนซึ่งสามารถเลือกที่จะเก็บค่า - Scala และ Haskell
Jim Balter

1
"... แต่แทนที่จะใช้วัตถุห่อหุ้มที่อาจมีค่าก็ได้" ซึ่งเป็นที่ชัดเจนไม่มีอะไรเหมือนประเภท nullable
Aaronaught

1
ใน haskell ไม่มีสิ่งเช่นตัวแปร uninitialized คุณสามารถประกาศ IORef แล้วเริ่มต้นด้วย None เป็นค่าเริ่มต้น แต่มันค่อนข้างคล้ายกับการประกาศตัวแปรในภาษาอื่น ๆ และปล่อยให้มันไม่กำหนดค่าเริ่มต้น การทำงานในคอร์ที่ทำงานได้อย่างหมดจดนอกโปรแกรมเมอร์ IO monad haskell ไม่มีการขอความช่วยเหลือประเภทอ้างอิงดังนั้นจึงไม่มีปัญหาการอ้างอิงเป็นโมฆะ
davidk01

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