Lớp dịch vụ có nên bắt tất cả các ngoại lệ dao và bọc chúng làm ngoại lệ dịch vụ không?


23

Tôi có ba lớp ứng dụng web Spring: dao, dịch vụ và bộ điều khiển. Một bộ điều khiển không bao giờ gọi trực tiếp dao, nó thực hiện thông qua lớp dịch vụ. Ngay bây giờ, hầu hết thời gian nếu có ngoại lệ dao (thời gian chạy) không được xử lý, nó sẽ bị bắt bởi một tệp hiển thị thông báo lỗi cho người dùng cuối. Lớp dịch vụ có nên bắt tất cả các ngoại lệ dao và bọc chúng làm ngoại lệ dịch vụ không?

try {
   daoInstance.someDaoMethod();
} catch(DataAccessException dae) {
   throw new ServiceException("message", dae);
}

Giả sử ServiceException cũng là thời gian chạy và nó cũng không được xử lý. Có sự khác biệt nào khi chỉ ném DataAccessException thay vì ServiceException không? Tôi chỉ nghĩ rằng lớp trình bày không nên biết về ngoại lệ truy cập dữ liệu. Nhưng tôi không thấy điểm bắt các ngoại lệ không thể phục hồi chỉ để bọc chúng.

Câu trả lời:


18

Tôi nghĩ một yếu tố quan trọng là khách hàng dịch vụ của bạn là ai.

Nếu lớp dịch vụ của bạn chỉ là ranh giới kiến ​​trúc giữa các lớp trong dự án của riêng bạn và máy khách dịch vụ nằm trong cùng một lĩnh vực tin cậy, thì bạn có thể thư giãn mọi thứ và để các trường hợp ngoại lệ không được kiểm tra bong bóng ra khỏi lớp điều khiển hoặc máy khách dịch vụ.

Tuy nhiên, đối với mã phải đối mặt công khai; dịch vụ được sử dụng bởi bên thứ ba hoặc khách hàng, tôi nghĩ sẽ tốt hơn nếu bao bọc mọi trường hợp ngoại lệ không được kiểm soát với ngoại lệ theo định hướng dịch vụ, chủ yếu cho các vấn đề bảo mật, thứ hai là khớp nối lỏng lẻo và trừu tượng sạch.

Một ngoại lệ của lớp dữ liệu không bao giờ nên, trực tiếp làm cho nó trở thành người dùng cuối của một ứng dụng web . Nó có khả năng chứa thông tin nội bộ về lược đồ của bạn, truy vấn của bạn, thông tin số dòng, tên biến hoặc tên hàm, v.v ... Ngoại lệ của người dùng cuối có thể được vệ sinh trong một cài đặt an toàn.

Một khách hàng dịch vụ bên ngoài không quan tâm đến chi tiết triển khai của bạn và dù sao cũng không thể xử lý các trường hợp ngoại lệ không được kiểm tra, vì chúng là các vấn đề về lỗi hoặc môi trường. Trong các ứng dụng bảo mật, lỗi cơ sở dữ liệu đơn giản là không đủ an toàn để lan truyền, OracleException - ORA-01234 - ...có thể là bảng thứ 3 được chèn vào. Khách hàng nên được phép đối phó với bất kỳ trường hợp ngoại lệ được kiểm tra / dự kiến ​​nào có thể xử lý và coi mọi thứ khác là báo cáo lỗi tiềm ẩn. Hợp đồng dịch vụ của bạn nên là một sự trừu tượng hóa nguyên tắc, nhất quán, giao dịch. Nếu nó không thể làm bất cứ điều gì về ngoại lệ, thì điều hữu ích duy nhất còn lại là cung cấp cho bạn một báo cáo lỗi. Bạn đã có khả năng đăng nhập ngoại lệ, vậy tại sao lại tạo gánh nặng cho người dùng cuối của bạn với các chi tiết? Ứng dụng của bạn có thể được theo dõi để bạn đã biết về các ngoại lệ không được kiểm tra trước khi người dùng báo cáo chúng.

