Mức độ chi tiết của ngoại lệ


9

Tôi đã gặp phải một cuộc tranh luận giữa một vài người bạn và tôi. Họ thích những ngoại lệ chung như ClientErrorExceptionServerErrorExceptionvới chi tiết là các trường hợp ngoại lệ, trong khi tôi thích làm cho mọi thứ cụ thể hơn. Ví dụ: tôi có thể có một số trường hợp ngoại lệ như:

  • BadRequestException
  • AuthenticationFailureException
  • ProductNotFoundException

Mỗi cái được xây dựng dựa trên mã lỗi được trả về từ API.

Theo các Ưu điểm của Ngoại lệ, điều này có vẻ như là thành ngữ đối với Java. Tuy nhiên, ý kiến ​​của bạn bè tôi không hẳn là hiếm.

Có một cách ưa thích nào về khả năng đọc mã và khả năng sử dụng API, hay nó thực sự chỉ được ưu tiên?


Trang bạn liên kết có thể là câu trả lời dứt khoát nhất mà chúng tôi có thể nhận được. Bạn đang hỏi ý kiến, thực sự. Tôi có thể trả lời với kinh nghiệm và ý kiến ​​của tôi là gì, nhưng đó không phải là một câu trả lời khách quan.
marstato

@marstato thật công bằng. Tôi đoán tôi đang tìm kiếm sự biện minh trong vị trí của mình. Tôi thà giữ những gì mọi người mong đợi trong các thư viện tôi viết, thay vì làm theo hướng dẫn nếu điều đó có nghĩa là nó giúp công cụ của tôi dễ sử dụng hơn, bạn biết không?

Tôi hoàn toàn đồng ý. Tôi có các lớp ngoại lệ của tôi chi tiết, quá. Ngoài ra, bạn có thể định nghĩa abstractvà khái quát các lớp ngoại lệ bằng các phương thức getter và sau đó làm cho các lớp chi tiết mở rộng các lớp chung. Ví dụ AuthenticationFaliureException extends ClientErrorException. Bằng cách này, mọi người dùng có thể chọn cách họ muốn đối phó với các ngoại lệ. Nó làm việc nhiều hơn, rõ ràng. Tuy nhiên, khi viết một ứng dụng (thay vì thư viện), đó là một tình huống khác IMHO. Trong trường hợp đó, tôi sẽ không làm cho các ngoại lệ chi tiết hơn bạn cần chúng, vì đơn giản vì lợi ích.
marstato

@marstato đó thực sự là cách tôi thực hiện nó bây giờ. Tôi rất vui vì bạn đồng ý. Tôi sẽ để câu hỏi mở qua đêm, nhưng vui lòng hợp nhất câu hỏi đó thành một bài đăng để tôi ít nhất có thể kiểm tra bạn

Câu trả lời:


15

Sự khác biệt chính giữa việc có nhiều lớp ngoại lệ khác nhau và chỉ có một vài lớp, với thông tin chi tiết hơn trong văn bản lỗi (ví dụ), là nhiều lớp ngoại lệ khác nhau cho phép mã gọi phản ứng khác nhau với các loại lỗi khác nhau, trong khi có chỉ có một vài lớp giúp dễ dàng xử lý tất cả các loại ngoại lệ một cách thống nhất.

Đây thường là một sự đánh đổi. Nó có thể được giảm thiểu ở một mức độ nào đó bằng cách sử dụng tính kế thừa (một lớp ngoại lệ cơ sở chung cho những người gọi muốn bắt và ghi nhật ký mọi thứ một cách chung chung và xuất phát ngoại lệ từ các lớp cơ sở đó cho những người gọi cần phản ứng khác nhau), nhưng thậm chí điều đó có thể tạo ra một rất nhiều sự phức tạp không cần thiết nếu bạn không cẩn thận và tuân thủ nguyên tắc YAGNI. Vì vậy, câu hỏi hướng dẫn nên ở đây:

  • Bạn có thực sự mong đợi người gọi mã của bạn phản ứng khác nhau, với luồng điều khiển khác nhau, với các loại lỗi khác nhau không?

