Theo tôi, có một sự khác biệt giữa trả về NULL, trả về một số kết quả trống (ví dụ: chuỗi rỗng hoặc danh sách trống) và ném ngoại lệ.
Tôi thường thực hiện theo cách tiếp cận sau đây. Tôi coi một hàm hoặc phương thức f (v1, ..., vn) gọi là ứng dụng của hàm
f : S x T1 x ... x Tn -> T
Trong đó S là "trạng thái của thế giới" T1, ..., Tn là các loại tham số đầu vào và T là loại trả về.
Trước tiên tôi cố gắng xác định chức năng này. Nếu hàm là một phần (tức là có một số giá trị đầu vào mà nó không được xác định) tôi trả về NULL để báo hiệu điều này. Điều này là do tôi muốn tính toán kết thúc bình thường và cho tôi biết rằng hàm tôi đã yêu cầu không được xác định trên các đầu vào đã cho. Việc sử dụng, ví dụ, một chuỗi rỗng làm giá trị trả về là không rõ ràng vì có thể hàm được xác định trên các đầu vào và chuỗi trống là kết quả chính xác.
Tôi nghĩ rằng việc kiểm tra thêm cho một con trỏ NULL trong mã gọi là cần thiết bởi vì bạn đang áp dụng một phần chức năng và đó là nhiệm vụ của phương thức được gọi để cho bạn biết nếu hàm nếu không được xác định cho đầu vào đã cho.
Tôi thích sử dụng các ngoại lệ cho các lỗi không cho phép thực hiện tính toán (nghĩa là không thể tìm thấy bất kỳ câu trả lời nào).
Ví dụ: giả sử tôi có một Khách hàng đẳng cấp và tôi muốn thực hiện một phương thức
Customer findCustomer(String customerCode)
để tìm kiếm một khách hàng trong cơ sở dữ liệu ứng dụng theo mã của nó. Trong phương pháp này, tôi sẽ
- Trả về một đối tượng của lớp Khách hàng nếu truy vấn thành công,
- Trả về null nếu truy vấn không tìm thấy bất kỳ khách hàng nào.
- Ném một ngoại lệ nếu không thể kết nối với cơ sở dữ liệu.
Việc kiểm tra thêm cho null, vd
Customer customer = findCustomer("...");
if (customer != null && customer.getOrders() > 0)
{
...
}
là một phần của ngữ nghĩa của những gì tôi đang làm và tôi sẽ không chỉ "bỏ qua chúng" để làm cho mã được đọc tốt hơn. Tôi không nghĩ rằng đó là một cách thực hành tốt để đơn giản hóa ngữ nghĩa của vấn đề trong tay chỉ để đơn giản hóa mã.
Tất nhiên, vì việc kiểm tra null xảy ra rất thường xuyên sẽ tốt nếu ngôn ngữ hỗ trợ một số cú pháp đặc biệt cho nó.
Tôi cũng sẽ xem xét sử dụng mẫu Null Object (như được đề xuất bởi Laf) miễn là tôi có thể phân biệt đối tượng null của một lớp với tất cả các đối tượng khác.