Tôi vừa có một cuộc thảo luận về lựa chọn thiết kế sau khi xem xét mã. Tôi tự hỏi ý kiến của bạn là gì.
Có Preferences
lớp này , là một nhóm cho các cặp khóa-giá trị. Giá trị Null là hợp pháp (đó là quan trọng). Chúng tôi hy vọng rằng một số giá trị nhất định có thể chưa được lưu và chúng tôi muốn tự động xử lý các trường hợp này bằng cách khởi tạo chúng với giá trị mặc định được xác định trước khi được yêu cầu.
Giải pháp thảo luận được sử dụng mẫu sau (LƯU Ý: đây không phải là mã thực tế, rõ ràng - nó được đơn giản hóa cho mục đích minh họa):
public class Preferences {
// null values are legal
private Map<String, String> valuesFromDatabase;
private static Map<String, String> defaultValues;
class KeyNotFoundException extends Exception {
}
public String getByKey(String key) {
try {
return getValueByKey(key);
} catch (KeyNotFoundException e) {
String defaultValue = defaultValues.get(key);
valuesFromDatabase.put(key, defaultvalue);
return defaultValue;
}
}
private String getValueByKey(String key) throws KeyNotFoundException {
if (valuesFromDatabase.containsKey(key)) {
return valuesFromDatabase.get(key);
} else {
throw new KeyNotFoundException();
}
}
}
Nó đã bị chỉ trích là một mô hình chống - lạm dụng các ngoại lệ để kiểm soát dòng chảy . KeyNotFoundException
- được đưa vào cuộc sống chỉ với một trường hợp sử dụng đó - sẽ không bao giờ được nhìn thấy ngoài phạm vi của lớp này.
Về cơ bản, đó là hai phương pháp chơi tìm nạp với nó chỉ đơn thuần là để giao tiếp với nhau.
Khóa không có trong cơ sở dữ liệu không phải là điều đáng báo động, hoặc ngoại lệ - chúng tôi hy vọng điều này xảy ra bất cứ khi nào cài đặt tùy chọn mới được thêm vào, do đó cơ chế khởi tạo nó một cách duyên dáng với giá trị mặc định nếu cần.
Phản biện là getValueByKey
- phương thức riêng tư - như được định nghĩa ngay bây giờ không có cách thông báo tự nhiên nào về phương thức công khai về cả giá trị, và liệu khóa có ở đó không. (Nếu không, nó phải được thêm vào để có thể cập nhật giá trị).
Trả lại null
sẽ là mơ hồ, vì null
là một giá trị pháp lý hoàn hảo, vì vậy không có ý nghĩa cho dù nó có nghĩa là chìa khóa không có ở đó, hoặc nếu có null
.
getValueByKey
sẽ phải trả về một số loại a Tuple<Boolean, String>
, bool được đặt thành true nếu khóa đã có sẵn, để chúng ta có thể phân biệt giữa (true, null)
và (false, null)
. (Một out
tham số có thể được sử dụng trong C #, nhưng đó là Java).
Đây có phải là một thay thế đẹp hơn? Có, bạn sẽ phải định nghĩa một số lớp sử dụng một lần cho hiệu quả của nó Tuple<Boolean, String>
, nhưng sau đó chúng ta sẽ loại bỏ KeyNotFoundException
, vì vậy loại cân bằng đó không còn nữa. Chúng tôi cũng tránh được việc xử lý một ngoại lệ, mặc dù về mặt thực tế không có ý nghĩa gì - không có cân nhắc về hiệu suất, đó là ứng dụng khách và không giống như sở thích của người dùng sẽ được truy xuất hàng triệu lần mỗi giây.
Một biến thể của phương pháp này có thể sử dụng Guava Optional<String>
(Guava đã được sử dụng trong suốt dự án) thay vì một số tùy chỉnh Tuple<Boolean, String>
, và sau đó chúng ta có thể phân biệt giữa Optional.<String>absent()
và "phù hợp" null
. Mặc dù vậy, nó vẫn cảm thấy bị hack, vì những lý do dễ thấy - giới thiệu hai cấp độ "vô hiệu" dường như lạm dụng khái niệm đứng đằng sau việc tạo Optional
s ở vị trí đầu tiên.
Một tùy chọn khác là kiểm tra rõ ràng liệu khóa có tồn tại hay không (chỉ thêm một boolean containsKey(String key)
phương thức và gọi getValueByKey
nếu chúng tôi đã xác nhận rằng nó tồn tại).
Cuối cùng, người ta cũng có thể nội tuyến phương thức riêng tư, nhưng thực tế getByKey
có phần phức tạp hơn mẫu mã của tôi, do đó, nội tuyến sẽ làm cho nó trông khá khó chịu.
Tôi có thể đang chia tóc ở đây, nhưng tôi tò mò không biết bạn sẽ đặt cược gì để gần nhất với thực tiễn tốt nhất trong trường hợp này. Tôi đã không tìm thấy câu trả lời trong hướng dẫn về phong cách của Oracle hoặc của Google.
Việc sử dụng các ngoại lệ như trong mẫu mã có phải là mẫu chống lại không, hoặc có thể chấp nhận được không khi các lựa chọn thay thế cũng không được sạch sẽ? Nếu là nó, trong hoàn cảnh nào nó sẽ ổn? Và ngược lại?
getValueByKey
cũng là công khai.