Gần đây tôi đã viết một đoạn mã nhỏ có thể chỉ ra một cách thân thiện với con người bao nhiêu tuổi một sự kiện. Chẳng hạn, nó có thể chỉ ra rằng sự kiện đã xảy ra, cách đây ba tuần, hay cách đây một tháng trước
Các yêu cầu tương đối rõ ràng và đây là một trường hợp hoàn hảo để phát triển theo hướng thử nghiệm. Tôi đã viết từng bài kiểm tra một, thực hiện mã để vượt qua từng bài kiểm tra và mọi thứ dường như hoạt động hoàn hảo. Cho đến khi một lỗi xuất hiện trong sản xuất.
Đây là đoạn mã có liên quan:
now = datetime.datetime.utcnow()
today = now.date()
if event_date.date() == today:
return "Today"
yesterday = today - datetime.timedelta(1)
if event_date.date() == yesterday:
return "Yesterday"
delta = (now - event_date).days
if delta < 7:
return _number_to_text(delta) + " days ago"
if delta < 30:
weeks = math.floor(delta / 7)
if weeks == 1:
return "A week ago"
return _number_to_text(weeks) + " weeks ago"
if delta < 365:
... # Handle months and years in similar manner.
Các thử nghiệm đã kiểm tra trường hợp của một sự kiện xảy ra hôm nay, hôm qua, bốn ngày trước, hai tuần trước, một tuần trước, v.v., và mã được xây dựng tương ứng.
Điều tôi đã bỏ lỡ là một sự kiện có thể xảy ra một ngày trước ngày hôm qua, trong khi đó là một ngày trước: ví dụ một sự kiện xảy ra hai mươi sáu giờ trước sẽ là một ngày trước, trong khi không chính xác là ngày hôm qua nếu bây giờ là 1 giờ sáng. một cái gì đó, nhưng vì delta
là một số nguyên, nó sẽ chỉ là một. Trong trường hợp này, ứng dụng sẽ hiển thị trên mạng Một ngày trước, rõ ràng là bất ngờ và chưa được xử lý trong mã. Nó có thể được sửa bằng cách thêm:
if delta == 1:
return "A day ago"
ngay sau khi tính toán delta
.
Mặc dù hậu quả tiêu cực duy nhất của lỗi là tôi đã lãng phí nửa giờ để tự hỏi trường hợp này có thể xảy ra như thế nào (và tin rằng nó phải làm với các múi giờ, mặc dù việc sử dụng UTC trong mã thống nhất), sự hiện diện của nó đang gây phiền toái cho tôi. Nó chỉ ra rằng:
- Rất dễ phạm phải một lỗi logic ngay cả trong một mã nguồn đơn giản như vậy.
- Phát triển theo hướng kiểm tra đã không giúp đỡ.
Điều đáng lo ngại là tôi không thể thấy làm thế nào có thể tránh được những lỗi như vậy. Bên cạnh suy nghĩ nhiều hơn trước khi viết mã, cách duy nhất tôi có thể nghĩ đến là thêm nhiều khẳng định cho các trường hợp mà tôi tin rằng sẽ không bao giờ xảy ra (như tôi tin rằng một ngày trước nhất thiết phải là ngày hôm qua), và sau đó lặp đi lặp lại mỗi giây mười năm qua, kiểm tra bất kỳ vi phạm khẳng định nào, có vẻ quá phức tạp.
Làm thế nào tôi có thể tránh tạo ra lỗi này ở nơi đầu tiên?