Cometer erros é importante para o seu crescimento como desenvolvedor. Gosto de dizer que o desenvolvimento de software é uma série contínua de erros e correções (ou problemas e soluções, se você preferir ver dessa forma). Para mim, sei que não seria o desenvolvedor incrível que sou se já não tivesse cometido todos os erros que cometi.

Os desenvolvedores cometem erros; isso é um dado porque somos humanos. Cometer erros é uma parte natural do processo de desenvolvimento. O verdadeiro problema não é que cometemos erros-isso é inevitável. É que às vezes nossos erros chegam aos nossos clientes, onde, na melhor das hipóteses, são constrangedores e, na pior, custam tempo e dinheiro para a empresa.

O que precisamos como desenvolvedores são ferramentas e técnicas que nos ajudem a detectar nossos erros antes que eles viajem para muito longe. Felizmente, podemos aprender com os erros dos outros e temos acesso a uma ampla gama de técnicas e práticas que podemos implantar para mitigar preventivamente o risco de erros ao entrarmos na produção.

Nesta postagem, abordaremos várias técnicas que podem ajudar. Usar uma combinação dessas técnicas nos dá liberdade para cometer os erros que sempre cometeríamos-e isso, por sua vez, nos dá espaço para aprender e crescer como desenvolvedores. Também nos ajuda a descobrir nossos erros antecipadamente e minimiza o risco de uma alteração importante ir para a produção.

Técnicas de desenvolvedor individuais

Eu dividi essas técnicas em duas seções. Primeiro, vamos cobrir o que você pode praticar sozinho e, em seguida, veremos o que você pode praticar com sua equipe. Como você verá, há muitas coisas que você pode fazer por conta própria para melhorar sua prática de desenvolvimento.

Codificação iterativa com pequenos commits

Isso é algo que todo desenvolvedor pode fazer. Ao escrever seu código iterativamente em pequenos incrementos, você pode testar e confirmar cada alteração de código independentemente, dando pequenos passos na direção de seu plano geral atual. Pequenas mudanças são mais fáceis de testar e verificar como corretas do que grandes mudanças; também é mais fácil desistir quando algo dá errado.

Quando as coisas vão mal, você pode redefinir sua cópia de trabalho com segurança. Embora você perca suas alterações atuais, elas não serão muito porque você está apenas fazendo pequenos commits.

Essa técnica é tão importante que é na verdade a regra mais fundamental em minha filosofia de desenvolvimento: quando você codifica em incrementos pequenos e simples, você mantém o código funcionando .

No final do dia, muitos commits de código pequenos e bem testados somam uma grande quantidade de código novo e funcional.

Mudança de código pequeno se os commits aumentam para grandes quantidades de alterações de código

Teste de código manual

Testar manualmente seu código é uma parte necessária, mas subestimada do desenvolvimento. Brinque com seu código! Entenda o que ele realmente faz, e não apenas o que você acha que ele faz. Essa é a melhor maneira de detectar erros antes que o código deixe seu computador de desenvolvimento.

Você pode testar seu código em seu REPL, na linha de comando ou usando seu front-end; você pode testar seu REST APIs usando VS Code REST Client , ou até mesmo crie seu próprio testbed, se necessário. Existem muitas maneiras de testar, mas certifique-se de que você está realmente testando seu código.

O teste manual é um ótimo ponto de partida para novos desenvolvedores e desenvolvedores experientes que criam novos produtos. Como há um custo significativo envolvido em testes automatizados, geralmente é melhor garantir que seu produto seja viável antes de investir em testes automatizados. Além disso, você precisa ser bom em testes manuais antes de ser bom em testes automatizados-como você poderia automatizar algo que você não sabe como fazer?

Mesmo depois de passar para o teste automatizado, você ainda precisará recorrer ao teste manual de vez em quando. Sem mencionar que alguém da sua equipe terá que fazer o teste manual de qualquer maneira-se o teste exploratório não for feito, você provavelmente não será capaz de encontrar os bugs que os desenvolvedores não poderiam imaginar.

Configurando seu ambiente de teste

Se você ainda não tem uma configuração rápida e eficiente para teste em seu computador de desenvolvimento, considere que a primeira coisa que você precisa corrigir em seu ambiente de desenvolvimento.

