เหตุใดตัวเลือก / อาจถือว่าเป็นความคิดที่ดีและข้อยกเว้นที่ตรวจสอบแล้วไม่ได้


23

ภาษาการเขียนโปรแกรมบางอย่างเช่น Scala มีแนวคิดของOptionประเภท (เรียกอีกอย่างว่าMaybe) ซึ่งสามารถมีค่าหรือไม่

จากสิ่งที่ฉันได้อ่านเกี่ยวกับพวกเขาพวกเขาได้รับการพิจารณาอย่างกว้างขวางว่าเป็นวิธีที่ดีกว่าในการจัดการกับปัญหานี้มากกว่าnullเพราะพวกเขาบังคับให้โปรแกรมเมอร์พิจารณากรณีที่อาจไม่มีค่าแทนที่จะระเบิดในระหว่างรันไทม์

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

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


ดูEither e aประเภทข้อมูล

4
เกี่ยวกับข้อยกเว้นที่ตรวจสอบ: ในฐานะผู้ใช้ที่มีโอเพ่นซอร์สจำนวนมากและ libs Java ภายในที่มีการพัฒนาโค้ดฐานและ docs ที่หายไป / ล้าสมัยฉันสั่นสะเทือนด้วยความคิดที่ว่า Java จะไม่บังคับใช้ข้อยกเว้นบางอย่างที่จะประกาศอย่างชัดเจน มันจะเป็นฝันร้ายของข้อผิดพลาดรันไทม์ที่ไม่สามารถจัดการได้โผล่ขึ้นมาในที่ไม่ดีโดยไม่คาดคิด และในที่สุด Java7 ก็จัดการข้อยกเว้นเกือบจะมีสติ, กำจัดความยุ่งเหยิงเก่า ๆ
hyde

คำตอบ:


24

เพราะOptions เป็นองค์ประกอบ มีจำนวนมากของวิธีการที่เป็นประโยชน์ในมีOptionที่ให้คุณสามารถเขียนโค้ดรัดกุมในขณะที่ยังช่วยให้การควบคุมที่แม่นยำในการไหล: map, flatMap, toList, flattenและอื่น ๆ นี่เป็นเพราะความจริงที่ว่าOptionเป็น monad ชนิดหนึ่งวัตถุบางอย่างที่เรารู้ดีว่าจะเขียนได้อย่างไร หากคุณไม่ได้มีวิธีการเหล่านี้และต้องจับคู่รูปแบบตลอดเวลาOptionหรือโทรisDefinedบ่อย ๆ พวกเขาอาจไม่ได้มีประโยชน์เท่าที่ควร

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


1
ข้อยกเว้นที่ตรวจสอบแล้วเขียนในลักษณะเดียวกันมากกว่าหรือน้อยกว่า ... ความแตกต่างระหว่างtry {/* bunch of complex code involving calls to 50 different methods that may throw SomeCheckedException */} catch(SomeCheckedException e) {/* operation failed, do something */}และfromMaybe someDefaultValue (something >>= otherThing >>= ...50 other functions that may return Nothing...)คืออะไรกันแน่ นอกเหนือจากข้อเท็จจริงที่ว่าอดีตให้รายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่คุณผิดพลาด
253751

14

ในขณะที่เกี่ยวข้องข้อยกเว้นและวัตถุอาจไม่ได้จัดการกับปัญหาประเภทเดียวกัน

ข้อยกเว้น

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

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

อาจจะเป็นวัตถุ

บางทีควรเลือกวัตถุเมื่อคุณสามารถจัดการกับ "ความล้มเหลว" ในพื้นที่ ในกรณีดังกล่าวพวกเขาจะแทนที่รหัสส่งคืน + ผ่านโดยอ้างอิง API หรือประเภท nullable

ข้อได้เปรียบของวัตถุบางทีคือคุณประกาศอย่างชัดเจนว่ามีบางอย่างผิดปกติ ใน Haskell วัตถุที่ไม่ใช่อาจจะต้องมีค่ามิฉะนั้นโปรแกรมจะไม่รวบรวม

ปัญหาเกี่ยวกับประเภท nullable คือคุณต้องตรวจสอบ null ตลอดเวลาเพื่อความปลอดภัยอย่างแน่นอน สถานะ "บางสิ่งอาจผิดปกติ" คือสถานะเริ่มต้น

