Geçenlerde bir olayın kaç yaşında olduğunu insan dostu bir şekilde gösteren küçük bir kod parçası yazıyordum. Örneğin, etkinliğin “Üç hafta önce” veya “Bir ay önce” veya “Dün” olduğunu gösterebilir.
Gereksinimler nispeten açıktı ve bu teste dayalı gelişim için mükemmel bir durumdu. Testleri birer birer yazdım, her testi geçmek için gereken kodu uyguladık ve her şey mükemmel çalışıyor gibiydi. Üretimde bir hata ortaya çıkana kadar.
İşte ilgili kod parçası:
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.
Testler, bugün, dün, dört gün önce, iki hafta önce, bir hafta önce vb. Meydana gelen bir olayın durumunu kontrol ediyordu ve kod buna göre oluşturuldu.
Kaçırdığım şey, bir olayın bir gün önce olduğu bir günden bir gün önce gerçekleşebileceğidir: örneğin, yirmi altı saat önce gerçekleşen bir olay bir gün önce olurken, tam olarak dün değil, şu an tam olarak 1 ise, bu tam olarak bir nokta. bir şey, ancak delta
bir tamsayı olduğundan, sadece bir olacak. Bu durumda, uygulama kodda açıkça beklenmeyen ve işlenmeyen “Bir gün önce” görüntüler. Ekleyerek düzeltilebilir:
if delta == 1:
return "A day ago"
hesapladıktan hemen sonra delta
.
Böceğin tek olumsuz sonucu, bu durumun nasıl olabileceğini merak ederek yarım saatimi boşa harcamam (ve bunun UTC'nin kodda aynı şekilde kullanılmasına rağmen zaman dilimi ile ilgisi olması gerektiğine inanmak) olmasına rağmen, varlığı beni rahatsız ediyor. Bu gösterir ki:
- Böyle basit bir kaynak kodunda bile mantıksal bir hata yapmak çok kolaydır.
- Test odaklı gelişme işe yaramadı.
Ayrıca endişe verici, bu tür böceklerin nasıl önlenebileceğini görememem. Kod yazmadan önce daha fazla düşünmenin yanı sıra, düşünebilmemin tek yolu, asla olamayacağımı düşündüğüm davalara pek çok şey eklemek (bir gün önce mutlaka dün olduğuna inandığım gibi) ve sonra her saniye son on yılda, çok karmaşık görünen herhangi bir iddia ihlali olup olmadığını kontrol etmek.
Bu hatayı en başta yaratmaktan nasıl kaçınabilirim?