มีทฤษฎีของลำดับชั้นการยกเว้นหรือไม่?


18

ฉันคุ้นเคยกับภาษาการเขียนโปรแกรมหลายสิบภาษาที่มีข้อยกเว้นบางประการ แต่ฉันก็มาพบกับแนวโน้ม "พยาธิวิทยา" สองประการ

  1. ดูเหมือนจะไม่มีรูปแบบทั่วไปหรือลำดับชั้นของข้อยกเว้น ทุกภาษาจะม้วนเวอร์ชั่นของตัวเองและหากข้อยกเว้นทำให้เป็นมาตรฐานแล้วชนิดของข้อยกเว้นที่พบในมาตรฐานจะค่อนข้างโดยพลการ สตริงหรือข้อยกเว้นในการเรียกใช้ดีบักเกอร์หรือสิ่งที่เกิดขึ้นเมื่อไม่พบไฟล์ ฯลฯ )

  2. ข้อยกเว้นที่กำหนดโดยภาษานั้นไม่ค่อยได้ใช้ซ้ำโดยโปรแกรมผู้ใช้ โดยปกติจะมีข้อยกเว้นที่ได้รับความนิยมหนึ่งหรือสองรายการ (ตัวอย่างเช่น "not Implement") แม้ว่าโปรแกรมเมอร์ส่วนใหญ่จะสร้างข้อยกเว้นของตนเอง (เปรียบเทียบสิ่งนี้กับการสร้างประเภทตัวเลขใหม่หรือประเภทคอลเลกชันใหม่)

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

ยิ่งไปกว่านั้น Goolge และ Wikipedia ยังให้ความช่วยเหลือเพียงเล็กน้อยในเรื่องนี้ จนถึงตอนนี้ฉันเพิ่งพบบทความเกี่ยวกับข้อยกเว้นการทำงานที่เปิดขึ้นเป็นตอน:

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

(ทฤษฎีการทำงานของข้อยกเว้น, Mike Spivey, 1988)

แต่ฉันคิดว่าข้อยกเว้นนั้นดี ฉันไม่ต้องการแปลงโปรแกรมที่ใช้ข้อยกเว้นในทางตรงกันข้ามฉันต้องการใช้ข้อยกเว้นให้วุ่นวายน้อยลง

คำถาม:

มีทฤษฎีของข้อยกเว้นหรือไม่? ถ้าเป็นเช่นนั้นมันจะเรียกว่าอะไร? อะไรคือสิ่งสำคัญถ้าสิ่งสำคัญคือการทำงานที่สรุปพื้นฐานของมันได้หรือไม่


ข้อยกเว้นเป็นสิ่งประดิษฐ์ที่ค่อนข้างใหม่อาจจะน้อยกว่า ~ 20 ปีซึ่งเกิดจาก "longjmp" ของ C พวกเขาส่วนใหญ่เชื่อมต่อกับ OOP ดูเหมือนว่าการใช้งาน / ทฤษฎี / แนวปฏิบัติที่ดีที่สุดในอุดมคติยังอยู่ภายใต้วิวัฒนาการ java มีหนึ่งในรุ่นที่ซับซ้อนมากขึ้น มี "antipatterns" จำนวนมากที่เกี่ยวข้องกับข้อยกเว้นตามที่คุณทราบ บางส่วนนี้เกี่ยวข้องกับทฤษฎี "การคำนวณความผิดพลาด" ซึ่งดูเหมือนว่าในช่วงวัยเด็กโดยรวม
vzn

คุณสามารถพิจารณาข้อยกเว้นเซตย่อยของทฤษฎีต่อเนื่อง ดูen.wikipedia.org/wiki/Continuation
jmite

@jmite ข้อยกเว้นและการต่อเนื่องแตกต่างกันมาก ข้อยกเว้นผูกกับตัวจัดการแบบไดนามิกในขณะที่การดำเนินการต่อเนื่องจะทำแบบคงที่ โดยทั่วไปตของตัวเองไม่สามารถใช้ในการใช้ข้อยกเว้นอย่างน้อยในการปรากฏตัวของประเภทให้ดูเช่นข้อยกเว้นพิมพ์และไม่ต Can Macro-Express แต่ละอื่น ๆ
Martin Berger

