Có một lý thuyết về thứ bậc ngoại lệ?


18

Tôi quen thuộc với hàng tá ngôn ngữ lập trình có ngoại lệ theo một cách nào đó, nhưng tôi đã chứng kiến ​​hai xu hướng "bệnh hoạn".

  1. Dường như không có một mô hình hoặc hệ thống phân cấp ngoại lệ chung. Về cơ bản, mọi ngôn ngữ đều có phiên bản riêng và nếu các ngoại lệ biến nó thành tiêu chuẩn, thì các loại ngoại lệ mà người ta tìm thấy trong tiêu chuẩn sẽ khá độc đoán (chủ yếu là các ngoại lệ được triển khai trong khi tạo các công cụ ngôn ngữ, chẳng hạn như đọc mã nguồn từ chuỗi hoặc một ngoại lệ để gọi trình gỡ lỗi hoặc chuỗi xảy ra khi không thể tìm thấy tệp, v.v.)

  2. Các ngoại lệ được xác định bởi ngôn ngữ rất hiếm khi được sử dụng lại bởi các chương trình người dùng. Thường sẽ có một hoặc hai ngoại lệ phổ biến (ví dụ "không triển khai"). Mặc dù hầu hết các lập trình viên sẽ tạo ra ngoại lệ của riêng họ. (So ​​sánh điều này với, ví dụ, tạo các loại số mới hoặc các loại bộ sưu tập mới).

Điều này có vẻ như là một thiếu sót khủng khiếp đối với tôi. Làm thế nào mà không ai biết những loại lỗi sẽ cần thiết trong các chương trình người dùng? Tôi đã hy vọng sẽ có một loại phân cấp tốt đẹp, tương tự như kiểu số, bộ sưu tập, hệ thống đối tượng, v.v.

Tệ hơn nữa, Goolge và Wikipedia cung cấp rất ít trợ giúp về chủ đề này. Cho đến nay tôi chỉ tìm thấy một bài báo về ngoại lệ chức năng mở ra trong một đoạn:

Bài viết này lập luận rằng lập trình chức năng lười biếng không chỉ làm cho cơ chế xử lý ngoại lệ tích hợp trở nên không cần thiết, mà còn cung cấp một công cụ mạnh mẽ để phát triển và chuyển đổi các chương trình sử dụng ngoại lệ

(Một lý thuyết chức năng của ngoại lệ, Mike Spivey, 1988)

Nhưng tôi nghĩ rằng ngoại lệ là tốt. Tôi không muốn chuyển đổi các chương trình sử dụng ngoại lệ, ngược lại, tôi muốn làm cho việc sử dụng các ngoại lệ ít hỗn loạn hơn.

Câu hỏi:

Có một lý thuyết về ngoại lệ? Nếu vậy, những gì nó được gọi là? Nếu có, nền tảng hoạt động phác thảo cơ sở của nó là gì?


trường hợp ngoại lệ là một phát minh khá mới, có thể ít hơn ~ 20yr cũ, phát sinh phần nào từ "longjmp" của C. chúng hầu hết được kết nối với OOP. có vẻ như một cách sử dụng / lý thuyết / thực hành tốt nhất vẫn đang được tiến hóa. java có một trong những mô hình phức tạp hơn. có nhiều "phản mẫu" liên quan đến ngoại lệ như bạn lưu ý. một số trong số này được kết nối với lý thuyết về "tính toán chịu lỗi", có vẻ như phần nào còn ở giai đoạn sơ khai.
vzn

Bạn có thể coi ngoại lệ là một tập hợp con của lý thuyết tiếp tục. Xem en.wikipedia.org/wiki/Contininating
jmite

@jmite Ngoại lệ và tiếp tục rất khác nhau. Các ngoại lệ liên kết động với trình xử lý của chúng, trong khi các phần tiếp theo thực hiện một cách tĩnh. Nói chung, các phần tiếp theo của riêng chúng không thể được sử dụng để thực hiện các ngoại lệ, ít nhất là với sự hiện diện của các loại, xem ví dụ: Các trường hợp ngoại lệ được nhập và Tiếp tục không thể Macro-Express lẫn nhau .
Martin Berger

