Tại sao "khúc gỗ và ném" được coi là một mô hình phản đối? [đóng cửa]


85

Câu hỏi này được khơi mào bởi một cuộc thảo luận xung quanh bài viết này , nơi tôi không nhận được bất kỳ câu trả lời hay ho nào.

Tại sao nên ghi lại ngoại lệ của bạn và sau đó ném lại nó (tất nhiên là giữ nguyên dấu vết ngăn xếp ban đầu) là một ý tưởng tồi nếu bạn không thể xử lý nó theo cách khác?


Hãy thử tìm kiếm câu trả lời trên softwareengineering.stackexchange.com
chharvey

Câu trả lời:


121

Tôi cho rằng câu trả lời phần lớn là vì tại sao bạn lại bắt được nó nếu bạn không thể xử lý nó? Tại sao không để bất kỳ ai có thể xử lý nó (hoặc bất cứ ai không có lựa chọn nào khác ngoài việc xử lý nó) ghi lại nó, nếu họ cảm thấy rằng nó xứng đáng với log?

Nếu bạn bắt được nó và ghi lại nó rồi ném lại, thì không có cách nào để mã ngược dòng biết rằng bạn đã ghi lại ngoại lệ và do đó, cùng một ngoại lệ có thể được ghi lại hai lần. Hoặc tệ hơn, nếu tất cả mã ngược dòng tuân theo cùng một mẫu này, thì ngoại lệ có thể được ghi lại một số lần tùy ý, một lần cho mỗi cấp trong mã quyết định bắt nó, ghi lại nó, rồi ném nó lại.

Ngoài ra, một số người có thể tranh luận rằng vì các trường hợp ngoại lệ ném và bắt là các hoạt động tương đối tốn kém, tất cả việc bắt và ném lại này không giúp ích cho hiệu suất thời gian chạy của bạn. Nó cũng không giúp mã của bạn về mặt ngắn gọn hoặc khả năng bảo trì.


cho xây dựng thêm, xem các ý kiến về câu trả lời của Jeff
Manu

8
Một lý do để ghi nhật ký và ghi lại một đoạn trích, người nên thu hẹp lý do và ghi lại một thông báo cụ thể.
Mike Argyriou

11
Trả lời: Có thể thông tin gỡ lỗi hữu ích có sẵn tại thời điểm hiện tại trong đống rằng sẽ không có sẵn tại một điểm nào đó trong stack trace
rtconner

Nắm bắt và đánh lại đôi khi hữu ích nếu ngoại lệ mới hữu ích hơn với nhiều thông tin hơn hoặc cụ thể hơn.
borjab

Để sử dụng những gì @rtconner đã nhận xét: trong mã không đồng bộ, có thể người bắt không có ngữ cảnh sẵn có cho người ném.
Nir Alfasi

53

Đăng nhập và ném là một mô hình tốt vì thực thể bắt và ném lại ngoại lệ có lý do để tin rằng nó chứa thông tin sẽ không được ghi vào ngăn xếp cuộc gọi - ít nhất là không theo cách mong muốn nhất. Một vài lý do khiến điều này có thể xảy ra:

  1. Ngoại lệ có thể bị bắt và phát triển lại ở ranh giới lớp ứng dụng và có thể chứa thông tin đặc quyền. Sẽ là không tốt nếu lớp cơ sở dữ liệu cho phép một ngoại lệ, ví dụ: "Cố gắng thêm khóa trùng lặp 'fnord' vào trường 'người dùng'" để đến lớp ứng dụng bên ngoài (có thể hiển thị nó cho người dùng), nhưng nó có thể hữu ích cho các phần bên trong của cơ sở dữ liệu để ném một ngoại lệ như vậy và giao diện ứng dụng để bắt nó, ghi lại nó một cách an toàn và tạo lại một ngoại lệ ít mô tả hơn.
  2. Ngoại lệ có thể là một ngoại lệ mà lớp bên ngoài có thể sẽ xử lý mà không cần ghi nhật ký, nhưng lớp bên trong có thể biết điều gì đó mà lớp bên ngoài không có, điều này cho thấy rằng việc ghi nhật ký có thể hữu ích. Như một ví dụ đơn giản, một lớp ứng dụng giữa có thể được lập trình để thử kết nối với một máy chủ và nếu điều đó không hiệu quả, hãy thử một lớp khác. Làm ngập nhật ký của ứng dụng với thông báo 'kết nối không thành công' trong khi máy chủ ngừng hoạt động để bảo trì có thể không hữu ích, đặc biệt là vì - từ quan điểm của ứng dụng, mọi thứ đều hoạt động tốt. Có thể hữu ích khi chuyển tiếp thông tin về lỗi kết nối đến tài nguyên ghi nhật ký được liên kết với máy chủ, sau đó có thể lọc nhật ký để tạo báo cáo về thời điểm máy chủ hoạt động lên xuống, trái ngược với nhật ký của mọi lần kết nối đơn lẻ .

