7 técnicas de depuração para acelerar a solução de problemas na produção
Publicados: 2022-03-11Fornecer suporte de produção para um aplicativo é um dos aspectos mais desafiadores do desenvolvimento de software. Os desenvolvedores são designados para a equipe de manutenção e trabalham na correção de bugs no aplicativo. No entanto, eles também estão disponíveis de plantão caso ocorra uma interrupção na produção, caso em que trabalham para colocar o aplicativo de volta nos trilhos o mais rápido possível.
Este artigo tem como objetivo fornecer um conjunto de recomendações selecionadas para que você possa evitar bugs na produção e encontrar problemas muito mais rapidamente. Manipular esses aplicativos em produção é uma tarefa complicada: muitas vezes, não há documentação disponível, o aplicativo foi escrito em uma pilha de tecnologia legada ou ambos. Há pouquíssimas sessões de treinamento e é comum ser chamado para dar suporte a um aplicativo sobre o qual você sabe pouco.
Muitos desenvolvedores não têm experiência em lidar com um aplicativo em produção. Há uma série de problemas que acontecem em ambientes de produção que causam bugs e interrupções, geralmente causando milhares e às vezes milhões de dólares em perda de receita para a empresa. Além disso, como a maioria dos desenvolvedores não tem exposição ao ambiente, eles continuam cometendo alguns erros que, por sua vez, causarão esses problemas. Esta lista de dicas deve tornar seu trabalho menos penoso, ensinando a partir da experiência de produção.
Dica #1: Remova ou automatize toda a configuração necessária para que o aplicativo seja executado.
Quanta configuração é necessária para instalar o software em um novo servidor? No passado, isso às vezes levava três dias para ser concluído toda vez que havia um novo desenvolvedor na equipe. A instalação do aplicativo exigiria muitas etapas que devem ser executadas manualmente. Com o tempo, o software evolui para novas versões que se tornam incompatíveis com essas instruções e, claro, as instruções geralmente não são atualizadas. De repente, você está gastando muito mais tempo do que o necessário simplesmente para colocar o aplicativo em funcionamento.
Com o advento da conteinerização, tornou-se muito mais fácil fornecer uma maneira de colocar um aplicativo em funcionamento em pouco tempo, com configuração zero e com o benefício adicional de que, como a imagem do Docker é autocontida, você executa um risco de ter problemas com diferentes versões do sistema operacional, linguagens e estruturas usadas.
Da mesma forma, simplifique a configuração do desenvolvedor, para que não demore muito tempo para começar a funcionar, incluindo a configuração do IDE. Um desenvolvedor deve ser capaz de ir de zero a herói em menos de 30 minutos.
Quando um problema de produção acontece, às vezes seus melhores especialistas podem não estar disponíveis (por exemplo, férias ou doença) e você quer que quem quer que você jogue no problema seja capaz de resolvê-lo e rapidamente.
Dica 2: Não caia na armadilha da sopa de pilha de tecnologia.
Quanto menos tecnologias usadas, melhor. Claro, às vezes, você precisa usar a ferramenta certa para o trabalho. No entanto, tome cuidado para não sobrecarregar as “ferramentas certas”. Mesmo a água potável pode resultar em sérios problemas de saúde se você beber demais. Cada nova linguagem e estrutura adicionada à pilha de tecnologia precisa passar por um processo de tomada de decisão claramente definido, com consideração cuidadosa dos impactos.
- Não adicione uma nova dependência de estrutura apenas porque você precisa de uma classe
StringUtils
. - Não adicione um idioma completamente novo só porque você precisa escrever um script rápido para mover os arquivos.
Uma grande pilha de dependências pode tornar sua vida miserável quando as bibliotecas se tornam incompatíveis ou quando ameaças de segurança são encontradas nos próprios frameworks ou em suas dependências transitivas.
Além disso, lembre-se de que as complexidades de pilha adicionadas tornam difícil encontrar e treinar novos desenvolvedores para a equipe. As pessoas passam para novos cargos em outras empresas, e você precisa encontrar novos. A rotatividade é muito alta nas equipes de engenharia, mesmo em empresas reconhecidas por ter grandes vantagens e guloseimas de equilíbrio entre vida profissional e pessoal. Você deseja encontrar o novo membro da equipe o mais rápido possível. Cada nova tecnologia adicionada ao topo da pilha de tecnologia aumenta o tempo para encontrar um novo candidato e tem o potencial de tornar as novas contratações cada vez mais caras.
Dica #3: O registro deve guiá-lo para encontrar o problema, não afogá-lo com detalhes inúteis.
O registro é muito semelhante aos comentários. É necessário documentar todas as decisões críticas que estão sendo tomadas, além de todas as informações a serem usadas em suas técnicas de depuração. Não é simples, mas com um pouco de experiência, é possível mapear alguns cenários possíveis de interrupções de produção e, em seguida, colocar o log necessário para resolver pelo menos isso. É claro que o registro evolui junto com a base de código, dependendo do tipo de problema que aparece. De um modo geral, você deve ter 80% do seu log nos 20% mais importantes do seu código - a parte que será mais usada. Informações importantes, por exemplo, são valores de argumentos passados para um método, tipos de tempo de execução de classes filhas e decisões importantes tomadas pelo software - ou seja, o momento em que ele estava em uma encruzilhada e ele escolheu a esquerda ou a direita.

