Tôi biết mọi người kiếm được nhiều tiền từ việc sử dụng ngoại lệ để kiểm soát dòng chảy nhưng đó không phải là vấn đề lớn nhất ở đây. Tôi thấy một vi phạm lệnh truy vấn tách lớn . Nhưng ngay cả đó không phải là tồi tệ nhất.
Không, điều tồi tệ nhất ở ngay đây:
/**
* Closes the door if open
*/
Tại sao mọi thứ khác nổ tung nếu giả định của bạn về trạng thái cửa là sai nhưng lock()
chỉ sửa nó cho bạn? Quên rằng điều này làm cho không thể khóa cửa mở, điều này là hoàn toàn có thể và đôi khi hữu ích. Không có vấn đề ở đây là bạn đã trộn lẫn hai triết lý khác nhau để xử lý các giả định không chính xác. Điều đó thật khó hiểu. Đừng làm vậy. Không cùng mức độ trừu tượng với cùng một kiểu đặt tên. Ow! Lấy một trong những ý tưởng bên ngoài. Các phương pháp dịch vụ cửa nên hoạt động theo cùng một cách.
Đối với vi phạm Phân tách truy vấn lệnh, tôi không cần phải cố gắng đóng cửa để tìm hiểu xem nó đóng hay mở. Tôi có thể chỉ cần hỏi. Dịch vụ cửa không cung cấp cách để làm điều đó mà không thể thay đổi trạng thái của cửa. Điều đó làm cho điều này trở nên tồi tệ hơn nhiều sau đó các lệnh cũng xảy ra để trả về các giá trị (một sự hiểu lầm phổ biến về những gì CQS nói về). Ở đây, các lệnh thay đổi trạng thái là cách duy nhất để thực hiện các truy vấn! Ow!
Đối với các trường hợp ngoại lệ đắt hơn mã trạng thái, đó là cuộc nói chuyện tối ưu hóa. Đủ nhanh là đủ nhanh. Không có vấn đề thực sự là con người không mong đợi ngoại lệ cho các trường hợp điển hình. Bạn có thể tranh luận về những gì điển hình tất cả những gì bạn thích. Đối với tôi câu hỏi lớn là làm thế nào bạn có thể đọc được mã bằng cách đọc.
ensureClosed(DoorService service, Door door){
// Need door closed and unlocked. No idea of its state. What to do?
try {
service.open(door)
service.close(door)
}
catch( DoorLockedException e ){
//Have no way to unlock the door so give up and die
log(e);
throw new NoOneGaveMeAKeyException(e);
}
catch( DoorAlreadyOpenedException e ){
try {
service.close(door);
}
catch( DoorAlreadyClosedException e ){
//Some multithreaded goof has been messing with our door.
//Oh well, this is what we wanted anyway.
//Hope they didn't lock it.
}
}
}
Xin đừng bắt tôi viết mã như thế này. Xin vui lòng cho chúng tôi isLocked()
và isClosed()
phương pháp. Với những cái đó tôi có thể tự viết ensureClosed()
và ensureUnlocked()
phương pháp dễ đọc. Những người chỉ ném nếu điều kiện bài của họ bị vi phạm. Tôi chỉ muốn tìm thấy bạn đã viết và kiểm tra chúng tất nhiên. Chỉ cần không trộn chúng lại với những thứ ném khi chúng không thể thay đổi trạng thái. Ít nhất là cho họ phân biệt tên.
Dù bạn làm gì, xin đừng gọi bất cứ điều gì tryClose()
. Đó là một cái tên khủng khiếp.
Đối với DoorLockedException
một mình và cũng có DoorAlreadyLockedException
bệnh nói điều này: tất cả là về việc sử dụng mã. Vui lòng không thiết kế các dịch vụ như thế này mà không viết mã bằng cách sử dụng và nhìn vào mớ hỗn độn bạn đang tạo. Tái cấu trúc và thiết kế lại cho đến khi sử dụng mã ít nhất có thể đọc được. Trong thực tế, xem xét việc viết mã bằng cách sử dụng đầu tiên.
ensureClosed(DoorService service, Door door){
if( !service.isClosed(door) ){
try{
service.close(door);
}
catch( DoorAlreadyClosedException e ){
//Some multithreaded goof has been messing with our door.
//Oh well, this is what we wanted anyway.
//Hope they didn't lock it.
}
} else {
//This is what you wanted, so quietly do nothing.
//Why are you even here? Who bothers to write empty else conditions?
}
}
ensureUnlocked(DoorService service, Door door){
if( service.islocked(door) ){
throw new NoOneGaveMeAKeyException();
}
}