Você deseja ter um script ou estrutura que possa inicializar e ter seu aplicativo em execução e pronto para testar em poucos instantes-quanto mais rápido, melhor. O comando compose no Docker é ótimo para isso, e ainda melhor, Compose agora está integrado ao Docker !

Você também precisará de acesso fácil a dados realistas para quaisquer testes que planeja executar. Você precisará de acessórios de banco de dados, ou conjuntos de dados de teste, para diferentes configurações de seu aplicativo. Esses conjuntos de dados de teste não precisam ser complicados-um conjunto de arquivos JSON fará o trabalho. Em seguida, você precisará de um script para carregar rapidamente os dados em seu banco de dados de teste.

Também é muito importante que você tenha acesso a um ambiente de teste semelhante ao seu ambiente de produção voltado para o cliente. Sua empresa deve fornecer isso a você-e se não fornecer, eles não podem reclamar quando erros de software aparecerem no ambiente de produção real.

Você também pode certificar-se de que seu ambiente de desenvolvimento está configurado para corresponder, ou corresponder o mais próximo possível, aos ambientes de teste e produção. Use o Docker para isso -é uma ótima maneira para garantir que o que funciona no desenvolvimento também funcione na produção e também funcione para seus colegas de equipe.

Autoavaliação do código

A autoavaliação é algo que todo desenvolvedor deve fazer, mesmo se você também estiver fazendo a revisão por pares.

Revisar seu próprio código antes de confirmá-lo é possivelmente a maneira mais fácil de detectar erros em seu código antes que qualquer outra pessoa o faça. As autoavaliações devem ser rápidas-supondo que você esteja fazendo pequenos commits, não deve demorar muito para revisar cada um enquanto você está trabalhando.

Use o recurso diff do seu software de controle de versão para verificar as alterações feitas. Certifique-se de entender as alterações no código e o motivo ou motivos pelos quais você está fazendo esse commit. Se você não os entende, não se comprometa ainda. Reserve um tempo para pensar sobre isso.

Tente explicar seu código a um amigo imaginário que está sentado ao seu lado. Alguns gostam de explicar suas mudanças de código para um pato de borracha.

Pato de borracha usado para depuração

Verifique o seu próprio trabalho primeiro, antes que outras pessoas o verifiquem. Você pode se surpreender com a quantidade de bugs que pode detectar preventivamente com uma autoavaliação consistente.

Pratique codificação defensiva

Antecipando-se à Lei de Murphy, devemos sempre praticar a codificação defensiva . É ingênuo pensar que nosso código funcionará o tempo todo-devemos nos preparar para o pior. Nosso código lançará exceções inesperadas (geralmente em produção, quando não esperamos), nossas APIs serão usadas da maneira errada, as entradas para nossas funções serão lixo. Eventualmente, tudo o que pode dar errado terá dado errado.

Portanto, devemos presumir que as coisas darão errado e garantir que nosso código lide com isso normalmente.

Como descobrimos isso? Por meio de…

Teste defensivo

Você deve atacar ativamente seu próprio código para determinar como ele responde. Adicione exceções ao código aleatoriamente e veja o que acontece. Use suas APIs da maneira errada de propósito. Passe entradas de lixo para suas funções. Queime servidores aleatoriamente-também conhecidos como engenharia do caos -para ter certeza de que seu sistema distribuído está tolerante a falhas.

Quando você souber como seu próprio código pode falhar, estará em uma posição melhor para lidar com essas falhas.

Teste automatizado

Já cobrimos como é necessário testar nosso código toda vez que o alteramos. E antes de cada lançamento de produção, devemos testar o código integrado de toda a equipe de desenvolvimento.

Depois de aprender como testar manualmente seu código, por que gastar horas testando-o laboriosamente se você pode colocá-lo no modo automático? Hoje em dia, não há muito código que não possa ser submetido a testes automatizados. Podemos usar simulação para isolar nosso código para teste de unidade ou podemos obter um verdadeiro estrondo para nosso investimento com testes de integração ou teste ponta a ponta (E2E) .

O teste automatizado significa que podemos executar novamente nosso processo de teste a qualquer momento, sem ter que investir nosso próprio tempo.

