Tôi có nên đưa ra ngoại lệ của riêng mình hoặc đồng chọn ngoại lệ tương tự cho các mục đích hơi không chuẩn?


8

Đây là một câu hỏi thiết kế chung, nhưng tôi đang tập trung vào C # và .NET vì đó là những ngôn ngữ tôi đang làm việc với ngay bây giờ.

Tôi có nên tạo các lớp ngoại lệ mới, riêng của mình hoặc đồng chọn ngoại lệ khung hiện có cho các mục đích hơi khác nhau không?

Ví dụ, tôi thấy mình cần một ngoại lệ cho biết một thành viên (ví dụ, thuộc loại chẳng hạn) đã được mong đợi, nhưng không được tìm thấy trong khi đọc một hội đồng sử dụng Mono.Cecil. Thư viện lớp cơ sở định nghĩa ngoại lệ MissingMemberException, dường như giao tiếp chính xác những gì tôi muốn, nhưng mô tả cho biết:

Ngoại lệ được ném khi có một nỗ lực truy cập động một thành viên lớp không tồn tại.

Điều này không phù hợp chính xác, bởi vì tôi không tự động truy cập vào thành viên, mà là làm việc với hội đồng một cách thụ động.


Những gì bạn muốn là sử dụng lại tên nhưng không phải là loại. Có ý nghĩa cụ thể gắn liền với MissingMemberException. Chỉ cần xác định một loại mới dành riêng cho khung của bạn và mang đúng ý nghĩa.
usr

Câu trả lời:


7

Nói chung

Các trường hợp ngoại lệ phân lớp là một ý tưởng tốt để nhóm các ngoại lệ vào các gia đình hoặc nhóm mà chúng thuộc về. Nó cũng cho phép mã máy khách cơ hội xử lý các trường hợp ngoại lệ dựa trên các lỗi cụ thể hoặc nói chung hơn. Tôi thường chia cây ở đâu đó gần gốc giữa các lỗi logic và thời gian chạy (ví dụ trong C ++ std::runtime_errorso với std::logic_error).

Có thể phân biệt giữa các ngoại lệ hệ thống và ngoại lệ của ứng dụng của bạn cũng là một ý tưởng hay. Sẽ là kỳ quặc nếu mã máy khách đang theo dõi lỗi hệ thống nào đó nhưng bắt lỗi logic (thông qua lớp cơ sở) của bạn.

Cho trường hợp này và C #

C # có một hệ thống phân cấp ngoại lệ phong phú và lớn - Tôi sẽ không thử chọn một lớp cơ sở quá sâu vào nó. Theo ví dụ của bạn, có vẻ như bạn đang đưa ra một lỗi logic (hoặc ít nhất là lỗi ứng dụng), vì vậy lớp cơ sở hoặc thậm chí chỉ là ngoại lệ đó sẽ gợi ý lỗi hệ thống. Ngoại lệ chính xác có thể được tranh luận, nhưng tôi nghĩ trong trường hợp này nó không phải là một lựa chọn tốt.

Hệ thống cấp bậc

Tôi sẽ xây dựng một hệ thống phân cấp cho phép bạn phân biệt lỗi hệ thống và lỗi ứng dụng và sau đó xa hơn giữa lỗi thời gian chạy và lỗi logic. Đừng ngại sử dụng các ngoại lệ bên trong - bắt lỗi hệ thống và bọc nó trong một cái gì đó có ý nghĩa hơn với bối cảnh mà nó đang bị ném. Đừng quá nhiệt tình, tập trung vào những gì sẽ là ngoại lệ chính. Các ngoại lệ có thể có các mô tả văn bản duy nhất được liên kết với chúng - sử dụng chúng để cung cấp cho người dùng chi tiết hơn hoặc gợi ý về những việc cần làm để khắc phục vấn đề.


2
Đây là chiến lược tuyệt vời khi ngoại lệ phân lớp. Tôi không chắc chắn nếu bạn đang nói với các trường hợp ngoại lệ trong mọi trường hợp hoặc bạn chỉ đơn giản nói rằng khi bạn phân lớp thì đây là cách bạn nên làm. Liên quan đến việc bạn có nên phân lớp tôi đồng ý với câu trả lời @DanielS đã đăng.
Chuck Conway

3

Câu trả lời tất nhiên là "nó phụ thuộc", nhưng với trường hợp sử dụng của bạn, tôi sẽ nói không. Đây là lý do tại sao:

C # là một ngôn ngữ tuyệt vời - đầu tiên, tốt nhất - hướng đối tượng xung quanh. Trên thực tế, điều đó tốt đến nỗi đôi khi tôi sẽ bị bắt gặp khi cố gắng thực hiện một tầm nhìn thuần túy cuồng tín về những gì bắt đầu như một dự án đơn giản. Điều đó không xảy ra với tôi rất nhiều khi viết mã JavaScript hoặc Objective-C hoặc PHP.