"Các ngoại lệ được xác định bởi ngôn ngữ rất hiếm khi được các chương trình người dùng sử dụng lại." Đúng đấy! Xác định các ngoại lệ tùy chỉnh là rất hiếm khi cần thiết. Ví dụ python và stdlib của nó định nghĩa một cái gì đó như 160 ngoại lệ. Cơ hội mà ngoại lệ bạn đang nghĩ đến không được xác định là rất nhỏ. Một số (hầu hết?) Của những ngoại lệ này không được biết rộng rãi. Ví dụ, điều LookupErrornày hoàn toàn tốt cho mọi container tùy chỉnh, nhưng tôi thậm chí nhiều người không biết nó tồn tại.
Bakuriu

1
@jmite Một lần nữa tôi gặp phải ngoại lệ trước chủ đề này là từ các loại sách và ngôn ngữ lập trình của Benjamin C. Pierce. Trong đó anh ta đề cập đến các lỗi trong bối cảnh xác định một loại hàm. Tức là từ quan điểm của anh ấy, lỗi chỉ là một giá trị khác được trả về từ các hàm (và cùng với đối số khác, chúng tạo thành một kiểu hoàn chỉnh, nếu tôi được phép nói như vậy).
wvxvw

Câu trả lời:


8

Có một số lượng lớn các ấn phẩm về các trường hợp ngoại lệ, với khá nhiều nghiên cứu lý thuyết. Dưới đây là một danh sách không có cấu trúc và xa danh sách đầy đủ với một số ví dụ. Xin lỗi, tôi không có thời gian để trả lời tập trung hơn.

  • B. Randell, Cấu trúc hệ thống cho dung sai lỗi phần mềm.
  • JB Goodenough. Xử lý ngoại lệ: Các vấn đề và ký hiệu đề xuất.
  • JB Goodenough. Cấu trúc xử lý ngoại lệ.
  • BG Ryder, ML Soffa, Ảnh hưởng đến việc thiết kế xử lý ngoại lệ.
  • D. Teller, A. Spiwack, T. Varoquaux, Hãy bắt tôi nếu bạn có thể: Hướng tới quản lý lỗi an toàn, phân cấp, nhẹ, đa hình và hiệu quả trong OCaml.
  • X. Leroy, F. Pessaux, Phân tích dựa trên loại ngoại lệ chưa được phát hiện.
  • R. Miller, A. Tripathi, Các vấn đề với Xử lý ngoại lệ trong các hệ thống hướng đối tượng.
  • S. Drew, KJ Gough, J. Ledermann, Thực hiện Xử lý ngoại lệ trên không.
  • B. Stroustrup, An toàn ngoại lệ: Khái niệm và kỹ thuật.
  • D. Malayeri, J. Aldrich, Thông số kỹ thuật ngoại lệ thực tế.
  • H. Nakano, Một hình thức xây dựng của cơ chế bắt và ném.
  • A. Nanevski, Một tính toán phương thức để xử lý ngoại lệ.
  • P. de Groote, Một phép tính đơn giản của Xử lý ngoại lệ.
  • H. Thielecke, về các trường hợp ngoại lệ và liên tục trong sự hiện diện của nhà nước.
  • JG Riecke, H. Thielecke, Nhập ngoại lệ và liên tục không thể macro-Express lẫn nhau.
  • M. van Dooren, E. Steegmans, Kết hợp tính mạnh mẽ của các ngoại lệ được kiểm tra với tính linh hoạt của các ngoại lệ không được kiểm tra bằng cách sử dụng Tuyên bố ngoại lệ neo.
  • JA Vaughan, Một cách giải thích hợp lý về các ngoại lệ theo kiểu Java.
  • S. Marlow, S. Peyton Jones, A. Moran, Ngoại lệ không đồng bộ ở Haskell.
  • B. Jacobs, F. Piessens, Failboxes: Có thể xử lý ngoại lệ an toàn.

