2010-10-17 24 views
5

Gần đây tôi đã đi qua mô hình thiết kế đối tượng Null và các đồng nghiệp của tôi nói rằng nó có thể được sử dụng để làm đi với các kiểm tra con trỏ null được gặp trong suốt mã.Mô hình đối tượng đơn giản để tránh kiểm tra Null?

ví dụ: giả sử lớp DAO trả về thông tin về Khách hàng (trong đối tượng giá trị được gọi là CustomerVO). Lớp chính của tôi là nghĩa vụ phải trích xuất firstName và emailId và gửi email cho khách hàng.

... 
CustomerVO custVO = CustomerDAO.getCustomer(customerID); 
if(custVO != null) { // imp, otherwise we may get null ptr exception in next line 
    sendEmail(custVO.getFirstName(), custVO.getEmailID()); 
} 
... 

Đây là ví dụ rất đơn giản, nhưng việc kiểm tra rỗng có thể nhanh chóng lan truyền khắp mã của bạn dựa trên độ phức tạp của các đối tượng giá trị.

Tôi có hai vấn đề với kiểm tra null, - họ có xu hướng làm cho mã khó đọc và khó đọc - nhà phát triển có kinh nghiệm thấp hơn đặt kiểm tra không cần thiết khi thực tế họ phải ném ngoại lệ. ví dụ: ở trên mã, nó sẽ là tốt hơn để ném ngoại lệ từ getCustomer() chính nó bởi vì nếu nó không thể tìm thấy thông tin khách hàng cho CustID đã cho, nó chỉ ra CustID không hợp lệ.

okay, quay lại mẫu đối tượng rỗng, chúng tôi có thể sử dụng đối tượng CustomerVO 'null' để ẩn kiểm tra không?

CustomerVO { 
    String firstName = ""; 
    String emailID = ""; 
} 

Không có ý nghĩa. bạn nghĩ sao?

Và những điều bạn làm theo để giảm thiểu kiểm tra không có trong ứng dụng của bạn là gì.

Trả lời

2

Trong trường hợp này, đối tượng rỗng có thể không phù hợp vì mặc định có thể ảnh hưởng đến việc ẩn nội dung thực tế là ngoại lệ. Nếu bạn thấy mình phải kiểm tra xem liệu bạn có an toàn không để thực hiện một số hoạt động khác thì mẫu null không mua cho bạn thứ gì.

Như bạn đã nói nhiều nhà phát triển mới dành nhiều thời gian cố gắng bảo vệ mã của họ khỏi các tình huống ngoại lệ tồi tệ hơn sau đó là một chương trình tạm dừng.

3

Trong khi mẫu đối tượng rỗng có sử dụng, bạn vẫn cần thực hiện kiểm tra tại đây, nếu không bạn sẽ cố gắng sendEmail() đến địa chỉ email là chuỗi trống (hoặc bạn đẩy séc vào sendEmail(), có thể dễ dàng kiểm tra null).

Trường hợp mẫu đối tượng rỗng thực sự hữu ích ở đây là nếu lớp CustomerVO triển khai phương thức sendEmail(). sau đó bạn chỉ có thể chuỗi các cuộc gọi với nhau, kể từ khi hợp đồng của getCustomer() sẽ đảm bảo rằng một tài liệu tham khảo null sẽ không được trả lại:

CustomerDAO.getCustomer(customerID).sendEmail(); 

Trong trường hợp đó phương pháp sendEmail() sẽ kiểm tra xem nó được yêu cầu hành động đặc biệt 'null đối tượng' và chỉ đơn giản là không làm gì (hoặc bất cứ điều gì thích hợp).

+1

+1, mặc dù tôi không muốn khách hàng của tôi có phương thức sendEmail.Điều đó chỉ mang lại cho một lớp khách hàng quá nhiều trách nhiệm. Nó giống như cho mọi lớp một phương thức "in" và bây giờ phải thực hiện logic in ở mọi nơi hoặc làm cho mọi lớp phụ thuộc vào một số trình quản lý in, trong khi nó có thể bị hạn chế đối với trình quản lý in và các biểu mẫu/lớp thực sự bắt đầu in. các lớp cần in. Trường hợp mẫu rỗng thực sự tốt đẹp, là trong thử nghiệm đơn vị ví dụ để cung cấp một lớp đăng nhập mà không làm bất cứ điều gì, do đó bạn không cần phải mã hóa mã đang được thử nghiệm. –

1

Phương thức getCustomer của bạn có ném ngoại lệ nếu khách hàng không tìm thấy, thay vì trả về không?

Câu trả lời, tất nhiên, điều đó phụ thuộc: có nên hầu như không bao giờ là trường hợp ID khách hàng không tồn tại? Nói cách khác, đó có phải là một trường hợp ngoại lệ không? Nếu vậy, một ngoại lệ là thích hợp.

