Đề xuất một mẫu thiết kế / cách tiếp cận để phơi bày / dung nạp / phục hồi từ các lỗi hệ thống, Xử lý ngoại lệ (ví dụ: trong Java, C ++, Perl, PHP)


13

Bạn có thể đề xuất một mẫu / phương pháp thiết kế để phơi bày / dung nạp / phục hồi từ các lỗi hệ thống, xử lý ngoại lệ (Java, C ++, Perl, PHP) không?

Một số lỗi cần phải được báo cáo.

Một số lỗi có thể được xử lý nội bộ (bằng cách thử lại hoặc không quan trọng (có thể bỏ qua).

Làm thế nào để bạn cấu trúc mã để bắt chúng?

Nhưng tất cả các lỗi cần phải được đăng nhập.

Những thực hành tốt nhất là gì?

Và để mô phỏng chúng để có thể kiểm tra đầy đủ các thành phần bị ảnh hưởng bởi chúng?

Câu hỏi cụ thể về ngôn ngữ phi lập trình chung áp dụng cho một số ngôn ngữ lập trình hiện đại nhưng sẽ hoan nghênh các ví dụ minh họa về các mẫu, cách tiếp cận và triết lý trong Java, C ++, PHP và Perl.

(Ngoài ra yêu cầu trong stackoverflow: /programming/7432596/recommend-a-design-pattern-approach-to-exposing-tolerating-recovering-from-system nhưng tôi nghĩ rằng nó nên được hỏi về lập trình quá vì Tôi nghĩ rằng Q & A lập trình viên bao gồm các vấn đề về phần mềm / lập trình rộng hơn trong khi stackoverflow liên quan nhiều hơn đến việc triển khai kỹ thuật IMHO).


2
Đối với tôi câu hỏi của bạn dường như quá chung chung và kết thúc mở để được trả lời một cách hiệu quả. Cố gắng hạn chế nó trong một số trường hợp cụ thể hơn và cả các loại / môi trường ứng dụng cụ thể (ví dụ: ứng dụng / máy chủ GUI / ...).
Péter Török


@ Péter Török, mikera cung cấp một câu trả lời tốt, có khả năng chấp nhận chúng.
trị liệu

Câu trả lời:


16

Fail fast là một cách tiếp cận thiết kế tuyệt vời và có lẽ nó có thể được tính là một mẫu: http://en.wikipedia.org/wiki/Fail-fast

Tôi cũng đã tìm thấy một số nguyên tắc hữu ích:

  • Xem xét các ngoại lệ như một phần của giao diện cho từng chức năng / mô-đun - tức là ghi lại chúng và khi thích hợp / nếu ngôn ngữ của bạn hỗ trợ thì hãy sử dụng các ngoại lệ được kiểm tra.
  • Không bao giờ làm thất bại một thất bại - nếu thất bại, đừng cố gắng tiếp tục với một số nỗ lực để "giả định" cách tiến hành. Ví dụ, xử lý đặc biệt cho các trường hợp null thường là mùi mã đối với tôi: nếu phương thức của bạn cần một giá trị khác null, thì nó sẽ ném ra một ngoại lệ ngay lập tức nếu nó gặp null (hoặc là NullPulumException hoặc lý tưởng hơn là IllegalArgumentException).
  • Viết các bài kiểm tra đơn vị cho các trường hợp đặc biệt cũng như các trường hợp thông thường - đôi khi các bài kiểm tra như vậy có thể khó cài đặt nhưng nó đáng giá khi bạn muốn chắc chắn rằng hệ thống của bạn mạnh mẽ khi gặp sự cố
  • Đăng nhập tại điểm bắt lỗi và xử lý (giả sử lỗi đã đủ nghiêm trọng để ghi lại). Lý do cho điều này là vì nó ngụ ý rằng bạn đã hiểu nguyên nhân và có cách tiếp cận để xử lý lỗi, vì vậy bạn có thể làm cho thông điệp tường trình có ý nghĩa .....
  • Chỉ sử dụng ngoại lệ cho các điều kiện / thất bại thực sự bất ngờ. Nếu chức năng của bạn "thất bại" theo cách thực sự được mong đợi (ví dụ: bỏ phiếu để xem có thêm đầu vào nào không và không tìm thấy) thì nó sẽ trả về phản hồi bình thường ("không có đầu vào khả dụng"), không ném ngoại lệ
  • Thất bại một cách duyên dáng (tín dụng cho Steven Lowe!) - dọn dẹp trước khi chấm dứt nếu có thể, thường là bằng cách tháo gỡ các thay đổi, khôi phục giao dịch hoặc giải phóng tài nguyên trong một tuyên bố "cuối cùng" hoặc tương đương. Việc dọn dẹp lý tưởng nên xảy ra ở cùng cấp độ mà các tài nguyên được cam kết vì mục đích rõ ràng và thống nhất logic.
  • Nếu bạn phải thất bại, thất bại lớn - một ngoại lệ mà không một phần nào trong mã của bạn có thể xử lý (nghĩa là đã bị xâm phạm đến cấp cao nhất mà không bị bắt + xử lý) sẽ gây ra lỗi ngay lập tức, to và rõ ràng khiến bạn chú ý đến nó. Tôi thường tạm dừng chương trình hoặc tác vụ và viết báo cáo ngoại lệ đầy đủ cho System.out.

1
cũng thất bại một cách duyên dáng - dọn dẹp trước khi chấm dứt nếu có thể
Steven A. Lowe

+1 @mikera cho điểm rõ ràng về những gì cần xem xét. Có khả năng được chấp nhận câu trả lời, tôi sẽ để ngỏ lâu hơn một chút để người khác đóng góp.
trị liệu

+1 @Steve A. Lowe - dành cho thiết kế lấy người dùng làm trung tâm. ví dụ như lưu tệp, không để các tệp tạm thời nói dối. Xem câu hỏi của tôi về "vệ sinh dữ liệu" là một chủ đề liên quan trong danh sách câu hỏi của tôi.
trị liệu

5

Đã làm việc với các ngoại lệ trong Java và .NET VÀ sau khi đọc rất nhiều bài viết về cách thức / thời điểm / lý do bắt ngoại lệ, cuối cùng tôi đã đưa ra các bước sau mà tôi trải qua trong đầu mỗi khi tôi thấy một ngoại lệ tiềm ẩn xảy ra hoặc ngoại lệ tôi phải nắm bắt (Java) ... ngay cả khi điều đó không bao giờ xảy ra (thở dài ...). Và nó dường như đang hoạt động, ít nhất là đối với tôi:

  1. Có điều gì hữu ích tôi có thể làm với ngoại lệ đó, (ngoại trừ đăng nhập) không? Nếu câu trả lời là có, hãy viết mã giải pháp và nếu cách giải quyết có thể đưa ra ngoại lệ, hãy chuyển đến 2:
  2. Bao bọc ngoại lệ xung quanh một ngoại lệ thời gian chạy, ném nó, đi đến 3.
  3. Trong lớp cấp cao hơn nơi giao dịch cơ sở dữ liệu / quy trình có thể được bắt đầu, bắt ngoại lệ, khôi phục giao dịch, lấy lại ngoại lệ.
  4. Ở lớp cấp cao nhất (có thể là giao dịch đã được thực hiện), hãy ghi lại ngoại lệ bằng cách sử dụng khung ghi nhật ký như slf4j ( ví dụ như kết hợp với log4j ) hoặc log4net . Nếu có thể, hãy gửi email trực tiếp ngoại lệ đến danh sách phân phối bao gồm các nhà phát triển ứng dụng.
  5. Nếu có GUI, hiển thị thông báo lỗi cho biết theo cách thân thiện nhất với người dùng, nguyên nhân gây ra sự cố; không hiển thị ngoại lệ / stacktrace, người dùng không quan tâm và không cần biết đó là NullPulumException.

Tôi cũng nên thêm bước 0 , trong đó tôi cố tình ném cái mà tôi gọi là ngoại lệ "doanh nghiệp" (một ngoại lệ mới mà tôi tạo bằng cách mở rộng lớp "Ngoại lệ") khi một số xử lý phức tạp không thể được thực thi do lỗi dữ liệu, NHƯNG được biết là xảy ra vì chúng đã được xác định là trường hợp ngoại lệ trong quá trình phân tích.

Ngoại trừ phần đăng nhập, tôi hoàn toàn đồng ý với các điểm được viết bởi "mikera"; Tôi sẽ chỉ thêm rằng ngoại lệ nên được ghi lại một lần duy nhất.

Ngoài ra, các bước tôi liệt kê có thể khác nếu những gì bạn đang viết là API / Framework . Ở đó, ném các ngoại lệ được thiết kế tốt là bắt buộc để giúp các nhà phát triển hiểu sai lầm của họ.

Đối với việc kiểm tra các trường hợp ngoại lệ, sử dụng các đối tượng giả, bạn sẽ có thể kiểm tra gần như mọi thứ, có thể là ngoại lệ hay không, miễn là các lớp của bạn tôn trọng "một lớp để làm một việc". Cá nhân tôi cũng đảm bảo đánh dấu các phương thức quan trọng nhất nhưng ẩn là "được bảo vệ" thay vì "riêng tư" để tôi có thể kiểm tra chúng mà không gặp quá nhiều khó khăn. Ngoài ra, việc kiểm tra các ngoại lệ rất đơn giản, chỉ cần kích thích ngoại lệ và "mong đợi" một ngoại lệ xảy ra bằng cách bắt nó. Nếu bạn không có ngoại lệ, thì bạn có lỗi trường hợp kiểm tra đơn vị.


+1 @Jalayn cho log4j đề cập như một cách tiếp cận, đây là những gì tôi sử dụng để nó củng cố nó để biết người khác cũng như vậy.
trị liệu

0

Xây dựng các đối tượng của bạn đúng cách, đừng lo lắng về các yếu tố bên ngoài. Nếu bạn chọn tận dụng các ngoại lệ, sau đó làm cho các đối tượng của bạn ném ngoại lệ nếu chúng thất bại ở một cái gì đó.

Khi tất cả các đối tượng của bạn đang hoạt động chính xác, sẽ khá dễ dàng để đưa ra một hệ thống phân cấp trách nhiệm xử lý lỗi rõ ràng trong thiết kế của bạn.

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.