
O que aprendi tentando automatizar uma tarefa que eu odiava
Tinha uma tarefa manual que tomava 40 minutos por dia. Passei uma semana automatizando. O script levava 2 minutos mas levou 3 meses para ficou estável o suficiente para confiar.
Toda manhã eu gerava um relatório manual.
Exportava dados do CRM, colava numa planilha, calculava alguns totais, formatava, mandava por email para o cliente. 40 minutos. Todo dia.
Em outubro de 2019 automatizei isso. Levei uma semana. O script rodava em 2 minutos.
E nos três meses seguintes, o script quebrou umas oito vezes.
A automação estava certa. O problema era que eu havia automatizado o caminho feliz mas não os casos de exceção.
O script quebrava quando:
- O CRM retornava mais de 1000 registros (a API tinha paginação que eu não tinha implementado)
- Um campo vinha como
nullem vez de string vazia (meu código assumia string) - A API ficava fora do ar por 30 segundos (sem retry, o script falhava silenciosamente)
- O email do destinatário tinha mudado (hardcoded no script)
Cada quebra eu corrigia. Depois de três meses o script era estável. Mas nesses três meses, toda vez que quebrava, eu precisava detectar (às vezes o cliente reportava antes de mim), entender o que tinha acontecido, corrigir, e explicar.
A lição que ficou: automatizar não é escrever código que funciona uma vez. É escrever código que funciona de forma confiável, mesmo quando as entradas são inesperadas, mesmo quando serviços externos falham, mesmo quando alguém muda o dado no CRM.
# a versão ingênua
data = api.get_leads()
report = generate_report(data)
send_email(report, "[email protected]")
# o que precisei implementar
def fetch_with_pagination(api, page_size=100):
page = 1
all_data = []
while True:
response = api.get_leads(page=page, size=page_size)
if not response.data:
break
all_data.extend(response.data)
page += 1
return all_data
def fetch_with_retry(fn, max_attempts=3, delay=5):
for attempt in range(max_attempts):
try:
return fn()
except ApiUnavailable:
if attempt < max_attempts - 1:
time.sleep(delay * (attempt + 1))
raise RuntimeError("API unavailable after retries")
Não é código complexo. É código que considera o que pode dar errado.
A regra prática que aprendi:
Quando você automatiza algo, você está construindo um contrato implícito com os usuários (nesse caso, o cliente e eu mesmo): "isso vai acontecer de forma confiável toda vez."
Contrato implícito que quebra com frequência é pior do que não ter automação nenhuma. Pelo menos manualmente você sabe se funcionou.
Automação boa tem três partes: o caminho feliz funcionando, tratamento de falha com mensagem clara, e alguma forma de você saber quando falhou antes do usuário. A terceira foi a que mais me custou aprender. Um script que falha silenciosamente e você só descobre quando o cliente pergunta "onde está o relatório de hoje?" — é automação que criou mais problema do que resolveu.