Wow, cảm ơn rất nhiều! Tôi sẽ mất vài tháng (nếu không nhiều hơn) để trở lại với câu trả lời tích cực :) Bây giờ tôi bị giằng xé giữa vài cuốn sách không biết bắt đầu từ đâu!
wvxvw

2
Rất nhiều trong số các bài viết này là về việc thực hiện hoặc mô hình hóa các ngoại lệ trong các ngôn ngữ lập trình, chứ không phải làm thế nào để thiết kế một hệ thống phân cấp ngoại lệ. Bạn có thể cắt danh sách xuống các giấy tờ liên quan?
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Câu hỏi ban đầu hơi không rõ ràng. Tôi nghĩ rằng những gì được coi là ngoại lệ thích hợp phụ thuộc chủ yếu vào ứng dụng. Vấn đề lý thuyết thực sự duy nhất với các ngoại lệ là sự đánh đổi giữa (1) các mô-đun không liên quan đến khớp nối thông qua các ngoại lệ (đây là lý do tại sao không có ngôn ngữ nào sau khi Java có các đặc tả ngoại lệ bắt buộc), (2) cung cấp cho người dùng mô-đun một số chỉ ra loại lỗi nào và (3) trình biên dịch giúp xử lý lỗi. Theo như tôi có thể thấy, chưa có giải pháp thực sự thuyết phục nào cho câu hỏi hóc búa này.
Martin Berger

6

Tôi không biết có hay không có một lý thuyết, nhưng có thể có một khoa học thực nghiệm mới nổi.

Nguồn tốt nhất tôi có thể nghĩ đến là Bjarne Stroustrup, Thiết kế và tiến hóa của C ++, Addison-Wesley, 1994 . Nếu tôi nhớ chính xác (đó là một cuốn sách rất hay và mọi người cứ mượn nó từ tôi và không trả lại, vì vậy tôi không có một bản sao vào lúc này) có một chương về các trường hợp ngoại lệ. Ủy ban C ++ thuộc Stroustrup yêu cầu rất nhiều bằng chứng thực nghiệm rằng một tính năng được đề xuất là cần thiết trước khi họ sẵn sàng thêm nó vào định nghĩa ngôn ngữ. Các trang Wikipedia về trường hợp ngoại lệ có trích dẫn sau đây từ cuốn sách đó:

Tại cuộc họp Palo Alto [tiêu chuẩn hóa C ++] vào tháng 11 năm 1991, chúng tôi đã nghe một bản tóm tắt tuyệt vời về các lý lẽ cho ngữ nghĩa chấm dứt được hỗ trợ với cả kinh nghiệm cá nhân và dữ liệu từ Jim Mitchell (từ Sun, trước đây từ Xerox PARC). Jim đã sử dụng xử lý ngoại lệ trong nửa tá ngôn ngữ trong khoảng thời gian 20 năm và là người đầu tiên đề xuất ngữ nghĩa nối lại với tư cách là một trong những nhà thiết kế và thực hiện chính của hệ thống Cedar / Mesa của Xerox. Thông điệp của ông là chấm dứt được ưu tiên hơn nối lại; đây không phải là vấn đề quan điểm mà là vấn đề nhiều năm kinh nghiệm. Tiếp tục là quyến rũ, nhưng không hợp lệ. Ông ủng hộ tuyên bố này với kinh nghiệm từ một số hệ điều hành. Ví dụ chính là Cedar / Mesa: Nó được viết bởi những người thích và sử dụng nối lại, nhưng sau mười năm sử dụng, chỉ có một lần sử dụng nối lại trong hệ thống nửa triệu - và đó là một cuộc điều tra bối cảnh. Bởi vì việc nối lại thực sự không cần thiết cho một cuộc điều tra bối cảnh như vậy, họ đã loại bỏ nó và tìm thấy sự gia tăng tốc độ đáng kể trong phần đó của hệ thống. Trong mọi trường hợp sử dụng lại, nó đã được sử dụng - trong mười năm - trở thành một vấn đề và một thiết kế phù hợp hơn đã thay thế nó. Về cơ bản, mỗi lần sử dụng nối lại đã thể hiện sự thất bại trong việc tách rời các mức độ trừu tượng riêng biệt. Trong mọi trường hợp sử dụng lại, nó đã được sử dụng - trong mười năm - trở thành một vấn đề và một thiết kế phù hợp hơn đã thay thế nó. Về cơ bản, mỗi lần sử dụng nối lại đã thể hiện sự thất bại trong việc tách rời các mức độ trừu tượng riêng biệt. Trong mọi trường hợp sử dụng lại, nó đã được sử dụng - trong mười năm - trở thành một vấn đề và một thiết kế phù hợp hơn đã thay thế nó. Về cơ bản, mỗi lần sử dụng nối lại đã thể hiện sự thất bại trong việc tách rời các mức độ trừu tượng riêng biệt.