Không bao giờ ổn khi ăn ngoại lệ, tôi cũng không phải là người thích kiểm tra ngoại lệ, nhưng tôi thích có một kế hoạch phù hợp với bản chất của sản phẩm tổng thể.


13

Không, bạn không nên bọc ngoại lệ DAO trong ứng dụng web

Đó là rất nhiều tiếng ồn trong mã cho lợi ích bằng không. Các ngoại lệ DAO là các ngoại lệ không được kiểm tra vì một lý do chính đáng. Mã ứng dụng không thể làm bất cứ điều gì hữu ích để phục hồi từ ngoại lệ DAO. Vấn đề thực sự nằm ở đây:

... nó sẽ bị bắt bởi một JSP hiển thị thông báo lỗi cho người dùng cuối.

Khắc phục sự cố này ở một nơi thay vì bỏ qua toàn bộ cơ sở mã.

Bạn kiểm soát cách một ngoại lệ chưa được hiển thị cho người dùng. Các trường hợp ngoại lệ không được lưu ý là do lỗi ứng dụng hoặc lỗi trong hệ thống cơ bản. Không có lý do để cung cấp cho người dùng bất kỳ thông tin nào về lý do yêu cầu của anh ta không thể được phục vụ. Người dùng không thể làm gì. Tất cả bạn nên làm là phục vụ một trang lỗi thân thiện.

Lưu ý: nếu bạn thấy mình viết rất nhiều mã tẻ nhạt, ví dụ, tạo ra một loạt các khối bắt đơn giản chỉ cần bọc và ném lại, hầu như luôn luôn có một giải pháp tốt hơn.


Cảm ơn câu trả lời của bạn. Và vâng, jsp hiển thị một thông báo tùy chỉnh: "Rất tiếc, đã xảy ra lỗi". Nó không hiển thị bất kỳ thông tin nào về ngoại lệ
Oscar

7

Lý do chính người ta sẽ sử dụng gói ngoại lệ là để ngăn chặn mã trong lớp nghiệp vụ phải biết về mọi ngoại lệ có thể có trong hệ thống . Có hai lý do chính cho việc này:

  • Tính nhất quán: ngoại lệ được khai báo tổng hợp về phía trên cùng của ngăn xếp cuộc gọi. Nếu bạn không bao gồm các ngoại lệ, nhưng thay vào đó, vượt qua chúng bằng cách khai báo các phương thức của bạn để ném chúng, bạn có thể kết thúc bằng các phương thức cấp cao nhất khai báo nhiều ngoại lệ khác nhau. Việc khai báo tất cả các ngoại lệ này trong mỗi phương thức sao lưu ngăn xếp cuộc gọi trở nên tẻ nhạt.

  • Đóng gói: Bạn có thể không muốn các thành phần cấp cao nhất của mình biết bất cứ điều gì về các thành phần cấp thấp nhất, cũng như các ngoại lệ mà chúng đưa ra. Ví dụ, mục đích của các giao diện và triển khai DAO là để trừu tượng hóa các chi tiết truy cập dữ liệu khỏi phần còn lại của ứng dụng. Bây giờ, nếu các phương thức DAO của bạn ném SQLException thì mã sử dụng DAO sẽ phải bắt chúng. Điều gì xảy ra nếu bạn thay đổi thành một triển khai đọc dữ liệu từ một dịch vụ web thay vì từ cơ sở dữ liệu? Sau đó, các phương thức DAO của bạn sẽ phải ném cả RemoteException và SQLException. Và, nếu bạn có một DAO đọc dữ liệu từ một tệp, bạn cũng sẽ cần phải ném IOException. Đó là ba trường hợp ngoại lệ khác nhau, mỗi trường hợp bị ràng buộc với việc thực hiện DAO của riêng họ.

Vì vậy, trong ngắn hạn, câu trả lời là có!


3
Việc triển khai JPA (ví dụ Hibernate) đưa ra các ngoại lệ không được kiểm soát. Họ không phải khai báo hay bắt.
kevin cline
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.