"ข้อยกเว้นที่กำหนดโดยภาษานั้นไม่ค่อยได้ใช้ซ้ำโดยโปรแกรมผู้ใช้" นี่เป็นเรื่องจริง! การกำหนดข้อยกเว้นแบบกำหนดเองนั้นไม่ค่อยจำเป็น ตัวอย่างเช่น python และ stdlib กำหนดบางอย่างเช่น 160 ข้อยกเว้น โอกาสที่ข้อยกเว้นที่คุณกำลังคิดเกี่ยวกับไม่ได้กำหนดไว้มีขนาดเล็กมาก ข้อยกเว้นเหล่านี้บางส่วน (ส่วนใหญ่) ไม่เป็นที่รู้จักอย่างกว้างขวาง ตัวอย่างเช่นLookupErrorจะดีที่สุดสำหรับทุกคอนเทนเนอร์ที่กำหนดเอง แต่ฉันหลายคนไม่รู้ด้วยซ้ำว่ามีอยู่จริง
บาคุริว

1
@jmite พบเจออีกครั้งหนึ่งที่ฉันมีข้อยกเว้นก่อนหัวข้อนี้คือจากประเภทหนังสือและภาษาการเขียนโปรแกรมของ Benjamin C. Pierce ที่ที่เขากล่าวถึงข้อผิดพลาดในบริบทของการกำหนดประเภทของฟังก์ชั่น เช่นจากมุมมองของเขาข้อผิดพลาดเป็นเพียงค่าอื่นที่ส่งคืนจากฟังก์ชั่น (และร่วมกับอาร์กิวเมนต์อื่น ๆ ที่พวกเขาฟอร์มทั้งประเภทถ้าฉันได้รับอนุญาตให้พูดอย่างนั้น)
wvxvw

คำตอบ:


8

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

  • B. Randell โครงสร้างระบบสำหรับ Software Fault Tolerance
  • JB Goodenough การจัดการข้อยกเว้น: ปัญหาและสัญกรณ์ที่เสนอ
  • JB Goodenough การจัดการข้อยกเว้นอย่างเป็นระบบ
  • BG Ryder, ML Soffa, อิทธิพลต่อการออกแบบการจัดการข้อยกเว้น
  • D. Teller, A. Spiwack, T. Varoquaux, จับฉันถ้าคุณทำได้: สู่การจัดการข้อผิดพลาดประเภทปลอดภัย, ลำดับชั้น, มีน้ำหนักเบา, polymorphic และมีประสิทธิภาพใน OCaml
  • X. Leroy, F. Pessaux, การวิเคราะห์ตามประเภทของข้อยกเว้นที่ไม่ได้ตรวจสอบ
  • R. Miller, A. Tripathi, ปัญหาเกี่ยวกับการจัดการข้อยกเว้นในระบบเชิงวัตถุ
  • S. Drew, KJ Gough, J. Ledermann, ดำเนินการจัดการข้อยกเว้นค่าโสหุ้ย
  • B. Stroustrup ความปลอดภัยยกเว้น: แนวคิดและเทคนิค
  • D. Malayeri, J. Aldrich, ข้อมูลจำเพาะข้อยกเว้นเชิงปฏิบัติ
  • H. Nakano การสร้างกลไกการจับและโยนแบบแผน
  • A. Nanevski แคลคูลัสเป็นกิริยาช่วยในการจัดการข้อยกเว้น
  • P. de Groote แคลคูลัสอย่างง่ายของการจัดการข้อยกเว้น
  • H. Thielecke บนข้อยกเว้นและการสืบเนื่องในการแสดงตนของรัฐ
  • JG Riecke, H. Thielecke, พิมพ์ข้อยกเว้นและการดำเนินการต่อไม่สามารถมาโคร - แสดงถึงกันและกัน
  • M. van Dooren, E. Steegmans ผสมผสานความทนทานของข้อยกเว้นที่ตรวจสอบเข้ากับความยืดหยุ่นของข้อยกเว้นที่ไม่ได้ตรวจสอบโดยใช้การประกาศข้อยกเว้นแบบยึด
  • JA Vaughan การตีความตรรกะของข้อยกเว้นสไตล์ Java
  • S. Marlow, S. Peyton Jones, A. Moran, ข้อยกเว้นแบบอะซิงโครนัสใน Haskell
  • B. Jacobs, F. Piessens, Failboxes: การจัดการข้อยกเว้นที่ปลอดภัยอย่างน่าเชื่อถือ