Trong C ++, phần thắng thực sự là RAII , giúp xử lý việc phân bổ tài nguyên dễ dàng hơn trong các lỗi. (Nó không làm mất đi nhu cầu throwtry- catchnhưng điều đó có nghĩa là bạn không cần finally.)

Tôi nghĩ rằng điều thuyết phục họ mà họ cần ngoại lệ là các thùng chứa chung: người viết container không biết gì về các loại lỗi mà các đối tượng chứa có thể cần trả về (ít hơn nhiều cách xử lý chúng), nhưng mã đã chèn các đối tượng đó vào container phải biết điều gì đó về giao diện của các đối tượng đó. Nhưng vì chúng ta không biết gì về loại lỗi mà các đối tượng có thể gây ra, chúng ta không thể tiêu chuẩn hóa các loại ngoại lệ. (Tương ứng: nếu chúng ta có thể tiêu chuẩn hóa các loại ngoại lệ thì chúng ta sẽ không cần ngoại lệ.)

Một điều khác mà mọi người dường như đã học được trong nhiều năm qua là các thông số kỹ thuật ngoại lệ khó có thể đưa vào một ngôn ngữ chính xác. Xem ví dụ này: http://www.gotw.ca/publications/mill22.htm hoặc này: http://www.gotw.ca/gotw/082.htm . (Và không chỉ C ++, các lập trình viên Java cũng có những tranh luận dài dòng về trải nghiệm của họ với các ngoại lệ được kiểm tra so với không được kiểm tra .)

Một chút về lịch sử của ngoại lệ. Bài viết kinh điển là: John B. Goodenough: "Xử lý ngoại lệ: các vấn đề và ký hiệu được đề xuất," Cộng đồng . ACM 18 (12): 683-696, 1975. Nhưng các trường hợp ngoại lệ đã được biết trước đó. Mesa có chúng vào khoảng năm 1974 và PL / tôi cũng có thể có chúng. Ada đã có một cơ chế ngoại lệ trước năm 1980. Tôi tin rằng các ngoại lệ của C ++ bị ảnh hưởng nhiều nhất bởi trải nghiệm với ngôn ngữ lập trình CLU của Barbara Liskov từ khoảng năm 1976. Barbara Liskov: "Lịch sử của CLU", trong Lịch sử ngôn ngữ lập trình --- II , Thomas J. Bergin, Jr. và Richard G. Gibson, Jr. (biên soạn). trang 471-510, ACM, 1996 .


Điều này thật thú vị và tôi sẽ phải nghiên cứu thêm để trả lời tốt hơn. Nhưng cho đến nay: tôi biết có một sự phản đối rất mạnh mẽ đối với việc sử dụng các ngoại lệ trong C ++ từ trước đến nay (có lẽ là giai thoại, nhưng các công ước mã hóa của Google được sử dụng để cấm sử dụng các ngoại lệ). Các ngoại lệ được kiểm tra của Java chắc chắn là một thử nghiệm độc đáo và thú vị, nhưng tính năng này đã kiếm được rất nhiều tín dụng xấu trong suốt lịch sử của nó ... hầu hết mọi người chỉ đơn giản là nghĩ lại chúng trong thời gian chạy (mặc dù điều này có thể chỉ liên quan đến cú pháp).
wvxvw

