Estes são os tipos de erros que você normalmente encontra na etapa refator do red / green / refactor. Não esqueça esse passo! Considere um refator como o seguinte (não testado):
def pluralize(num, unit):
if num == 1:
return unit
else:
return unit + "s"
def convert_to_unit(delta, unit):
factor = 1
if unit == "week":
factor = 7
elif unit == "month":
factor = 30
elif unit == "year":
factor = 365
return delta // factor
def best_unit(delta):
if delta < 7:
return "day"
elif delta < 30:
return "week"
elif delta < 365:
return "month"
else:
return "year"
def human_friendly(event_date):
date = event_date.date()
today = now.date()
yesterday = today - datetime.timedelta(1)
if date == today:
return "Today"
elif date == yesterday:
return "Yesterday"
else:
delta = (now - event_date).days
unit = best_unit(delta)
converted = convert_to_unit(delta, unit)
pluralized = pluralize(converted, unit)
return "{} {} ago".format(converted, pluralized)
Aqui você criou 3 funções em um nível mais baixo de abstração, que são muito mais coesas e fáceis de testar isoladamente. Se você deixou de fora um intervalo de tempo que você pretendia, ele se destacaria como um polegar dolorido nas funções de ajuda mais simples. Além disso, ao remover a duplicação, você reduz o potencial de erro. Você teria que adicionar código para implementar seu caso quebrado.
Outros casos de teste mais sutis também vêm à mente quando se olha para uma forma refatorada como essa. Por exemplo, o que deve best_unit
fazer se delta
for negativo?
Em outras palavras, a refatoração não é apenas para torná-lo bonito. Isso torna mais fácil para os humanos detectar erros que o compilador não consegue.