Không có giải pháp một kích cỡ phù hợp cho tất cả, không có "cách thực hành tốt nhất" nào mà bạn có thể áp dụng ở mọi nơi. Câu trả lời cho câu hỏi này phụ thuộc rất nhiều vào loại phần mềm hoặc thành phần bạn đang thiết kế:

  • một số ứng dụng, nơi bạn hoặc nhóm có toàn bộ cơ sở mã dưới sự kiểm soát của bạn?

  • hoặc một số thành phần có thể tái sử dụng cho bên thứ ba, nơi bạn không biết tất cả những người gọi tiềm năng?

  • một ứng dụng máy chủ chạy lâu, trong đó các loại lỗi khác nhau không nên phá vỡ toàn bộ hệ thống ngay lập tức và có thể yêu cầu các loại giảm thiểu lỗi khác nhau?

  • một quy trình ứng dụng tồn tại trong thời gian ngắn, trong trường hợp có lỗi để hiển thị thông báo lỗi cho người dùng và sau đó khởi động lại quy trình?

Vì vậy, bạn càng biết nhiều về những người gọi tiềm năng của thành phần của mình, bạn càng có thể quyết định tốt hơn về mức độ chi tiết chính xác cho các ngoại lệ của mình.


3
"Bạn có thực sự mong đợi người gọi mã của bạn phản ứng khác nhau, với luồng điều khiển khác nhau, với các loại lỗi khác nhau không?" đây là một câu hỏi tuyệt vời để hỏi Cảm ơn bạn, tôi sẽ nhớ điều này.

Đây là một câu trả lời tốt, tôi nghĩ rằng tôi chỉ nhấn mạnh hơn nữa sự cần thiết phải để ứng dụng khách điều khiển thiết kế ném ngoại lệ. Ngay cả những khái quát mà bạn có thể nghĩ là hợp lý để xây dựng theo hệ thống phân cấp ngoại lệ cũng có thể không phù hợp với cách mà ứng dụng khách của bạn (nếu không phải là chính bạn viết nó) có thể chọn để khái quát một trình xử lý. Nếu bạn có nhiều ứng dụng khách với các nhu cầu khác nhau, thì tất nhiên sẽ tùy thuộc vào bạn để cân bằng chúng.
Magicduncan

1

Câu trả lời phụ thuộc vào mức độ báo cáo lỗi mà chúng ta đang nói đến.

Nói chung, tôi đồng ý với bạn bè của bạn, bạn không nên làm cho họ chi tiết hơn mức cần thiết để truyền đạt nguyên nhân của vấn đề.

Nếu có một ngoại lệ phổ biến, nổi tiếng để tham chiếu null (NullReferenceException), bạn không nên tạo MyObjectIsNullException của riêng bạn. Điều đó sẽ chỉ thêm một lớp nhầm lẫn cho trình thông dịch con người, một điều bổ sung để tìm hiểu mà không làm rõ bất cứ điều gì.

Chỉ khi ngoại lệ của bạn đặc biệt đến mức không có một nguyên nhân được xác định trước bao gồm nguyên nhân gốc thì bạn mới nên tạo ra nguyên nhân của riêng mình.

Tuy nhiên, bạn không phải dừng lại ở đó. Lỗi phổ biến có thể xảy ra ở một trong các thành phần của bạn và bạn có thể muốn chuyển tải có vấn đề trong thành phần của mình . Vì vậy, không chỉ những gì đã đi sai mà còn ở đâu. Sau đó, nó sẽ thích hợp để bọc ngoại lệ đầu tiên trong MyComponentException. Điều đó sẽ cung cấp cho bạn tốt nhất của cả hai thế giới.

Đầu tiên, nó sẽ rõ ràng thành phần của bạn gặp rắc rối. Trên một đòn bẩy thấp hơn, nguyên nhân cụ thể sẽ nằm trong ngoại lệ bên trong.


Điều đó công bằng. Vì vậy, bạn đề nghị không phát minh ra một ngoại lệ mới khi một cái tốt đã tồn tại?

@rec Có, vì mọi người đều đã biết những cái được xác định trước. Đó là những gì họ đang ở đó cho.
Martin Maat
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.