Đừ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 MyClasscó ở "trạng thái mặc định" hay không. Bên cạnh việc đưa vào một trường bool nonemptyhoặ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 MyClasstheo 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::pairvà đả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ó grepcho 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 optionloại (trong thư viện tiêu chuẩn OCaml) hoặc một eitherloạ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 defaultableloạ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 defaultablenhư 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 'avà 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 defaultableloạ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::variantvới hai phiên bản cùng loại, nhưng các phần của std::variantAPI 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::variantvì 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 DefaultedMyClasskế thừa từ MyClassvà 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.