É importante reconhecer que o teste automatizado é um grande investimento . Precisamos ter certeza de que é um investimento que vale a pena antes de entrarmos nele, mas para projetos de médio a longo prazo, o teste automatizado provavelmente vai economizar muito tempo e dinheiro-sem mencionar, provavelmente vai pegar alguns embaraçosos bugs que de outra forma teriam chegado à produção.

Desenvolvimento orientado a testes

Desenvolvimento orientado a testes (TDD) faz testes automatizados e coloca-o na frente e no centro do processo de desenvolvimento: nosso desenvolvimento é conduzido pelo processo de teste.

O TDD alcança um resultado incrível que você precisa ver por si mesmo para acreditar de verdade. A primeira vez que você tentar o TDD e perceber que seu código funciona perfeitamente após a primeira execução, você ficará surpreso. É raro que o código seja executado corretamente na primeira vez-sempre há um problema-mas com o TDD, é perfeitamente normal que seu código seja executado perfeitamente na primeira vez, dependendo, é claro, da precisão e confiabilidade de seus testes!

Talvez a coisa mais importante sobre o TDD é que ele faz você pensar sobre o teste desde o início, o que ajuda a refinar sua capacidade de criar código que pode ser submetido a testes automatizados.

TDD muda você como desenvolvedor. O desenvolvedor pós-TDD escreve código de alta qualidade, bem projetado e melhor testado. Mesmo quando um desenvolvedor pós-TDD não está fazendo TDD, seu código terá menos erros puramente em virtude de prestar mais atenção ao que está escrevendo.

Testado Modelo de desenvolvimento (TDD)

Invista em suas habilidades e ambiente de desenvolvimento

A última coisa que você pode fazer como desenvolvedor individual é investir tempo constante e consistentemente melhorando suas habilidades e atualizando seu conjunto de ferramentas. Esteja sempre aprendendo e melhorando. Esteja sempre em busca de ferramentas e técnicas que podem fazer a diferença.

Temos o privilégio de ser desenvolvedores em um momento em que temos acesso a um enorme e crescente ecossistema de ferramentas. Temos nossa escolha de linguagens de programação, estruturas e ferramentas de software e teste. Você precisa entender o que está disponível e como isso pode ajudá-lo a fornecer um código mais confiável-portanto, certifique-se de estar por dentro do que há de melhor e mais recente na área.

Técnicas da equipe de desenvolvedores

Agora vamos subir para o nível de equipe! Na seção a seguir, revisaremos uma coleção de técnicas que você pode praticar com sua equipe.

Revisão do código de pares

Ter um novo olhar sobre o seu código é um passo além da revisão do seu próprio código. Na próxima vez que você estiver prestes a enviar um código, chame seu colega de equipe para ver as alterações no código. Revise o diff mudança por mudança. Explique o que você mudou e por que está mudando. Se você estiver trabalhando remotamente, envie uma solicitação pull e faça com que ela seja revisada virtualmente antes de ser aceita.

Isso funciona porque seu revisor tem uma perspectiva diferente e é provável que ele identifique bugs e deficiências em seu código que você não imaginou-ou não poderia-imaginar.

As revisões de código por pares também são uma ótima maneira de promover a comunicação e compartilhar experiências de aprendizagem entre e dentro da equipe. Também melhora a capacidade de sua equipe de receber críticas-mas tome cuidado para garantir que você está servindo ao tipo bem-intencionado. Críticas tóxicas e não construtivas não são e não devem ser bem-vindas.

Observe que não se trata de culpá-lo por problemas em seu código. Trata-se de fazer a equipe trabalhar em conjunto para melhorar o produto e encontrar problemas que, de outra forma, poderiam chegar à produção.

Estratégia de ramificação

Uma estratégia de ramificação simples, porém robusta, é fácil de implementar e pode ajudar a isolar o código problemático. Você também pode usar branches para proteger seu cliente contra problemas.

Não precisa ser complicado. Eu gosto de usar os seguintes branches: main , test e prod . Criar esses pontos de teste significa que seu código precisa passar por vários pontos de verificação antes de ser infligido aos clientes.

Desenvolvedores enviando código para main significa que seu código é integrado com frequência. Isso ajuda a evitar conflitos de mesclagem e garante que a equipe de desenvolvimento trabalhe em conjunto para integrar seu código e corrigir quaisquer problemas que ocorram.