ว้าวขอบคุณมาก! จะใช้เวลาสองสามเดือน (ถ้าไม่มาก) เพื่อตอบกลับด้วยการตอบกลับในเชิงบวก :) ตอนนี้ฉันฉีกขาดระหว่างหนังสือสองสามเล่มที่ไม่รู้ว่าจะเริ่มที่ไหน
wvxvw

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

@Gilles คำถามเดิมค่อนข้างชัดเจน ฉันคิดว่าสิ่งที่นับเป็นข้อยกเว้นที่เหมาะสมขึ้นอยู่กับแอปพลิเคชันเป็นส่วนใหญ่ ปัญหาทางทฤษฎีที่แท้จริงเพียงข้อยกเว้นคือการแลกเปลี่ยนระหว่าง (1) การมีเพศสัมพันธ์โมดูลที่ไม่เกี่ยวข้องผ่านข้อยกเว้น (นี่คือเหตุผลที่ไม่มีภาษาหลังจาก Java มีข้อกำหนดข้อยกเว้นบังคับ), (2) ให้ผู้ใช้โมดูลบ่งชี้สิ่งที่ชนิดของความคาดหวัง และ (3) คอมไพเลอร์ช่วยแก้ไขข้อผิดพลาด เท่าที่ฉันเห็นไม่มีวิธีแก้ปัญหาที่น่าเชื่อถือสำหรับปริศนานี้ที่ถูกค้นพบ
Martin Berger

6

ฉันไม่รู้ว่ามีทฤษฎีหรือไม่ แต่อาจมีวิทยาศาสตร์การทดลองเชิงปฏิบัติที่เกิดขึ้นใหม่

แหล่งที่ดีที่สุดที่ฉันสามารถคิดเป็นBjarne Stroustrup, การออกแบบและวิวัฒนาการของภาษา C ++, Addison-Wesley 1994 ถ้าฉันจำได้อย่างถูกต้อง (มันเป็นหนังสือที่ดีมากและผู้คนยืมมันมาจากฉันและไม่คืนมันดังนั้นฉันไม่มีสำเนาตอนนี้) มีบทหนึ่งเกี่ยวกับข้อยกเว้น คณะกรรมการ C ++ ภายใต้ Stroustrup ต้องการหลักฐานเชิงประจักษ์จำนวนมากว่าคุณลักษณะที่เสนอนั้นจำเป็นก่อนที่พวกเขาจะยินดีที่จะเพิ่มลงในคำจำกัดความภาษา หน้าวิกิพีเดียเกี่ยวกับข้อยกเว้นมีข้อความต่อไปนี้จากหนังสือที่:

ในการประชุม Palo Alto [มาตรฐาน C ++] ในเดือนพฤศจิกายน 2534 เราได้ยินบทสรุปที่ยอดเยี่ยมของข้อโต้แย้งสำหรับการเลิกความหมายซึ่งได้รับการสนับสนุนทั้งประสบการณ์ส่วนตัวและข้อมูลจาก Jim Mitchell (จาก Sun เดิมจาก Xerox PARC) จิมใช้ข้อยกเว้นในภาษาครึ่งโหลในช่วงระยะเวลา 20 ปีและเป็นผู้เสนอความหมายในการเริ่มต้นใหม่ในฐานะหนึ่งในผู้ออกแบบและผู้พัฒนาระบบซีดาร์ / เมซ่าของซีร็อกซ์ ข้อความของเขาคือการเลิกจ้างเป็นที่ต้องการมากกว่าการเริ่มต้นใหม่; นี่ไม่ใช่เรื่องของความเห็น แต่เป็นเรื่องของประสบการณ์ การเริ่มต้นใหม่มีเสน่ห์ แต่ไม่ถูกต้อง เขาสนับสนุนคำแถลงนี้ด้วยประสบการณ์จากระบบปฏิบัติการหลายระบบ ตัวอย่างสำคัญคือ Cedar / Mesa: มันถูกเขียนขึ้นโดยคนที่ชอบและใช้การเริ่มต้นใหม่ แต่หลังจากใช้งานไปสิบปี มีการเริ่มต้นใหม่เพียงครั้งเดียวที่ใช้ในระบบครึ่งล้านเส้น - และนั่นเป็นการสอบถามบริบท เนื่องจากการเริ่มต้นใหม่ไม่จำเป็นสำหรับการสอบถามบริบทเช่นนั้นพวกเขาจึงลบออกและพบว่าการเพิ่มความเร็วอย่างมีนัยสำคัญในส่วนนั้นของระบบ ในแต่ละกรณีที่มีการเริ่มต้นใหม่ทุกครั้งที่ใช้งาน - ในช่วงสิบปีที่ผ่านมากลายเป็นปัญหาและการออกแบบที่เหมาะสมกว่าได้เข้ามาแทนที่ โดยพื้นฐานแล้วการใช้การเริ่มต้นใหม่ทุกครั้งเป็นตัวแทนของความล้มเหลวในการแยกระดับของ abstraction disjoint ในแต่ละกรณีที่มีการเริ่มต้นใหม่ทุกครั้งที่ใช้งาน - ในช่วงสิบปีที่ผ่านมากลายเป็นปัญหาและการออกแบบที่เหมาะสมกว่าได้เข้ามาแทนที่ โดยพื้นฐานแล้วการใช้การเริ่มต้นใหม่ทุกครั้งเป็นตัวแทนของความล้มเหลวในการแยกระดับของ abstraction disjoint ในแต่ละกรณีที่มีการเริ่มต้นใหม่ทุกครั้งที่ใช้งาน - ในช่วงสิบปีที่ผ่านมากลายเป็นปัญหาและการออกแบบที่เหมาะสมกว่าได้เข้ามาแทนที่ โดยพื้นฐานแล้วการใช้การเริ่มต้นใหม่ทุกครั้งเป็นตัวแทนของความล้มเหลวในการแยกระดับของ abstraction disjoint

