Sử dụng đúng
Có nhiều cách sử dụng khác nhau null. Cách phổ biến nhất và đúng về mặt ngữ nghĩa là sử dụng nó khi bạn có thể có hoặc không có một giá trị duy nhất . Trong trường hợp này, một giá trị bằng nullhoặc là một cái gì đó có ý nghĩa như một bản ghi từ cơ sở dữ liệu hoặc một cái gì đó.
Trong những tình huống này, sau đó bạn chủ yếu sử dụng nó như thế này (bằng mã giả):
if (value is null) {
doSomethingAboutIt();
return;
}
doSomethingUseful(value);
Vấn đề
Và nó có một vấn đề rất lớn. Vấn đề là vào thời điểm bạn gọi doSomethingUsefulgiá trị có thể chưa được kiểm tra null! Nếu không thì chương trình có thể sẽ bị sập. Và người dùng thậm chí có thể không nhìn thấy bất kỳ thông báo lỗi tốt nào, bị bỏ lại với một cái gì đó như "lỗi khủng khiếp: giá trị mong muốn nhưng không có giá trị!" (sau khi cập nhật: mặc dù có thể có ít thông tin lỗi hơn như Segmentation fault. Core dumped., hoặc tệ hơn nữa, không có lỗi và thao tác không chính xác trên null trong một số trường hợp)
Quên viết séc nullvà xử lý các nulltình huống là một lỗi cực kỳ phổ biến . Đây là lý do tại sao Tony Hoare, người đã phát minh ra nulltại một hội nghị phần mềm có tên QCon London năm 2009 rằng ông đã mắc sai lầm hàng tỷ đô la vào năm 1965:
https://www.infoq.com/presentations/Null-References-The-Billion-Dollar- Sai lầm-Tony-Hoare
Tránh vấn đề
Một số công nghệ và ngôn ngữ giúp kiểm tra nullkhông thể quên theo các cách khác nhau, giảm số lượng lỗi.
Ví dụ, Haskell có Maybeđơn nguyên thay vì null. Giả sử đó DatabaseRecordlà một loại do người dùng định nghĩa. Trong Haskell, một giá trị của loại Maybe DatabaseRecordcó thể bằng Just <somevalue>hoặc nó có thể bằng Nothing. Sau đó, bạn có thể sử dụng nó theo nhiều cách khác nhau nhưng cho dù bạn sử dụng nó như thế nào, bạn không thể áp dụng một số thao tác trên Nothingmà không biết.
Ví dụ, hàm này được gọi là zeroAsDefaulttrả về xcho Just xvà 0cho Nothing:
zeroAsDefault :: Maybe Int -> Int
zeroAsDefault mx = case mx of
Nothing -> 0
Just x -> x
Christian Hackl nói C ++ 17 và Scala có cách riêng của họ. Vì vậy, bạn có thể muốn thử tìm hiểu xem ngôn ngữ của bạn có bất cứ thứ gì như vậy không và sử dụng nó.
Nulls vẫn được sử dụng rộng rãi
Nếu bạn không có gì tốt hơn thì sử dụng nulllà tốt. Chỉ cần tiếp tục xem ra cho nó. Gõ khai báo trong các hàm sẽ giúp bạn phần nào.
Ngoài ra điều đó nghe có vẻ không tiến bộ lắm nhưng bạn nên kiểm tra xem đồng nghiệp của mình có muốn sử dụng nullhay không. Họ có thể bảo thủ và có thể không muốn sử dụng cấu trúc dữ liệu mới vì một số lý do. Ví dụ, hỗ trợ các phiên bản cũ hơn của một ngôn ngữ. Những điều như vậy nên được khai báo trong các tiêu chuẩn mã hóa của dự án và thảo luận đúng đắn với nhóm.
Theo đề nghị của bạn
Bạn đề nghị sử dụng một trường boolean riêng. Nhưng dù sao bạn cũng phải kiểm tra nó và vẫn có thể quên kiểm tra nó. Vì vậy, không có gì chiến thắng ở đây. Nếu bạn thậm chí có thể quên một cái gì đó khác, như cập nhật cả hai giá trị mỗi lần, thì điều đó còn tồi tệ hơn. Nếu vấn đề quên kiểm tra nullkhông được giải quyết thì không có điểm nào. Tránh nulllà khó khăn và bạn không nên làm theo cách làm cho nó tồi tệ hơn.
Làm thế nào để không sử dụng null
Cuối cùng, có những cách phổ biến để sử dụng nullkhông chính xác. Một cách như vậy là sử dụng nó thay cho các cấu trúc dữ liệu trống như mảng và chuỗi. Một mảng trống là một mảng thích hợp như bất kỳ khác! Nó hầu như luôn luôn quan trọng và hữu ích cho các cấu trúc dữ liệu, có thể phù hợp với nhiều giá trị, có thể để trống, tức là có 0 độ dài.
Từ quan điểm đại số, một chuỗi rỗng cho các chuỗi giống như 0 cho các số, tức là nhận dạng:
a+0=a
concat(str, '')=str
Chuỗi rỗng cho phép các chuỗi nói chung trở thành một chuỗi đơn:
https://en.wikipedia.org/wiki/Monoid
Nếu bạn không hiểu thì điều đó không quan trọng đối với bạn.
Bây giờ hãy xem tại sao nó quan trọng để lập trình với ví dụ này:
for (element in array) {
doSomething(element);
}
Nếu chúng ta vượt qua một mảng trống ở đây, mã sẽ hoạt động tốt. Nó sẽ không làm gì cả. Tuy nhiên, nếu chúng tôi vượt qua nullở đây thì có thể chúng tôi sẽ gặp sự cố với một lỗi như "không thể lặp qua null, xin lỗi". Chúng tôi có thể bọc nó iflại nhưng ít sạch hơn và một lần nữa, bạn có thể quên kiểm tra nó
Cách xử lý null
Những gì doSomethingAboutIt()nên làm và đặc biệt là liệu nó có nên ném một ngoại lệ hay không là một vấn đề phức tạp khác. Nói tóm lại, nó phụ thuộc vào việc nullgiá trị đầu vào có thể chấp nhận được đối với một tác vụ nhất định hay không và điều gì được mong đợi trong phản hồi. Các ngoại lệ dành cho các sự kiện không được mong đợi. Tôi sẽ không đi sâu hơn vào chủ đề đó. Câu trả lời này rất lâu rồi.
std::optionalhoặcOption. Trong các ngôn ngữ khác, bạn có thể phải tự xây dựng một cơ chế phù hợp hoặc bạn thực sự có thể dùng đếnnullhoặc một cái gì đó tương tự vì nó thành ngữ hơn.