Tôi đang trò chuyện với một người bạn về một đoạn mã Ruby và chủ đề về giá trị trả về đã xuất hiện…
… Và tất nhiên, nil
luôn là một phần của cuộc trò chuyện đó.
Cuối ngày hôm đó, tôi đang trên giường chuẩn bị đi ngủ và nghĩ, tại sao chúng ta lại sử dụng nil
?
Tôi nghĩ sẽ là một ý kiến hay nếu viết về vấn đề này vào ngày hôm sau, và tôi ở đây. Tôi hy vọng bạn thấy điều này thú vị và học được điều gì đó mới!
Giá trị trả lại &Hành vi mong đợi
Khi bạn gọi một phương thức như select
bạn sẽ luôn nhận được một mảng.
Ngay cả khi không có gì được chọn.
Ví dụ :
[1,2,3].select {} # [] [1,2,3].select(&:even?) # [2]
Nhưng tại sao điều này lại quan trọng?
Câu hỏi hay!
Nếu bạn luôn nhận được một mảng, bạn có thể gọi các phương thức mảng (size
, empty?
, push
…) mà không cần phải kiểm tra xem bạn có thực sự đang làm việc với một mảng .
Đó là một điều tốt vì việc kiểm tra lớp dẫn đến khả năng khớp nối cao.
Nếu bạn muốn viết mã linh hoạt hơn, hãy tránh kiểm tra “đây là lớp gì” càng nhiều càng tốt.
Trả lại các giá trị đơn
Ok, nhưng sử dụng một phương pháp như find
thì sao , chỉ trả về một giá trị?
Nếu phần tử được tìm thấy, nó chỉ hoạt động:
[1,2,3].find { |n| n == 2 } # 2
Nếu không có kết quả phù hợp, hãy find
phải trả lại một cái gì đó, nó có thể trả về false
, nhưng nếu chúng ta muốn gọi một phương thức trên giá trị trả về này, chúng ta sẽ nhận được một ngoại lệ.
Đây là nơi nil
đến, chúng tôi sử dụng nó vì nó là thứ gần nhất mà chúng tôi có thể nhận được đối với một Đối tượng Null chung chung.
Như bạn có thể nhớ lại từ bài viết cuối cùng của tôi về nil, tôi đã chỉ cho bạn cách nil
là một lớp có các phương thức như to_i
, to_s
&to_a
.
Điều này cho phép bạn sử dụng các phương thức như Array()
và String()
để chuyển đổi một đối tượng thành các loại này.
Ví dụ :
String(123) # "123" String(nil) # "" Array(nil) # []
Điều này cũng xuất hiện trong nội suy chuỗi:
"abc#{nil}dfg"
Các lệnh gọi nội suy chuỗi to_s
về kết quả đánh giá những gì bên trong khối nội suy. Vì vậy, nếu bạn có #{1 + 1}
điều này chuyển đổi thành 2.to_s
.
Bây giờ là vấn đề với nil
đến khi bạn không mong đợi , bạn nghĩ rằng đó là một số đối tượng phản hồi với foo
nhưng không phải vậy, vì vậy bạn nhận được NoMethodError
đáng sợ ngoại lệ.
Trong trường hợp đó, bạn muốn triển khai mẫu Null Object, như tôi mô tả trong bài viết này. Các giải pháp khác bao gồm sử dụng fetch
phương pháp với giá trị mặc định &nâng cao một ngoại lệ khi giá trị mặc định không có ý nghĩa.
Tóm tắt
Bạn đã biết tại sao chúng tôi sử dụng nil
, cách tránh các ngoại lệ đến từ các phương thức gọi trên nil
giá trị và cách viết mã tin cậy hơn.
Hãy xem mã của bạn và xem liệu bạn có thể phát hiện ra một số mã kiểm tra kiểu không (is_a?
/ kind_of?
/ ===
). Làm cách nào bạn có thể cải thiện mã đó bằng cách sử dụng những gì bạn đã học được hôm nay?