ใน C ++ การชนะที่แท้จริงคือRAIIซึ่งทำให้ง่ายต่อการจัดการการจัดสรรทรัพยากรระหว่างข้อผิดพลาด (มันไม่ได้ทำไปด้วยความต้องการthrowและtry- catchแต่มันหมายความว่าคุณไม่ต้องการfinally)

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

สิ่งอื่น ๆ ที่ผู้คนดูเหมือนจะได้เรียนรู้ในช่วงหลายปีที่ผ่านมาก็คือคุณสมบัติของข้อยกเว้นนั้นยากที่จะนำมาใช้ในภาษาอย่างถูกต้อง ดูตัวอย่างนี้: http://www.gotw.ca/publications/mill22.htmหรือนี้: http://www.gotw.ca/gotw/082.htm (และไม่ใช่แค่ C ++ โปรแกรมเมอร์ Java ยังมีข้อโต้แย้งที่ยาวเกี่ยวกับประสบการณ์ของพวกเขาด้วยการตรวจสอบกับข้อยกเว้นที่ไม่ได้ตรวจสอบ )

ประวัติความเป็นมาของข้อยกเว้นเล็กน้อย กระดาษคลาสสิกคือ: John B. Goodenough: "การจัดการข้อยกเว้น: ปัญหาและสัญกรณ์ที่เสนอ" ชุมชน ACM 18 (12): 683-696 1975 แต่ข้อยกเว้นเป็นที่รู้จักกันมาก่อนเลยว่า เมซ่ามีพวกเขาในประมาณปี 1974 และ PL / ฉันอาจมีพวกเขาด้วย Ada มีกลไกการยกเว้นก่อนปี 1980 ฉันเชื่อว่าข้อยกเว้นของ C ++ นั้นได้รับอิทธิพลมากที่สุดจากประสบการณ์ในการเขียนโปรแกรม CLU ของ Barbara Liskov จากปี 1976 Barbara Liskov: "A History of CLU" ในประวัติศาสตร์ของภาษาโปรแกรม --- II , Thomas J. Bergin, Jr. และ Richard G. Gibson, Jr. (Eds.) ได้ pp. 471-510, ACM 1996


สิ่งนี้น่าสนใจและฉันจะต้องค้นคว้าเพิ่มเติมเพื่อตอบกลับให้ดีขึ้น แต่จนถึงตอนนี้: ฉันรู้ว่ามีข้อคัดค้านที่แข็งแกร่งมากในการใช้ข้อยกเว้นใน C ++ เลยทีเดียว (อาจเป็นเรื่องเล็ก ๆ น้อย ๆ แต่เป็นแนวทางแบบเข้ารหัสของ Google ที่ใช้เพื่อห้ามการใช้ข้อยกเว้น) การตรวจสอบข้อยกเว้นของ Java นั้นเป็นการทดลองที่ไม่เหมือนใครและน่าสนใจ แต่ฟีเจอร์นี้ได้รับเครดิตที่ไม่ดีมากมายในประวัติศาสตร์ของมัน ... คนส่วนใหญ่ก็ทำการคอมไพล์อีกครั้งที่รันไทม์ (แม้ว่านี่อาจจะเกี่ยวข้องกับไวยากรณ์)
wvxvw