Esta é a base para integração contínua , uma prática importante que antecede e fundamenta a entrega contínua. Quando o main é quebrado, é responsabilidade da equipe descobrir o que está errado e consertá-lo.

Assumindo que o branch main está saudável quando os recursos estão prontos, main é mesclado com test . Agora, testes extensivos podem ser feitos em test antes de mesclar com prod e infligir as alterações no cliente.

Priorizando defeitos

Você está trabalhando em uma base de código que já está cheia de bugs e problemas? Seu foco deve ser reduzir os defeitos que você já possui. Uma base de código duvidosa ou um ambiente de desenvolvimento ruim causa problemas próprios, mas também pode diminuir a motivação do desenvolvedor-o que pode, por sua vez, aumentar o número de problemas que chegam à produção.

Concentre-se primeiro em corrigir os piores defeitos existentes antes de adicionar novos recursos.

Claro, existe um equilíbrio aqui-temos que continuar adicionando novos recursos para manter o progresso dos negócios-mas é uma troca. Com a estrutura de equipe certa, podemos implementar novos recursos ao mesmo tempo em que estamos melhorando continuamente a base de código para ser mais confiável e resistente a falhas.

Certifique-se de ter uma visão de longo prazo para a saúde do seu produto. Pode levar muitas horas de esforço persistente e contínuo para lidar com isso de forma eficaz.

Programação em pares

O que você faz quando tem um problema complicado que está se mostrando difícil de resolver? Você pede a outra pessoa para se sentar ao seu lado e ajudá-lo a resolver o problema. A programação em pares leva isso ao extremo: pares de desenvolvedores trabalham juntos para resolver problemas lado a lado.

O benefício aqui é simples: dois pares de olhos detectam mais problemas do que um. A programação em pares ajuda os desenvolvedores a encontrar problemas de maneira mais rápida e confiável, mas também pode melhorar e expandir muito sua experiência. Não há maneira mais rápida de subir de nível como desenvolvedor do que trabalhar em pares com alguém mais experiente.

Depois de entrar em um ritmo com a programação em pares, o código livre de bugs realmente flui. É como um jogo de pingue-pongue em que os jogadores cooperam para manter a bola no ar pelo maior tempo possível.

“Pare a linha” com desenvolvimento ágil

O desenvolvimento ágil tem suas raízes na manufatura enxuta, introduzida por Taiichi Ohn da Toyota. Em seu sistema, qualquer trabalhador da fábrica era capaz de interromper a produção caso percebesse algum problema. Os problemas foram então reparados e a produção reiniciada. Eles não toleraram quaisquer falhas de fabricação.

Como desenvolvedores, devemos fazer o mesmo. Não tolere problemas em sua integração contínua ou sistemas de entrega contínua. Se esses sistemas automatizados falharem, a equipe de desenvolvimento deve parar de trabalhar em outros projetos e se concentrar em corrigi-los. Esses são os sistemas de alerta precoce para problemas e os pontos de verificação para o código que vai para a produção. Eles são nossa última linha de defesa antes que os bugs atinjam o cliente. A equipe deve dar a mais alta prioridade em manter esses sistemas funcionando.

Mas-o que acontece quando os problemas são lançados na produção? Devemos tentar consertá-los na produção? Isso é um não difícil!

Colete evidências e documente o caso de reprodução o mais rápido possível. Em seguida, para o bem de seu cliente, reverta a alteração de interrupção para a versão de trabalho anterior para restaurar a funcionalidade o mais rápido possível. Assim que a pressão acabar, você pode reproduzir e corrigir o problema em um ambiente de teste ou computador de desenvolvimento, onde isso não incomodará os clientes.

Conclusão

Os programadores cometem erros e bugs acontecem. É um fato do desenvolvimento, mas isso não significa que nossos clientes devam sofrer. Há muitas maneiras de detectar-e corrigir-problemas no início de nosso pipeline de desenvolvimento.

Uma vez que podemos esperar que problemas ocorram, devemos estar sempre em busca de soluções.

Use as técnicas descritas nesta postagem do blog para reduzir o risco de erros que podem chegar até a produção. Suas necessidades de desenvolvimento variam, mas você tem o dever de impedir que seus erros cheguem aos usuários.

A postagem Mantendo os erros longe da produção apareceu primeiro em LogRocket Blog .