Lỗi lập trình của các trường hợp ngoại lệ.


9

Tôi hiện đang cố gắng cải thiện việc sử dụng các ngoại lệ của mình và tìm thấy sự khác biệt quan trọng giữa các ngoại lệ biểu thị các lỗi lập trình (ví dụ: ai đó đã chuyển null thành đối số hoặc gọi một phương thức trên một đối tượng sau khi nó được xử lý) và các phương thức đó biểu thị sự thất bại trong hoạt động không phải là lỗi của người gọi (ví dụ: ngoại lệ I / O).

Hai loại ngoại lệ này nên được đối xử khác nhau như thế nào? Bạn có nghĩ rằng các ngoại lệ lỗi cần phải được ghi lại rõ ràng, hoặc nó có đủ để ghi lại các điều kiện tiên quyết liên quan không? Và bạn có thể bỏ tài liệu về một điều kiện tiên quyết hoặc ngoại lệ lỗi nếu nó rõ ràng (ví dụ: ObjectDisposedExceptionkhi gọi một phương thức trên một đối tượng bị loại bỏ)


Tôi thường phân biệt một loại ngoại lệ khác: ngoại lệ kinh doanh. Chúng đề cập đến các điều kiện lỗi mà người dùng quan tâm đến các chi tiết của. Tôi thường làm cho những ngoại lệ được kiểm tra.
beluchin

Câu trả lời:


2

Tôi nghĩ rằng bạn đang đi đúng hướng. Không ném, bắt, cũng không ghi lại tất cả các ngoại lệ có khả năng ném có ý nghĩa nhiều. Đôi khi tính nghiêm ngặt của sản phẩm đòi hỏi mức độ cao hơn về việc làm và tài liệu ngoại lệ (ví dụ: các khía cạnh quan trọng về an toàn nhất định của hệ thống).

Chiến lược phòng thủ hơn, sử dụng các khái niệm hợp đồng để xác định các điều kiện tiên quyết (và hậu điều kiện) đối với những người gọi đặc biệt (ví dụ: bất cứ điều gì giống với một thành viên công cộng hoặc được bảo vệ) thường sẽ hiệu quả và linh hoạt hơn. Điều này không chỉ áp dụng cho việc thực hiện, mà còn cho tài liệu. Nếu các nhà phát triển biết những gì được mong đợi, họ có nhiều khả năng tuân theo các quy tắc và ít có khả năng bị nhầm lẫn hoặc sử dụng sai mã bạn đã viết.

Một số điều phổ biến cần được ghi lại bao gồm trường hợp tham số null. Thường có một hậu quả cho việc sử dụng của họ dẫn đến kết quả là điều mà thông thường không được mong đợi, nhưng được cho phép và sử dụng vì nhiều lý do, đôi khi vì sự linh hoạt. Là người tiêu dùng của một thành viên có các tham số cho phép null hoặc các giá trị phi lý, đặc biệt khác (như thời gian âm hoặc số lượng âm), tôi hy vọng sẽ thấy chúng được xác định và giải thích.