ฉันคุ้นเคยกับการจัดหมวดหมู่ข้อยกเว้น Common LISP ที่พวกเขาพยายาม (แม้ว่าจะประสบความสำเร็จเพียงเล็กน้อย) แบ่งพวกเขาออกตามระดับของภัยคุกคามที่พวกเขาวางโปรแกรม เช่นVSserious-condition simple-conditionตอนนี้ฉันกำลังอ่าน JL Austing ซึ่งเขาจำแนกข้อผิดพลาด (ไม่เกี่ยวข้องกับการเขียนโปรแกรม) เป็นกลุ่มตามวิธีที่ระบบล้มเหลวในการทำงาน (เช่นชิ้นส่วนที่ไม่เหมาะสมใช้กับเจตนาที่ไม่จริงใจ) ซึ่งไม่สามารถใช้ได้ทันทีกับการเขียนโปรแกรม แต่อาจเกิดขึ้นหลังจากการปรับแต่งแล้ว
wvxvw

@ หลงทางลอจิกฉัน upvoded เพราะคุณได้อธิบายว่าทำไม C ++ excpetios จึงเป็น sux และการรวมคุณสมบัติที่มีการศึกษาอาจทำลายภาษา
วาล

@wvxvw very strong objectionข้อยกเว้นใน C ++ มาจากข้อเท็จจริงสองประการ: ไม่มีสิ่งfinallyก่อสร้างและไม่มีใครใช้ข้อยกเว้น ปัญหาแรกก็ยิ่งทำให้ปัญหาที่สองแย่ลงไปอีก นั่นคือเมื่อคุณไม่มีfinallyคุณจะไม่สามารถปิดทรัพยากรเมื่อเกิดข้อยกเว้น เนื่องจากไม่มีใครใช้ข้อยกเว้นฟังก์ชั่น / API ทั้งหมดจะหลีกเลี่ยงพวกเขาคุณจะต้องลงทุนจำนวนมากในการสร้างโครงสร้างพื้นฐาน C ++ แบบดั้งเดิมทั้งหมดที่ห่อหุ้มฟังก์ชั่นทั้งหมดพร้อมกับข้อยกเว้นของคุณ แต่การขาดfinallyทำให้วิธีนี้เป็นไปไม่ได้เช่นกัน
Val

@wvxvw: ข้อกำหนดของ Google ห้ามไม่ให้มีการยกเว้นข้อยกเว้นข้ามขอบเขตของโมดูล (.so) เนื่องจากข้อยกเว้นใน C ++ ใช้ข้อมูลชนิดรันไทม์ (RTTI) และ Linux ทำงานได้ไม่ดีในการใช้การพิมพ์แบบรันไทม์ ใน Linux คุณสามารถส่งผ่านชนิดรันไทม์ระหว่างโมดูลได้อย่างน่าเชื่อถือหากคุณรวบรวมโมดูลด้วยเวอร์ชันเดียวกันของคอมไพเลอร์เดียวกันและเชื่อมโยงกับ libstdc ++ รุ่นที่เหมือนกัน จริงๆแล้วนี่คือการปฏิเสธ C ++ โดยทั่วไปโดยชุมชน Linux ไม่ใช่การปฏิเสธข้อยกเว้นโดยเฉพาะ
หลงทางลอจิก

3

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


1
ฉันคิดว่านี่ไม่เกี่ยวข้องอย่างสมบูรณ์ คำถามไม่ได้เกี่ยวกับการสร้างแบบจำลองความคิดของข้อยกเว้น แต่เกี่ยวกับการทำแผนที่กับข้อผิดพลาด - ฉันคิดว่าวิธีที่ถูกต้องในการอธิบายจากมุมมอง PLT จะเป็นทฤษฎีของลำดับชั้นข้อยกเว้น
Gilles 'หยุดความชั่วร้าย'

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