Tuy nhiên, trong lớp truy cập dữ liệu, điều này thường khá bình thường đối với một thứ không tồn tại.Trong trường hợp đó, tốt hơn là không nên ném vì nó không phải là một tình huống bất ngờ, đặc biệt.

'Trả về đối tượng không trống có trường trống' có lẽ không tốt hơn. Làm thế nào để bạn biết nếu đối tượng trả về là 'hợp lệ' hay không mà không cần thêm một số mã kiểm tra có lẽ tệ hơn kiểm tra null?

Vì vậy, nếu nó có thể là một trạng thái bình thường mà một cái gì đó đang được tìm nạp không tồn tại, mẫu kiểm tra null có lẽ là tốt nhất. Nếu nó là cái gì đó là bất ngờ sau đó có phương pháp truy cập dữ liệu ném một ngoại lệ NotFound có lẽ là tốt hơn.

+0

Xem câu trả lời của tôi, nếu một cái gì đó không thể tồn tại, có một phương pháp kiểm tra xem nó có tồn tại hay không. Bằng cách đó, bạn chỉ cần ném ngoại lệ mà nó đặc biệt. – nicodemus13

1

Tôi gặp sự cố với loại mã này, đây là mẫu chung. Bạn không cần phải kiểm tra null nếu bạn phân hủy những gì bạn đang thực sự làm. Vấn đề ở đây, theo quan điểm của tôi, là bạn đang vi phạm SRP.

Phương thức CustomerVO custVO = CustomerDAO.getCustomer(customerID); thực hiện hai việc.

Thứ nhất, nó trả về khách hàng, nếu khách hàng tồn tại và thứ hai trả về null nếu không có khách hàng như vậy. Đây là hai hoạt động riêng biệt và phải được mã hóa như vậy.

Một cách tiếp cận tốt hơn sẽ là:

bool customerExists = CustomerDAO.exists(customerID); 

if (customerExists) 
{ 
    CustomerVO custVO = CustomerDAO.getCustomer(customerID); 
    sendEmail(custVO.getFirstName(), custVO.getEmailID()); 
} 
else 
{ 
    // Do whatever is appropriate if there is no such customer. 
} 

}

Vì vậy, chia phương pháp này thành hai, một trong đó kiểm tra xem các đối tượng yêu cầu tồn tại và lần thứ hai mà thực sự lấy nó. Không cần bất kỳ ngoại lệ nào và thiết kế và ngữ nghĩa là rất rõ ràng (trong đó, với một mẫu không-không-tồn tại-trả về-không, theo quan điểm của tôi). Hơn nữa, trong phương pháp này, phương pháp CustomerDAO.getCustomer(customerID) ném ArgumentException, nếu khách hàng được yêu cầu không tồn tại. Sau khi tất cả, bạn đã yêu cầu một Customer và không có một.

Hơn nữa, theo quan điểm của tôi, không có phương pháp nào phải trả lại null. Null rõ ràng là 'Tôi không biết câu trả lời đúng là gì, tôi không có giá trị trả lại'. Null không phải là ý nghĩa, thiếu thiếu ý nghĩa. Hãy tự hỏi, 'tại sao tôi trả lại thứ gì đó mà tôi biết không nên thực sự xảy ra? Phương thức của bạn GetCustomer phải trả lại rõ ràng là Customer. Nếu bạn trả lại null, bạn chỉ đơn giản là đẩy trách nhiệm của những việc cần làm để sao lưu chuỗi cuộc gọi và phá vỡ hợp đồng. Nếu có mặc định có ý nghĩa, hãy sử dụng điều đó, nhưng việc ném một ngoại lệ ở đây có thể khiến bạn suy nghĩ kỹ hơn về thiết kế chính xác.

0

Tên là mẫu thiết kế đối tượng NULL và không phải mẫu thiết kế kiểm tra NULL. Null đối tượng biểu thị sự vắng mặt của một đối tượng. Điều này nên được sử dụng khi bạn có đối tượng làm việc trong COLLABORATION. Trong trường hợp của bạn, bạn đang kiểm tra sự tồn tại của một đối tượng mà kiểm tra NULL sẽ được sử dụng tốt.

Mẫu thiết kế NULL không có nghĩa là thay thế xử lý ngoại lệ NULL. Đó là một trong những lợi ích phụ của mẫu thiết kế NULL nhưng ý định là cung cấp một hành vi mặc định.

Kiểm tra NULL không được thay thế bằng các đối tượng mẫu thiết kế NULL vì nó có thể dẫn đến các lỗi thầm lặng trong ứng dụng.

Hãy xem bài viết dưới đây mô tả chi tiết mẫu DO và Donts của NULL.

http://www.codeproject.com/Articles/1042674/NULL-Object-Design-Pattern

Các vấn đề liên quan