Đối với các tham số không null, với tư cách là người tiêu dùng của một thành viên công cộng hoặc được bảo vệ, tôi muốn biết rằng null không được phép. Tôi muốn biết phạm vi giá trị hợp lệ trong ngữ cảnh cụ thể là gì. Tôi muốn biết hậu quả của việc sử dụng các giá trị nằm ngoài phạm vi bình thường, nhưng nếu không thì hợp lệ trong một ngữ cảnh gọi khác (ví dụ: giá trị của loại này thường hợp lệ cho bất kỳ hoạt động nào, nhưng không phải ở đây - như tham số boolean không 'T mong đợi sai là một giá trị hợp lệ.

Đối với nền tảng, hoặc các giao diện nổi tiếng khác, tôi không nghĩ bạn phải đi đến cực đoan trong việc ghi lại nó. Tuy nhiên, vì bạn có cơ hội là nhà phát triển để thay đổi việc triển khai từ bất kỳ hướng dẫn nền tảng nào, hãy lưu ý cách thực hiện theo hướng dẫn đó có thể có giá trị.

Cụ thể đối với IDis Dùng, việc triển khai giao diện này thường cung cấp một phương pháp thay thế được ưa thích hơn quy trình xử lý rõ ràng. Trong những trường hợp này, hãy làm nổi bật phương pháp ưa thích và lưu ý rằng việc xử lý rõ ràng không được ưu tiên.


Tôi hiểu sự cần thiết phải ghi lại giá trị nào được cho phép, nhưng nếu bạn thấy một hàm performReadCommand(ICommand cmd, int replySizeBytes)- bạn có nghĩ rằng null sẽ được chấp nhận cho cmd hoặc giá trị âm cho replySizeBytes không? Tài liệu IMO sẽ chỉ cần thiết nếu những giá trị đó thực sự được cho phép và có lẽ bạn nên giải quyết xem 0 có hợp lệ cho replySizeBytes hay không.
Medo42

Cả hai đều có thể "hợp lệ" tùy thuộc vào việc thực hiện. Bạn hoặc tôi, và thậm chí tất cả mọi người ở đây sẽ không mong đợi các giá trị null hoặc âm là phù hợp với chữ ký đó, nhưng chúng có thể. Hãy xem xét một môi trường trong đó trình đọc là một quá trình chặn, liên tục và khi cmd là null có thể có nghĩa là không thay đổi lệnh được sử dụng bởi trình đọc và tiến hành đọc tiếp theo bằng lệnh ưu tiên. Lý tưởng nhất là trong trường hợp đó, một chữ ký phương thức phù hợp hơn sử dụng cmd làm tham số sẽ được xác định và sử dụng, nhưng có thể không.
JustinC

2

Dưới đây là những suy nghĩ của riêng tôi. Lưu ý rằng tôi không quá chắc chắn đây là cách tốt nhất để đi, đó là lý do tại sao tôi đã tạo ra câu hỏi này ngay từ đầu.

Theo như tôi hiểu, thật vô nghĩa khi một người gọi ngay lập tức thực sự xử lý các trường hợp ngoại lệ lỗi lập trình, thay vào đó anh ta nên đảm bảo rằng các điều kiện tiên quyết được đáp ứng. Chỉ các trình xử lý ngoại lệ "bên ngoài" tại các ranh giới nhiệm vụ mới bắt được chúng, vì vậy chúng có thể giữ cho hệ thống chạy nếu một tác vụ thất bại.

Để đảm bảo rằng mã máy khách có thể bắt được các ngoại lệ "thất bại" một cách sạch sẽ mà không bắt lỗi ngoại lệ do lỗi, tôi tạo các lớp ngoại lệ của riêng mình cho tất cả các ngoại lệ thất bại bây giờ và ghi lại chúng theo các phương thức ném chúng. Tôi sẽ làm cho họ kiểm tra ngoại lệ trong Java.

Cho đến gần đây, tôi đã cố gắng ghi lại tất cả các trường hợp ngoại lệ mà một phương thức có thể đưa ra, nhưng đôi khi nó tạo ra một danh sách vô tình cần được ghi lại trong mọi phương thức trong chuỗi cuộc gọi cho đến khi bạn có thể thấy rằng lỗi sẽ không xảy ra. Thay vào đó, bây giờ tôi ghi lại các điều kiện tiên quyết trong các mô tả tóm tắt / tham số và thậm chí không đề cập đến những gì xảy ra nếu chúng không được đáp ứng. Ý tưởng là mọi người không nên cố gắng nắm bắt những ngoại lệ này một cách rõ ràng, vì vậy không cần phải ghi lại các loại của họ.

Để ghi lại các điều kiện tiên quyết, việc nêu rõ ràng chỉ tạo ra sự lộn xộn không cần thiết - nếu truyền null cho một phương thức không có ý nghĩa rõ ràng, người gọi phải mong đợi một ngoại lệ nếu anh ta chuyển null dù thế nào, ngay cả khi điều đó không được ghi lại. Điều tương tự cũng đúng với trường hợp của ObjectDisposedException - giao diện này được sử dụng rộng rãi đến mức ai đó gọi Dispose sẽ nhận thức được trách nhiệm để đảm bảo không ai tiếp tục sử dụng đối tượng.


1

Một nguyên tắc hợp lý:

  1. Bắt bất kỳ ngoại lệ bạn có thể sửa chữa.
  2. Nắm bắt, nhận xét và suy nghĩ lại bất kỳ ngoại lệ nào bạn không thể sửa nhưng có thể nói điều gì đó hữu ích.
  3. Đừng bắt bất kỳ ngoại lệ nào bạn không thể xử lý hoặc chẩn đoán tốt hơn so với xử lý mặc định.

Bạn có thể muốn có một trình xử lý ngoại lệ không gây tử vong ở cấp cao nhất để bẫy mọi thứ không thể xử lý bên dưới để cố gắng giữ cho ứng dụng của bạn không bị đổ, nhưng điều đó sẽ phụ thuộc mạnh vào ứng dụng cụ thể của bạn. Ví dụ, các ứng dụng iOS thích bẫy càng nhiều càng tốt; một ứng dụng dòng lệnh có thể hoàn toàn ổn nếu nó bẫy hầu như không có ngoại lệ nào cả.


0

Ngay cả Java cũng không "tài liệu" tất cả các ngoại lệ. Mặc dù yêu cầu rằng mọi throwngoại lệ n được đề cập trong một throwsmệnh đề, bất kỳ dòng mã nào cũng có thể ném RuntimeExceptionmà không cần khai báo nó trong chữ ký phương thức.


Điều này đi ngược lại với lời khuyên phổ biến - cụ thể, Java hiệu quả, tái bản lần 2, Mục 62 là "Tài liệu tất cả các ngoại lệ được ném bởi mỗi phương thức". Trên thực tế, Bloch thừa nhận rằng các trường hợp ngoại lệ không được kiểm tra thường là do lỗi lập trình, nhưng chúng cũng phải được ghi lại cẩn thận, vì đó là "cách tốt nhất" để ghi lại các điều kiện tiên quyết của phương pháp. Tôi không chắc chắn mặc dù tôi đồng ý. Nếu tôi ghi lại các lần thực hiện, tôi biến chúng thành một phần của hợp đồng giao diện và có thể phải thêm mã để làm cho chúng giữ nguyên nếu việc triển khai của tôi thay đổi.
Medo42

1
Đối với mỗi chuyên gia, có một chuyên gia phản tác dụng. Bruce Eckel, tác giả của cuốn Thinking khá nổi tiếng ở Java , đã từng ở trong trại ngoại lệ được kiểm tra và đã thay đổi bên. Có một cuộc thảo luận thú vị giữa Eckels và Anders Hejlsberg , người tạo ra C #, không kiểm tra ngoại lệ.
Ross Patterson

0

Cách tiêu chuẩn để làm điều đó là với cách tiếp cận java. Lỗi lập trình nên được kiểm tra ngoại lệ và không nên bắt để đảm bảo thất bại nhanh. Lỗi hợp đồng được kiểm tra ngoại lệ và nên được xử lý thích hợp bởi khách hàng.


2
Bạn có xem (ví dụ) một NULL được tính toán (hoặc giá trị lỗi) là lỗi lập trình hoặc lỗi hợp đồng không? Tôi đi với sự phân biệt của bạn, nhưng ranh giới không quá rõ ràng :)
Andrew

Nếu null được tính từ một đối số được truyền vào (chẳng hạn như đối số null hoặc không hợp lệ), đó là lỗi hợp đồng. Nếu null được tính toán do một đoạn mã xấu, đó là lỗi lập trình. Nếu null được cho là được tính toán thì đó không phải là lỗi. Tôi thực sự không thấy bất kỳ sự mơ hồ nào trong ví dụ này.
J.Ashworth
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.