Khi tôi ở trong "chế độ" này, loại tê liệt này, một trong những triệu chứng có thể là nỗi ám ảnh với việc xử lý ngoại lệ và thuốc generic và lập trình meta. Đôi khi cả ba cùng nhau. Nó có nhiều khả năng là một vấn đề khi tôi đang làm việc trên một cái gì đó mới, tương đối chưa biết, hoặc với các thông số kỹ thuật và mục tiêu kém chất lượng. Thay vì sa lầy vào các chi tiết triển khai , tôi nghĩ, tại sao lại cố gắng tạo ra thứ gì đó có thể phù hợp với hầu hết các kịch bản mà tôi dự đoán một cách hợp lý? Sau đó, khi tôi nhận được các chi tiết, nền tảng sẽ được đặt và tôi sẽ viết một loạt các phương pháp nhỏ cứng đầu, và như vậy. Có lẽ ai đó sẽ làm việc với mã UI, tôi sẽ chỉ cung cấp cho họ các dịch vụ tốt đẹp này và các hợp đồng này ...

Thật không may, điều đó vẫn chưa xảy ra với tôi. Điều có xu hướng xảy ra là tôi bắt đầu con đường này hoạt động trên "cơ sở hạ tầng" - những thứ như:

  • Viết các giao diện bộ chứa IoC của riêng tôi hoặc nói cách khác Castle.Windsor
  • Xác định cách tôi sẽ xử lý ánh xạ loại trong ứng dụng
  • Viết logic luồng điều khiển cho các lớp cơ sở trừu tượng giống Interceptors và gói các cuộc gọi đến các thành viên trừu tượng với xử lý ngoại lệ
  • Tạo các lớp cơ sở trừu tượng cho IRepository, IUnitOfWork, IDomainService, ICrossCuttingValidationvv
  • Cố gắng mô tả một mô hình đối tượng phân cấp cho một cái gì đó mà bản chất của nó phủ nhận cách tiếp cận meta như vậyIFrameworkException ( như )

Khi bạn gác máy về việc liệu mô tả của một ngoại lệ có đủ chính xác cho thị hiếu của bạn hay không, bạn thực sự đang từ chối một số tính năng quan trọng khác được triển khai. Bản chất của ngoại lệ cũng là nói - nó không phải là ngoại lệ được xử lý theo sự kiện , nó xuất hiện rõ ràng so với bất kỳ phương pháp nhập liệu nào (như UI hoặc ống dẫn hoặc một cái gì đó) và có thể có tính chất quyết định - như trong, bạn không thể dự đoán những gì người dùng sẽ nhập, nhưng bạn có thể dự đoán lắp ráp nào bạn chọn để tải hoặc không có gì.

Nhân tiện, nếu mô tả làm phiền bạn rất nhiều, bạn có thể viết một phương thức mở rộng để ghi đè lên nó trong phạm vi thích hợp không?

Vì vậy, đây thực sự chỉ là tôi loại dự án quá trừu tượng và tê liệt phân tích của riêng tôi lên bạn nhưng tôi nghĩ nó có thể phù hợp. Tôi sẽ nói rằng để ở bên an toàn, chỉ phân lớp một Exceptionkhi:

  • Bạn thực sự đã trải qua một ngoại lệ thời gian chạy mà bạn đang tìm cách xử lý nói chung
  • Ngoại lệ thời gian chạy không phải là thứ mà bạn có thể loại trừ một cách hợp lý tại thời điểm thiết kế
  • Ngoại lệ chưa được bao phủ tốt bởi số lượng lớn các Exceptionlớp con hiện có
  • Bạn thực sự có một ý tưởng trong đầu về cách bạn muốn xử lý ngoại lệ HOẶC nếu không, chỉ vì nó phức tạp đến mức bạn cần phải suy nghĩ về nó và quay lại với nó
  • Ý tưởng của bạn vượt ra ngoài việc thay đổi siêu dữ liệu, phạm vi của nó, ngoại lệ bên trong của nó, v.v. và liên quan nhiều hơn đến đối tượng hoặc sự kiện cơ bản tạo ra ngoại lệ và / hoặc phương tiện thực sự xử lý nó
  • Bạn đã viết hoặc không chịu trách nhiệm cho phần lớn các mặt phải đối mặt của những thứ như UI

Tôi đánh giá cao cách tiếp cận thực dụng của bạn. Như với tất cả mọi thứ nó phụ thuộc.
Chuck Conway

1

Theo quan điểm của tôi, ngoại lệ tùy chỉnh chỉ có ý nghĩa trong 2 trường hợp:

1) bạn đang phát triển Api

2) bạn sử dụng nó trong mã của bạn để phục hồi từ một thất bại.

Trong bất kỳ kịch bản nào khác, được xây dựng trong các trường hợp ngoại lệ là đủ.

Trong trường hợp của bạn, bạn có thể sử dụng UnlimitedArgumentException


Bạn nên mở rộng câu trả lời của mình một chút và đưa ra "Tại sao" cho mỗi điểm gạch đầu dòng. Bạn đang ở đây Tạo các ngoại lệ tùy chỉnh là một hệ thống / phân cấp khác để duy trì.
Chuck Conway
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.