ปัญหาเกี่ยวกับรหัสส่งคืน + ส่งโดย apis คือพวกเขาไม่สามารถอ่านได้สำหรับคนส่วนใหญ่


1
@ MattFenwick ขอบคุณสำหรับความคิดเห็น ทำไมคุณถึงคิดว่าตัวอย่าง csv ไม่สมเหตุสมผล? OP ไม่ได้ขอเทคนิคการหลีกเลี่ยงสำเร็จรูปและฉันมีความรู้สึกว่าคำศัพท์เช่น functor และ monads อาจจะเป็นเทคนิคสำหรับคำถามนี้
Simon Bergot

1
ฉันต้องการจะชี้ให้เห็นว่ากับ Java (ไม่แน่ใจเกี่ยวกับภาษาอื่น ๆ ที่มีการตรวจสอบข้อยกเว้น) IDEs ดูแลการเพิ่มและการตัดแต่งกิ่งพ่นและปรับปรุง javadoc ความคิดเห็นส่วนสำเร็จรูป อย่างน้อยก็ส่วนนั้นก็ไม่ได้รำคาญและเจ็บปวดอย่างแน่นอน ไม่ว่าจะเป็นความเจ็บปวดหรือความเป็นประโยชน์หรือสิ่งที่อยู่ในระหว่างการออกแบบเมื่อทำ API ที่เรื่องอื่น ...
hyde

5
@hyde: เพียงเพราะ IDE สามารถสร้างการสร้างสำเร็จรูปที่ไม่มีจุดหมายได้โดยอัตโนมัติไม่ได้หมายความว่าการสร้างที่ไม่มีประโยชน์นั้นไม่เจ็บปวด
Michael Shaw

2
@hyde: แต่ความเจ็บปวดไม่ได้ถูกลบออก หม้อไอน้ำไร้จุดหมายยังคงอยู่ที่นั่นทำให้โค้ดยุ่งเหยิงโดยไม่มีเหตุผล หากมีเหตุผลสำหรับการต้มก็คืออะไร?
Michael Shaw

2
@MichaelShaw หากข้อยกเว้นไม่มีจุดหมายให้ลบออก: ละเว้นสถานการณ์หรือคืนค่าข้อผิดพลาดแทน หากเป็นข้อบกพร่องหรือสถานการณ์ที่ไม่สามารถกู้คืนได้ให้ใช้ข้อยกเว้นที่ไม่ได้ตรวจสอบ สิ่งที่เหลืออยู่ก็มีความสำคัญพอ ๆ กับตัวอย่างของพารามิเตอร์ประเภทต่างๆ ถ้ามันเป็น API ที่ไม่ดีใน lib ที่มีอยู่ให้พิจารณาเมธอด / คลาส wrapper โดยใช้ lib อื่นหรือแค่ทนกับ API ที่ไม่ดี
hyde

1

เพราะด้วยMaybeคุณสามารถชะลอการจัดการข้อผิดพลาดจนกว่าคุณจะต้องการค่าจริง (ซึ่งอาจเป็นวิธีการบางอย่างที่โทรออก)

ในขณะที่การยกเว้นการตรวจสอบความต้องการที่จะจัดการในสถานที่โทร

สิ่งเดียวที่ทำให้เกิดข้อยกเว้นคือข้อมูลเพิ่มเติมสามารถส่งผ่านเกี่ยวกับสาเหตุที่มันล้มเหลว (เว้นแต่มีคนพัฒนาMaybeErrorด้วยเขตข้อมูลที่สามารถโยนได้เมื่อเกิดข้อผิดพลาด)


2
แต่ฉันสามารถเลื่อนการจัดการข้อยกเว้นที่ตรวจสอบได้โดยประกาศว่าวิธีการของฉันมีข้อยกเว้นนี้
นักวิทยาศาสตร์ Mad

1
@ MadScientist ที่ขึ้นไปบน call stack เท่านั้นในขณะที่บางทีสามารถไปได้ทุกทิศทาง
ratchet freak

5
ฉันคิดว่าคุณไม่ควรสร้างความสับสนMaybeกับการจัดการข้อผิดพลาด มีการใช้ข้อยกเว้นเพื่อรายงานข้อผิดพลาดชนิดของตัวเลือกจะใช้เพื่อแสดงผลลัพธ์ของฟังก์ชันบางส่วน ฟังก์ชันที่ส่งคืนบางส่วนNothingไม่ใช่ข้อผิดพลาด
Giorgio

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