Tôi quen thuộc hơn với phân loại ngoại lệ Common Lisp, nơi họ đã cố gắng (mặc dù có ít thành công) chia chúng theo mức độ đe dọa mà họ đặt ra cho chương trình. ví dụ serious-conditionvs simple-condition. Bây giờ tôi cũng đang đọc JL Austing, nơi anh ấy phân loại các lỗi (không liên quan đến lập trình) thành các nhóm dựa trên cách hệ thống không thực hiện nhiệm vụ (ví dụ: các phần không phù hợp được sử dụng so với ý định không chính đáng). Điều này không được áp dụng ngay lập tức cho lập trình, nhưng có thể là sau một số tinh chỉnh.
wvxvw

@Wandering Logic Tôi đã tăng cường bởi vì bạn đã giải thích lý do tại sao các đoạn trích C ++ là sux và việc bao gồm các tính năng có giáo dục có thể phá hủy ngôn ngữ.
Val

@wvxvw Việc very strong objectionchống lại các ngoại lệ trong C ++ xuất phát từ hai sự thật: không có finallycấu trúc và không ai khác sử dụng ngoại lệ. Vấn đề thứ nhất cũng làm trầm trọng thêm vấn đề thứ hai. Đó là, khi bạn không có finally, bạn không thể đóng tài nguyên khi có ngoại lệ. Vì không ai sử dụng ngoại lệ, tất cả các hàm / API đều tránh chúng, bạn phải đầu tư rất nhiều để xây dựng lại toàn bộ cơ sở hạ tầng C ++ truyền thống bao gồm tất cả các chức năng với các ngoại lệ của bạn để bắt đầu nhận được lợi ích từ mã của chúng. Nhưng thiếu finallylàm cho cách tiếp cận này cũng không thể.
Val

@wvxvw: Các quy ước của Google cấm ném ngoại lệ qua các ranh giới mô-đun (.so). Điều này là do các ngoại lệ trong C ++ sử dụng thông tin loại thời gian chạy (RTTI) và Linux đã không làm tốt công việc thực hiện gõ thời gian chạy. Trong Linux, bạn chỉ có thể chuyển các loại thời gian chạy một cách đáng tin cậy giữa các mô-đun nếu bạn biên dịch các mô-đun có cùng phiên bản của cùng một trình biên dịch và được liên kết với phiên bản libstdc ++ giống hệt nhau. Thực sự đây là một sự từ chối C ++ nói chung bởi cộng đồng Linux, không phải là từ chối các trường hợp ngoại lệ cụ thể.
Logic lang thang

3

Hãy để tôi chỉ ra rằng các ngoại lệ là một trường hợp có hiệu lực tính toán . Các hiệu ứng tính toán khác là trạng thái đột biến, I / O, không xác định, tiếp tục và nhiều thứ khác. Vì vậy, câu hỏi của bạn có thể được hỏi một cách tổng quát hơn: làm thế nào để chúng ta hình thành hệ thống phân cấp các hiệu ứng tính toán, cách chúng ta sắp xếp chúng và tại sao chúng ta có những cái chúng ta có, chứ không phải những cái khác, v.v.


1
Tôi nghĩ rằng điều này là hoàn toàn không liên quan. Câu hỏi không phải là về việc mô hình hóa khái niệm ngoại lệ, mà là về việc ánh xạ nó thành lỗi - tôi nghĩ rằng cách đúng để mô tả nó theo quan điểm PLT sẽ là một lý thuyết về phân cấp ngoại lệ.
Gilles 'SO- ngừng trở nên xấu xa'

Hmm, bạn nói đúng. Tôi đã sửa câu trả lời để chỉ ra điều này, nhưng tôi nghĩ không cần phải xóa nó. Bạn nghĩ sao?
Andrej Bauer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.