Tiền đề
Mã sau đây sẽ được coi là hình thức xấu, bất kể ngôn ngữ hoặc chức năng mong muốn:
while( true ) {
}
Lập luận hỗ trợ
Các while( true )
vòng lặp là hình thức nghèo vì nó:
- Phá vỡ hợp đồng ngụ ý của một vòng lặp trong khi.
- Khai báo vòng lặp while phải nêu rõ điều kiện thoát duy nhất .
- Ngụ ý rằng nó lặp lại mãi mãi.
- Mã trong vòng lặp phải được đọc để hiểu mệnh đề kết thúc.
- Các vòng lặp lặp lại mãi mãi ngăn người dùng chấm dứt chương trình từ bên trong chương trình.
- Không hiệu quả.
- Có nhiều điều kiện kết thúc vòng lặp, bao gồm cả việc kiểm tra "true".
- Dễ bị lỗi.
- Không thể dễ dàng xác định nơi đặt mã sẽ luôn thực thi cho mỗi lần lặp.
- Dẫn đến mã phức tạp không cần thiết.
- Phân tích mã nguồn tự động.
- Để tìm lỗi, phân tích độ phức tạp của chương trình, kiểm tra bảo mật hoặc tự động lấy ra bất kỳ hành vi mã nguồn nào khác mà không cần thực thi mã, việc chỉ định (các) điều kiện phá vỡ ban đầu cho phép các thuật toán xác định các bất biến hữu ích, do đó cải thiện các chỉ số phân tích mã nguồn tự động.
- Vòng lặp vô hạn.
- Nếu mọi người luôn sử dụng
while(true)
vòng lặp for không phải là vô hạn, chúng ta sẽ mất khả năng giao tiếp chính xác khi các vòng lặp thực sự không có điều kiện kết thúc. (Có thể cho rằng, điều này đã xảy ra rồi, vì vậy vấn đề là tranh luận.)
Thay thế cho "Đi tới"
Đoạn mã sau là dạng tốt hơn:
while( isValidState() ) {
execute();
}
bool isValidState() {
return msg->state != DONE;
}
Ưu điểm
Không có cờ. Không goto
. Không có ngoại lệ. Dễ dàng thay đổi. Dễ đọc. Dễ dàng sửa chữa. Ngoài ra, mã:
- Cô lập kiến thức về khối lượng công việc của vòng lặp khỏi chính vòng lặp.
- Cho phép ai đó duy trì mã dễ dàng mở rộng chức năng.
- Cho phép nhiều điều kiện kết thúc được gán ở một nơi.
- Tách mệnh đề kết thúc khỏi mã để thực thi.
- An toàn hơn cho các nhà máy Điện hạt nhân. ;-)
Điểm thứ hai là quan trọng. Nếu không biết mã hoạt động như thế nào, nếu ai đó yêu cầu tôi tạo vòng lặp chính để các luồng (hoặc quy trình) khác có một chút thời gian CPU, bạn sẽ nghĩ đến hai giải pháp:
Lựa chọn 1
Dễ dàng chèn tạm dừng:
while( isValidState() ) {
execute();
sleep();
}
Lựa chọn 2
Ghi đè thực thi:
void execute() {
super->execute();
sleep();
}
Mã này đơn giản hơn (do đó dễ đọc hơn) so với một vòng lặp có nhúng switch
. Các isValidState
phương pháp duy nhất nên xác định xem vòng lặp nên tiếp tục. Workhorse của phương thức nên được trừu tượng hóa thành execute
phương thức, điều này cho phép các lớp con ghi đè hành vi mặc định (một nhiệm vụ khó khăn khi sử dụng nhúng switch
và goto
).
Ví dụ Python
Đối chiếu câu trả lời sau (cho một câu hỏi Python) đã được đăng trên StackOverflow:
- Vòng lặp mãi mãi.
- Yêu cầu người dùng nhập lựa chọn của họ.
- Nếu đầu vào của người dùng là 'khởi động lại', hãy tiếp tục lặp lại mãi mãi.
- Nếu không, dừng lặp lại mãi mãi.
- Kết thúc.
Mã
while True:
choice = raw_input('What do you want? ')
if choice == 'restart':
continue
else:
break
print 'Break!'
Đấu với:
- Khởi tạo sự lựa chọn của người dùng.
- Vòng lặp trong khi lựa chọn của người dùng là từ 'khởi động lại'.
- Yêu cầu người dùng nhập lựa chọn của họ.
- Kết thúc.
Mã
choice = 'restart';
while choice == 'restart':
choice = raw_input('What do you want? ')
print 'Break!'
Ở đây, while True
dẫn đến mã sai lệch và quá phức tạp.