Dica #4: Lide com situações inesperadas.
Mapeie muito claramente quais são as suposições do código. Se uma determinada variável deve sempre conter os valores 2, 5 ou 7, certifique-se de que seja do tipo enum, não int. A fonte número um de grandes interrupções de produção é quando uma determinada suposição falha. Todo mundo está procurando o problema no lugar errado porque eles tomam algumas coisas como certas.
As suposições devem ser documentadas explicitamente e quaisquer falhas nessas suposições devem gerar alarmes suficientes para que a equipe de suporte à produção possa corrigir rapidamente a situação. Também deve haver código para evitar que os dados fiquem em um estado inválido, ou pelo menos crie algum tipo de alerta nesse caso. Se certas informações devem ser armazenadas em um registro e, de repente, há dois registros, um aviso deve ser acionado.
Dica 5: Deve ser simples replicar um problema que está acontecendo com um cliente.
Uma das etapas mais difíceis é sempre replicar o problema enfrentado pelo cliente. Muitas vezes, você gastará 95% do tempo tentando replicar o problema e, no momento em que puder replicá-lo, será uma questão de minutos para corrigir, testar e implantar. Como tal, o arquiteto de aplicativos deve certificar-se de que é tremendamente simples e rápido replicar problemas. Muito disso acontece porque, para chegar na mesma situação em que o cliente se encontra, o desenvolvedor tem que fazer uma quantidade significativa de configuração da aplicação. Há muitos registros armazenados que juntos compõem a situação em que o cliente se encontra - o problema é que você, como desenvolvedor, precisa adivinhar exatamente o que o cliente fez. E, às vezes, eles realizaram uma sequência de etapas, das quais lembram apenas da última.
Além disso, o cliente explicará o problema em termos comerciais, que o desenvolvedor deverá traduzir em termos técnicos. E se o desenvolvedor tiver menos experiência com o aplicativo, ele não saberá pedir os detalhes que faltam, pois ainda nem sabe os detalhes que faltam. Copiar todo o banco de dados de produção para sua máquina é inviável. Portanto, deve haver uma ferramenta para importar rapidamente do banco de dados de produção apenas os poucos registros necessários para simular a situação.
Digamos que o cliente tenha um problema com a tela Pedidos. Você pode ter que importar alguns de seus pedidos, seus registros de clientes, alguns registros de detalhes de pedidos, registros de configuração de pedidos, etc. vendo a mesma coisa que o cliente está vendo. Tudo isso, é claro, deve ser feito com o devido cuidado para garantir que nenhum desenvolvedor tenha acesso a dados confidenciais.
Dica #6: Deve ser óbvio onde colocar os pontos de interrupção no aplicativo.
Se você tiver uma tela Customer, deve haver algum objeto Customer onde você possa colocar os pontos de interrupção para depurar um problema nessa tela. Às vezes, os desenvolvedores caem na febre da abstração e apresentam alguns conceitos incrivelmente inteligentes sobre como lidar com os eventos da interface do usuário. Em vez disso, devemos sempre confiar no princípio KISS (Keep it Simple, St- er, Silly) e ter um método facilmente localizável por evento de interface do usuário. Da mesma forma, para trabalhos de processamento em lote e tarefas agendadas, deve haver uma maneira fácil de identificar onde os pontos de interrupção são colocados para avaliar se esse código está funcionando ou não.
Dica #7: Certifique-se de que todas as dependências externas estejam explicitamente documentadas.
Idealmente, faça isso no arquivo README dentro do sistema de controle de origem para que a documentação não possa ser perdida. Documente quaisquer sistemas, bancos de dados ou recursos externos que devam estar disponíveis para que o aplicativo seja executado corretamente. Além disso, observe quais deles são opcionais e adicione instruções sobre como lidar com eles quando forem opcionais e não estiverem disponíveis.
Além das técnicas de depuração
Depois que essas recomendações forem seguidas ao criar novos recursos ou fornecer manutenção a um sistema, o suporte à produção se tornará muito mais fácil e sua empresa gastará muito menos tempo (e dinheiro). Como você já sabe, o tempo é essencial para solucionar bugs e travamentos de produção – qualquer minuto que possa ser economizado faz uma grande diferença nos resultados. Boa codificação!