4
# 1 thực sự là một trường hợp sử dụng chung hợp lý, tuy nhiên OP đã hỏi rõ ràng về việc "ném lại nó (tất nhiên là giữ nguyên dấu vết ngăn xếp ban đầu)", vì vậy # 1 không phải là câu trả lời đúng.
Geoffrey Zheng

@GeoffreyZheng: Điều đó sẽ phụ thuộc vào việc ghi nhật ký theo dõi ngăn xếp ban đầu một cách an toàn có được tính là "bảo tồn" hay không.
supercat

2
Về # 1: việc hiển thị nội dung ngoại lệ (như hiển thị e.getMessage()/ stacktrace trên giao diện người dùng, cũng như gửi nó dưới dạng phản hồi REST) ​​nên được coi là lỗ hổng bảo mật, vì ngoại lệ thời gian chạy có thể chứa bất kỳ loại thông tin nhạy cảm nào. Liên quan đến # 2: bạn có thể ném lại ngoại lệ thêm tất cả thông tin bạn muốn khách hàng biết (+ nguyên nhân gốc rễ), không cần đăng nhập bất kỳ thứ gì.
Nikita Bosik

@NikitaBosik: Cho dù có nên để lộ ra phía máy khách các trường hợp ngoại lệ hay không, các ứng dụng làm như vậy đủ phổ biến đến mức nguyên tắc 'bảo mật chuyên sâu' sẽ đề xuất rằng các thông báo ngoại lệ nên được loại bỏ thông tin nhạy cảm. Hơn nữa, nếu lớp ngoài không mong đợi loại bỏ một loại ngoại lệ cụ thể mà không ghi nhật ký nó cũng như chuyển tiếp thông tin đến một thực thể bên ngoài có thể quan tâm, thì việc lớp giữa thêm thông tin mà lớp ngoài sẽ bỏ qua sẽ không giúp ích gì. bất cứ thứ gì.
supercat

20

Tôi đoán lý do đơn giản nhất là bạn thường có một trình xử lý cấp cao nhất làm việc này cho bạn, vì vậy không cần phải làm ô nhiễm mã với xử lý ngoại lệ này.

Lập luận về mối quan tâm xuyên suốt về cơ bản là việc xử lý các lỗi không liên quan đến bạn sẽ rất lãng phí thời gian. Tốt hơn nhiều là để lỗi nổi lên ngăn xếp cuộc gọi cho đến khi tìm thấy một trình xử lý thích hợp.

Theo tôi, thời điểm duy nhất bạn nên bắt một ngoại lệ là khi bạn có thể làm điều gì đó hữu ích với kết quả. Bắt đơn giản để ghi nhật ký không hữu ích, vì bạn có thể tập trung công việc đó lên cao hơn nữa.


1
Tôi đồng ý rằng bạn nên có một trình xử lý cấp cao nhất làm việc này cho bạn. Nhưng theo ý kiến ​​của tôi, trình xử lý cấp cao nhất NÊN là "đăng nhập và ném" -ing. Vì vậy, tranh luận là xung quanh ĐIỂM NÀO để "đăng nhập và ném", không ướt hơn hay không để làm điều đó ở tất cả?!?
Manu

@Manu, tôi đoán vấn đề là nếu nó là một trình xử lý duy nhất (tập trung), thì tốt thôi. Nếu bạn đang trùng lặp mã, điều đó không ổn. Tôi không nghĩ rằng có nhiều hơn thế nữa!
Jeff Foster,

5
@Manu - Trình xử lý cấp cao nhất sẽ ném cho gì trong trường hợp đó? Đối với tôi, dường như nếu có sẵn thứ gì đó để nó ném tới, thì nó không thực sự là người xử lý cấp cao nhất. Và bạn chắc chắn không muốn đưa lại một ngoại lệ cho chính môi trường thời gian chạy. Điều đó sẽ làm cho hầu hết các ứng dụng ngừng hoạt động.
aroth

1
@aroth: Tôi hiểu rồi, những gì bạn đang nói là "ghi nhật ký và xử lý" (nếu bạn là người xử lý cấp cao nhất) hoặc "không ghi nhật ký và ném (hoặc xử lý theo cách khác)" nếu bạn không phải. Cảm ơn vì đã chỉ ra điều đó.
Manu

9

Nhật ký và ném IMO rõ ràng là vi phạm Nguyên tắc Ít bất ngờ.

Nếu ngoại lệ được xử lý đúng cách thêm vào ngăn xếp cuộc gọi, nó có thể không có giá trị cho một mục nhập nhật ký lỗi. Và sau đó thật khó hiểu khi tìm thấy một mục nhật ký lỗi.


Điều gì về các bản ghi không lỗi?
Su Zhang

6
@SuZhang Tôi không hiểu lắm câu hỏi của bạn. Nếu không có lỗi, không có gì để ném. Tất nhiên bạn có thể và nên viết nhật ký không lỗi.
Bastian Voigt
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.