2010-12-26 33 views
16

Có thực hành không tốt để chuyển đối số NULL cho các phương thức hay nói cách khác chúng ta nên có định nghĩa phương thức cho phép đối số NULL làm đối số hợp lệ.Đối số NULL có phải là một thực tế không tốt?

Giả sử tôi muốn hai phương thức 1. để truy xuất danh sách tất cả các công ty 2. để truy xuất danh sách các công ty dựa trên bộ lọc.

Chúng ta có thể có hai phương pháp như như dưới đây

List<Company> getAllCompaniesList(); 
    List<Company> getCompaniesList(Company companyFilter); 

hoặc chúng tôi có thể có một phương pháp duy nhất

List<Company> getCompaniesList(Company companyFilter); 

đây trong trường hợp thứ hai, nếu đối số là NULL thì phương pháp trở lại danh sách tất cả các công ty.

Bên cạnh câu hỏi về thực tiễn tốt, thực tế tôi thấy một vấn đề khác với cách tiếp cận sau được giải thích bên dưới.

Tôi đang triển khai Spring AOP, trong đó tôi muốn có một số kiểm tra về các đối số như 1. Đối số NULL? 2. Kích thước của bộ sưu tập là 0?

Có một số tình huống mà chúng ta không thể có đối số null ở tất cả như cho phương pháp

void addBranches(int companyId, List<Branch>); 

kiểm tra này có thể được thực hiện rất tốt bằng cách sử dụng Spring AOP bằng cách định nghĩa phương pháp như sau

@Before(argNames="args", value="execution(* *)") 
void beforeCall(JoinPoint joinPoint ,Object[] args) 
{ 
      foreach(Object obj in args) 
      { 
       if(obj == NULL) 
       { 
        throw new Exception("Argument NULL"); 
       } 
      } 
} 

Nhưng vấn đề tôi đang phải đối mặt là kể từ khi tôi đã xác định một số phương pháp mà nên chấp nhận NULL đối số cho nhiều chức năng của một phương pháp duy nhất như đã đề cập ở trên cho phương pháp Danh sách getCompaniesList (Company companyFilter); Vì vậy, tôi không thể áp dụng AOP thống nhất cho tất cả các phương pháp và không phải một số biểu thức cho các phương thức khớp tên sẽ hữu ích ở đây.

Vui lòng cho tôi biết nếu cần thêm thông tin hoặc sự cố không đủ mô tả.

Cảm ơn bạn đã đọc sự cố của tôi và suy nghĩ về nó.

+1

Đó là vấn đề về phong cách. Không có câu trả lời đúng. –

Trả lời

14

Tốt, trong trường hợp có quá nhiều phương thức quá tải. Vì vậy, thay vì có tất cả các kết hợp các tham số, bạn cho phép một số kết hợp là null. Nhưng nếu bạn làm như vậy, tài liệu này một cách rõ ràng với

@param foo foo description. Can be null 

Trong trường hợp của bạn tôi muốn có hai phương pháp, nơi người đầu tiên gọi lần thứ hai với một cuộc tranh luận null. Nó làm cho API dễ sử dụng hơn.

Không có đường dây nghiêm ngặt để dừng quá tải và bắt đầu dựa vào các thông số có thể vô hiệu. Đó là vấn đề ưu tiên. Nhưng lưu ý rằng do đó phương pháp của bạn với hầu hết các thông số sẽ cho phép một số trong số chúng được nullable, do đó, tài liệu này là tốt.


Cũng lưu ý rằng cách ưu tiên để đối phó với nhiều thông số hàm tạo là thông qua Trình tạo. Vì vậy, thay vì:

public Foo(String bar, String baz, int fooo, double barr, String asd); 

nơi mỗi người trong số các đối số là tùy chọn, bạn có thể có:

Foo foo = new FooBuilder().setBar(bar).setFooo(fooo).build(); 
+0

Nhưng, sau đó chúng ta phải tạo một phương thức cho mỗi tham số (trừ khi chúng ta nhóm một số tham số vào một đối tượng, ví dụ: string username, string password = object user). Nó rất hữu ích và xinh đẹp, nhưng không phải là quá nhiều mã? Ngoài ra, henning77 nói rằng nó không ổn từ quan điểm thực tế do tất cả các NPE mà nó có thể gây ra. – testerjoe2

5

Thực tiễn phổ biến, nhưng có nhiều cách để làm cho mã của bạn rõ ràng hơn - tránh kiểm tra rỗng đôi khi hoặc di chuyển chúng ở nơi khác. Tra cứu mẫu đối tượng rỗng - nó cũng có thể chính xác những gì bạn cần: http://en.m.wikipedia.org/wiki/Null_Object_pattern?wasRedirected=true

+0

Cảm ơn bạn, Bạn có thể cung cấp một số liên kết tốt cho cùng nếu bạn đã biết? –

+0

Yep, sẽ chỉnh sửa ... –

+0

Mô hình đối tượng đơn giản có thể hữu ích cho một số trường hợp như trả về bộ sưu tập không phải trong tất cả các trường hợp như trong trường hợp đối tượng duy nhất của nó tôi sẽ trả về NULL. –

2

Quy tắc là: giao diện đơn giản, thực hiện phức tạp.

Các quyết định thiết kế về API của bạn nên được thực hiện bằng cách xem xét cách mã máy khách có khả năng sử dụng nó. Nếu bạn mong đợi để xem một trong hai

getAllCompaniesList(null); 

hoặc

if (companyFilter == null) { 
    getAllCompaniesList(); 
} else { 
    getAllCompaniesList(companyFilter); 
} 

sau đó bạn đang làm nó sai. Nếu trường hợp sử dụng có khả năng là mã máy khách sẽ, tại thời điểm nó được viết, có hoặc không có bộ lọc, bạn nên cung cấp hai điểm vào; nếu quyết định đó có thể không được thực hiện cho đến khi thời gian chạy, cho phép một đối số null.

13

tôi sử dụng một quy tắc rất đơn giản:

bao giờ cho phép null như một cuộc tranh cãi hoặc trả lại giá trị trên một phương pháp nào.

Tôi sử dụng OptionalPreconditions hoặc AOP để thực thi quy tắc đó. Quyết định này đã tiết kiệm cho tôi rất nhiều giờ sửa lỗi sau hành vi của NPE hoặc lạ.

+0

Các liên kết tuyệt vời! Là một lập trình viên có kinh nghiệm vừa đạt được nhiều kiến ​​thức về Java hơn, điều này rất hữu ích. – Duke

+0

'setLocationRelativeTo (null);' ... Tôi muốn Sun/Oracle biết đó là một thực hành tồi. – Stepan

+0

Nhưng Bozho nói đôi khi của nó cũng không được phép. Bạn có đồng ý không? – testerjoe2

0

Một cách tiếp cận khác có thể hoàn toàn khả thi có thể là có giao diện CompanyFilter với phương thức companyIsIncluded(Company) chấp nhận số Company và trả về true hoặc false để nói liệu có nên đưa công ty nào hay không. Company có thể triển khai giao diện sao cho hành vi của phương thức companyIsIncluded được nhân đôi equals(), nhưng có thể dễ dàng có một phương thức CompanyFilter.AllCompanies đơn lẻ có phương thức companyIsIncluded() sẽ luôn trả về giá trị đúng. Sử dụng phương pháp đó, không cần phải vượt qua giá trị null - chỉ cần chuyển một tham chiếu đến singlet AllComapnies.

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