Đừng sử dụng nếu bạn có thể tránh nó. Sử dụng hàm xuất xưởng trả về loại tùy chọn, bộ dữ liệu hoặc loại tổng riêng. Nói cách khác, biểu thị một giá trị có khả năng mặc định bằng một loại khác với giá trị được bảo đảm không được mặc định.
Đầu tiên, hãy liệt kê desiderata sau đó suy nghĩ về cách chúng ta có thể diễn đạt điều này bằng một vài ngôn ngữ (C ++, OCaml, Python)
- bắt sử dụng không mong muốn của một đối tượng mặc định tại thời gian biên dịch.
- làm rõ liệu một giá trị đã cho có khả năng được mặc định hay không trong khi đọc mã.
- chọn giá trị mặc định hợp lý của chúng tôi, nếu có, một lần cho mỗi loại . Chắc chắn không chọn một mặc định có khả năng khác nhau ở mỗi trang web cuộc gọi .
- làm cho nó dễ dàng cho các công cụ phân tích tĩnh hoặc một con người
grep
để săn lùng các lỗi tiềm ẩn.
- Đối với một số ứng dụng , chương trình sẽ tiếp tục bình thường nếu bất ngờ được cung cấp một giá trị mặc định. Đối với các ứng dụng khác , chương trình sẽ tạm dừng ngay lập tức nếu được cung cấp một giá trị mặc định, lý tưởng nhất là theo cách thông tin.
Tôi nghĩ rằng sự căng thẳng giữa Mẫu đối tượng Null và các con trỏ null xuất phát từ (5). Tuy nhiên, nếu chúng ta có thể phát hiện lỗi đủ sớm, (5) sẽ trở thành lỗi.
Hãy xem xét ngôn ngữ này bằng ngôn ngữ:
C ++
Theo tôi, một lớp C ++ thường có thể được xây dựng mặc định vì nó giúp giảm bớt sự tương tác với các thư viện và giúp sử dụng lớp này trong các thùng chứa dễ dàng hơn. Nó cũng đơn giản hóa sự kế thừa vì bạn không cần phải nghĩ về việc xây dựng siêu lớp nào để gọi.
Tuy nhiên, điều này có nghĩa là bạn không thể biết chắc giá trị của loại MyClass
có ở "trạng thái mặc định" hay không. Bên cạnh việc đưa vào một trường bool nonempty
hoặc tương tự với trạng thái mặc định bề mặt khi chạy, điều tốt nhất bạn có thể làm là tạo ra các phiên bản mới MyClass
theo cách bắt buộc người dùng kiểm tra nó .
Tôi khuyên bạn nên sử dụng một chức năng nhà máy mà trả về một std::optional<MyClass>
, std::pair<bool, MyClass>
hoặc một tài liệu tham khảo r-giá trị vào std::unique_ptr<MyClass>
nếu có thể.
Nếu bạn muốn chức năng xuất xưởng của mình trả về một số trạng thái "giữ chỗ" khác với trạng thái được tạo mặc định MyClass
, hãy sử dụng std::pair
và đảm bảo rằng tài liệu của bạn thực hiện điều này.
Nếu chức năng của nhà máy có một tên duy nhất, thật dễ dàng để grep
đặt tên và tìm kiếm sự chậm chạp. Tuy nhiên, thật khó grep
cho các trường hợp mà lập trình viên nên sử dụng chức năng của nhà máy nhưng không được .
Tháng 10
Nếu bạn đang sử dụng một ngôn ngữ như OCaml, thì bạn chỉ có thể sử dụng một option
loại (trong thư viện tiêu chuẩn OCaml) hoặc một either
loại (không phải trong thư viện tiêu chuẩn, nhưng dễ dàng tự cuộn). Hoặc một defaultable
loại (tôi đang tạo thành thuật ngữ defaultable
).
type 'a option =
| None
| Some of 'a
type ('a, 'b) either =
| Left of 'a
| Right of 'b
type 'a defaultable =
| Default of 'a
| Real of 'a
Một defaultable
như trình bày ở trên là tốt hơn so với một cặp vì người sử dụng bắt buộc đối sánh mẫu để trích xuất các 'a
và có thể không chỉ đơn giản là bỏ qua các yếu tố đầu tiên của cặp.
Tương đương với defaultable
loại như được hiển thị ở trên có thể được sử dụng trong C ++ bằng cách sử dụng một std::variant
với hai phiên bản cùng loại, nhưng các phần của std::variant
API không sử dụng được nếu cả hai loại đều giống nhau. Ngoài ra, đó là một cách sử dụng kỳ lạ std::variant
vì các hàm tạo kiểu của nó không được đặt tên.
Con trăn
Bạn không nhận được bất kỳ kiểm tra thời gian biên dịch nào cho Python. Nhưng, được gõ động, thường không có trường hợp nào bạn cần một thể hiện giữ chỗ của một số loại để xoa dịu trình biên dịch.
Tôi khuyên bạn chỉ nên ném một ngoại lệ khi bạn buộc phải tạo một thể hiện mặc định.
Nếu điều đó không được chấp nhận, tôi khuyên bạn nên tạo một DefaultedMyClass
kế thừa từ MyClass
và trả lại từ chức năng xuất xưởng của bạn. Điều đó mua cho bạn sự linh hoạt về chức năng "khai thác" trong các trường hợp mặc định nếu bạn cần.