Câu hỏi của bạn.
Nhưng, nhưng - từ sự ngây thơ của tôi, hãy để tôi hét lên - đôi khi một giá trị CÓ THỂ vắng mặt một cách có ý nghĩa!
Hoàn toàn trên tàu với bạn ở đó. Tuy nhiên, có một số cảnh báo tôi sẽ nhận được trong một giây. Nhưng trước tiên:
Nulls là ác và nên tránh bất cứ khi nào có thể.
Tôi nghĩ rằng đây là một tuyên bố có thiện chí nhưng quá mức.
Nulls không xấu xa. Chúng không phải là một antipotype. Chúng không phải là thứ cần tránh bằng mọi giá. Tuy nhiên, null dễ bị lỗi (do không kiểm tra null).
Nhưng tôi không hiểu làm thế nào để không kiểm tra null là bằng chứng nào đó chứng minh rằng null vốn đã sai khi sử dụng.
Nếu null là ác, thì các chỉ mục mảng và con trỏ C ++ cũng vậy. Họ không phải. Họ dễ dàng tự bắn vào chân mình, nhưng họ không nên tránh bằng mọi giá.
Đối với phần còn lại của câu trả lời này, tôi sẽ điều chỉnh ý định "nulls là xấu xa" thành một " nulls sắc thái hơn nên được xử lý có trách nhiệm ".
Giải pháp của bạn.
Trong khi tôi đồng ý với ý kiến của bạn về việc sử dụng null như một quy tắc toàn cầu; Tôi không đồng ý với việc bạn sử dụng null trong trường hợp cụ thể này.
Để tóm tắt các phản hồi dưới đây: bạn đang hiểu sai mục đích của kế thừa và đa hình. Mặc dù đối số của bạn để sử dụng null có hiệu lực, nhưng "bằng chứng" tiếp theo của bạn về lý do tại sao cách khác là xấu được xây dựng dựa trên việc lạm dụng quyền thừa kế, khiến cho các điểm của bạn có phần không liên quan đến vấn đề null.
Hầu hết các bản cập nhật tự nhiên có một Người chơi được liên kết với chúng - sau tất cả, cần phải biết người chơi nào đã thực hiện bước chuyển này. Tuy nhiên, một số cập nhật không thể có Trình phát được liên kết với chúng một cách có ý nghĩa.
Nếu các cập nhật này có ý nghĩa khác nhau (đó là), thì bạn cần hai loại cập nhật riêng biệt.
Xem xét tin nhắn, ví dụ. Bạn có thông báo lỗi và tin nhắn trò chuyện IM. Nhưng trong khi chúng có thể chứa dữ liệu rất giống nhau (tin nhắn chuỗi và người gửi), chúng không hoạt động theo cùng một cách. Chúng nên được sử dụng riêng biệt, như các lớp khác nhau.
Những gì bạn đang làm bây giờ là phân biệt hiệu quả giữa hai loại cập nhật dựa trên tính không hợp lệ của thuộc tính Người chơi. Điều đó tương đương với việc quyết định giữa thông báo IM và thông báo lỗi dựa trên sự tồn tại của mã lỗi. Nó hoạt động, nhưng nó không phải là cách tiếp cận tốt nhất.
- Bây giờ, mã JS sẽ chỉ nhận một đối tượng mà không có Trình phát như một thuộc tính được xác định, giống như nếu nó là null vì cả hai trường hợp đều yêu cầu kiểm tra xem giá trị có hay không có;
Lập luận của bạn dựa trên những sai lầm của đa hình. Nếu bạn có một phương thức trả về một GameUpdate
đối tượng, thì nó thường không bao giờ quan tâm đến việc phân biệt giữa GameUpdate
, PlayerGameUpdate
hoặc NewlyDevelopedGameUpdate
.
Một lớp cơ sở cần phải có một hợp đồng làm việc đầy đủ, tức là các thuộc tính của nó được định nghĩa trên lớp cơ sở chứ không phải trên lớp dẫn xuất (có thể nói, giá trị của các thuộc tính cơ sở này tất nhiên có thể được ghi đè trong các lớp dẫn xuất).
Điều này làm cho tranh luận của bạn moot. Trong thực tế tốt, bạn không bao giờ nên quan tâm rằng GameUpdate
đối tượng của bạn có hoặc không có người chơi. Nếu bạn đang cố truy cập vào Player
tài sản của a GameUpdate
, thì bạn đang làm điều gì đó phi logic.
Các ngôn ngữ được nhập như C # thậm chí sẽ không cho phép bạn thử và truy cập vào Player
tài sản của GameUpdate
vì GameUpdate
đơn giản là không có tài sản. Javascript là cách lỏng lẻo hơn đáng kể trong cách tiếp cận của nó (và nó không yêu cầu tiền biên dịch) vì vậy nó không bận tâm để sửa lỗi cho bạn và thay vào đó nó sẽ nổ tung khi chạy.
- Nếu một trường không thể khác được thêm vào lớp GameUpdate, tôi sẽ phải có thể sử dụng nhiều kế thừa để tiếp tục với điều này - nhưng MI là ác theo cách riêng của nó (theo các lập trình viên có kinh nghiệm hơn) và quan trọng hơn, C # không có nó vì vậy tôi không thể sử dụng nó.
Bạn không nên tạo các lớp dựa trên việc thêm các thuộc tính nullable. Bạn nên tạo các lớp dựa trên các loại cập nhật trò chơi độc đáo về chức năng .
Làm thế nào để tránh các vấn đề với null nói chung?
Tôi nghĩ rằng nó có liên quan để giải thích về cách bạn có thể diễn đạt một cách có ý nghĩa sự vắng mặt của một giá trị. Đây là một tập hợp các giải pháp (hoặc phương pháp xấu) không theo thứ tự cụ thể.
1. Sử dụng null nào.
Đây là cách tiếp cận dễ dàng nhất. Tuy nhiên, bạn đang đăng ký cho mình một tấn kiểm tra null và (khi không làm như vậy) xử lý sự cố ngoại lệ tham chiếu null.
2. Sử dụng một giá trị vô nghĩa không null
Một ví dụ đơn giản ở đây là indexOf()
:
"abcde".indexOf("b"); // 1
"abcde".indexOf("f"); // -1
Thay vì null
, bạn nhận được -1
. Ở cấp độ kỹ thuật, đây là một giá trị số nguyên hợp lệ. Tuy nhiên, giá trị âm là một câu trả lời vô nghĩa vì các chỉ số được dự kiến là số nguyên dương.
Về mặt logic, điều này chỉ có thể được sử dụng cho các trường hợp loại trả về cho phép nhiều giá trị có thể hơn mức có thể được trả về một cách có ý nghĩa (indexOf = số nguyên dương; int = số nguyên âm và số nguyên dương)
Đối với các loại tham chiếu, bạn vẫn có thể áp dụng nguyên tắc này. Ví dụ: nếu bạn có một thực thể có ID số nguyên, bạn có thể trả về một đối tượng giả với ID của nó được đặt thành -1, trái ngược với null.
Bạn chỉ cần xác định một "trạng thái giả" mà theo đó bạn có thể đo xem một đối tượng có thực sự có thể sử dụng được hay không.
Lưu ý rằng bạn không nên dựa vào các giá trị chuỗi được xác định trước nếu bạn không kiểm soát giá trị chuỗi. Bạn có thể cân nhắc đặt tên người dùng thành "null" khi bạn muốn trả lại một đối tượng trống, nhưng bạn sẽ gặp phải sự cố khi Christopher Null đăng ký dịch vụ của bạn .
3. Thay vào đó hãy ném một ngoại lệ.
Không, nhất quyết không. Các ngoại lệ không nên được xử lý cho luồng logic.
Điều đó đang được nói, có một số trường hợp bạn không muốn ẩn ngoại lệ (nullreference), nhưng thay vào đó hiển thị một ngoại lệ thích hợp. Ví dụ:
var existingPerson = personRepository.GetById(123);
Điều này có thể ném một PersonNotFoundException
(hoặc tương tự) khi không có người có ID 123.
Rõ ràng, điều này chỉ được chấp nhận đối với các trường hợp không tìm thấy một mục khiến cho không thể thực hiện thêm bất kỳ xử lý nào. Nếu không tìm thấy một mục là có thể và ứng dụng có thể tiếp tục, thì bạn KHÔNG BAO GIỜ nên ném ngoại lệ . Tôi không thể nhấn mạnh điều này đủ.