Nếu một ngôn ngữ vốn đã hỗ trợ các ngoại lệ, thì nên ưu tiên ném ngoại lệ và khách hàng có thể bắt ngoại lệ nếu họ không muốn nó dẫn đến thất bại. Trong thực tế, các máy khách của mã của bạn mong đợi các ngoại lệ và sẽ gặp nhiều lỗi vì chúng sẽ không kiểm tra các giá trị trả về.
Có khá nhiều lợi thế để sử dụng ngoại lệ nếu bạn có sự lựa chọn.
Tin nhắn
Các ngoại lệ chứa thông báo lỗi người dùng có thể đọc được các nhà phát triển có thể sử dụng để gỡ lỗi hoặc thậm chí hiển thị cho người dùng nếu muốn. Nếu mã tiêu thụ không thể xử lý ngoại lệ, nó luôn có thể ghi nhật ký để các nhà phát triển có thể duyệt nhật ký mà không phải dừng lại ở mọi dấu vết khác để tìm ra giá trị trả về là gì và ánh xạ nó trong bảng để tìm ra đâu là giá trị ngoại lệ thực tế.
Với các giá trị trả về, không có thông tin bổ sung nào có thể dễ dàng được cung cấp. Một số ngôn ngữ sẽ hỗ trợ thực hiện các cuộc gọi phương thức để nhận thông báo lỗi cuối cùng, vì vậy mối quan tâm này đã được xóa bỏ một chút, nhưng điều đó đòi hỏi người gọi phải thực hiện thêm các cuộc gọi và đôi khi sẽ yêu cầu quyền truy cập vào một 'đối tượng đặc biệt' mang thông tin này.
Trong trường hợp có thông báo ngoại lệ, tôi cung cấp càng nhiều ngữ cảnh càng tốt, chẳng hạn như:
Không thể truy xuất chính sách tên "foo" cho "thanh" người dùng, được tham chiếu trong hồ sơ người dùng.
So sánh điều này với mã trả về -85. Bạn thích cái nào hơn?
Ngăn xếp cuộc gọi
Các ngoại lệ thường có ngăn xếp cuộc gọi chi tiết giúp mã gỡ lỗi nhanh hơn và nhanh hơn và cũng có thể được ghi lại bằng mã cuộc gọi nếu muốn. Điều này cho phép các nhà phát triển xác định chính xác vấn đề thường đến dòng chính xác và do đó rất mạnh mẽ. Một lần nữa, so sánh tệp này với tệp nhật ký với các giá trị trả về (chẳng hạn như -85, 101, 0, v.v.), bạn thích cái nào hơn?
Thất bại trong cách tiếp cận thiên vị nhanh
Nếu một phương thức được gọi ở đâu đó không thành công, nó sẽ đưa ra một ngoại lệ. Mã gọi phải loại bỏ ngoại lệ một cách rõ ràng nếu không nó sẽ thất bại. Tôi đã thấy điều này thực sự tuyệt vời bởi vì trong quá trình phát triển và thử nghiệm (và ngay cả trong sản xuất), mã bị lỗi nhanh chóng, buộc các nhà phát triển phải sửa nó. Trong trường hợp giá trị trả về, nếu kiểm tra giá trị trả về bị bỏ lỡ, lỗi sẽ âm thầm bị bỏ qua và lỗi xuất hiện ở đâu đó không mong muốn, thường có chi phí cao hơn để gỡ lỗi và sửa lỗi.
Ngoại lệ gói và Unwrapping
Các ngoại lệ có thể được bọc bên trong các ngoại lệ khác và sau đó mở ra nếu cần. Ví dụ: mã của bạn có thể ném mã ArgumentNullException
mà cuộc gọi có thể bao bọc bên trong UnableToRetrievePolicyException
vì thao tác đó đã thất bại trong mã cuộc gọi. Mặc dù người dùng có thể được hiển thị một thông báo tương tự như ví dụ tôi đã cung cấp ở trên, một số mã chẩn đoán có thể hủy bỏ ngoại lệ và thấy rằng ArgumentNullException
đã gây ra sự cố, điều đó có nghĩa đó là lỗi mã hóa trong mã của người tiêu dùng. Điều này sau đó có thể kích hoạt cảnh báo để nhà phát triển có thể sửa mã. Các kịch bản nâng cao như vậy không dễ thực hiện với các giá trị trả về.
Mã đơn giản
Điều này khó hơn một chút để giải thích, nhưng tôi đã học được thông qua mã hóa này với cả giá trị trả về cũng như ngoại lệ. Mã được viết bằng các giá trị trả về thường sẽ thực hiện cuộc gọi và sau đó có một loạt kiểm tra về giá trị trả về là gì. Trong một số trường hợp, nó sẽ thực hiện cuộc gọi đến một phương thức khác và bây giờ sẽ có một loạt kiểm tra khác cho các giá trị trả về từ phương thức đó. Với các trường hợp ngoại lệ, việc xử lý ngoại lệ đơn giản hơn nhiều trong hầu hết các trường hợp. Bạn có một khối thử / bắt / cuối cùng, với thời gian chạy cố gắng hết sức để thực thi mã trong các khối cuối cùng để dọn dẹp. Ngay cả các khối thử / bắt / cuối cùng lồng nhau cũng tương đối dễ theo dõi và duy trì hơn so với lồng nhau nếu / khác và các giá trị trả về được liên kết từ nhiều phương thức.
Phần kết luận
Nếu nền tảng bạn đang sử dụng hỗ trợ các ngoại lệ (đặc biệt là Java hoặc .NET), thì bạn chắc chắn nên cho rằng không có cách nào khác ngoại trừ ném ngoại lệ vì các nền tảng này có hướng dẫn để ném ngoại lệ và khách hàng của bạn sẽ mong đợi vì thế. Nếu tôi đang sử dụng thư viện của bạn, tôi sẽ không bận tâm kiểm tra các giá trị trả về vì tôi hy vọng các ngoại lệ sẽ bị ném, đó là cách thế giới trong các nền tảng này.
Tuy nhiên, nếu là C ++, thì sẽ khó khăn hơn một chút để xác định vì một cơ sở mã lớn đã tồn tại với mã trả về và một số lượng lớn các nhà phát triển được điều chỉnh để trả về các giá trị trái ngược với ngoại lệ (ví dụ: Windows đầy rẫy với HRESULT) . Hơn nữa, trong nhiều ứng dụng, nó cũng có thể là một vấn đề về hiệu năng (hoặc ít nhất là được coi là có).
try
/catch
tồn tại cho. Ngoài ra, bạn có thể đặttry
/catch
nhiều hơn nữa lên ngăn xếp ở một vị trí phù hợp hơn để xử lý nó (cho phép phân tách mối quan tâm lớn hơn).