paint-brush
7 práticas comprovadas para aumentar a velocidade de desenvolvimento e a qualidade do projetopor@dsitdikov
1,622 leituras
1,622 leituras

7 práticas comprovadas para aumentar a velocidade de desenvolvimento e a qualidade do projeto

por Daniil Sitdikov8m2023/03/28
Read on Terminal Reader

Muito longo; Para ler

Ao adotar técnicas como simulação de resposta de back-end, sinalizadores de recursos, monitoramento de erros, otimização de desempenho, padrões de estilo de código, testes de regressão e rastreamento, você pode criar um software mais eficiente e confiável.
featured image - 7 práticas comprovadas para aumentar a velocidade de desenvolvimento e a qualidade do projeto
Daniil Sitdikov HackerNoon profile picture
0-item

Todos esses pontos podem ser aplicados ao desenvolvimento móvel, web front-end e back-end. Reuni essas práticas de diferentes equipes e através dos problemas que enfrentei nos últimos 6 anos. Essas práticas podem ser especialmente úteis quando você cria um projeto do zero. Alguns deles podem se adequar perfeitamente a você, enquanto outros não. Se você tem suas próprias abordagens e experiências diferentes, ficaria feliz se você as compartilhasse aqui. A propósito, se você é um desenvolvedor intermediário ou júnior em busca de uma promoção, a implementação dessas práticas em sua equipe pode realmente ajudar. Vamos!

1. Zombando das respostas de back-end até que esteja pronto

Em um processo de desenvolvimento de software padrão, quando uma nova solicitação de recurso vem do negócio, ela é distribuída entre várias equipes: front-end, back-end e desenvolvimento de aplicativos móveis.


Em seguida, cada equipe procede ao planejamento e decomposição das tarefas. Mas e se a equipe de back-end exigir muito mais tempo para desenvolver sua parte? E se eles puderem entregar endpoints apenas uma vez por semana?


O back-end se torna um gargalo.


As equipes de desenvolvimento mobile e front-end acabam trabalhando assim: "Ah, o back-end já implementou isso. Deixa eu fazer essa tarefa." Então, eles fazem uma pausa, mudam seu contexto para outro recurso e o ciclo continua. Isso leva à fadiga, diminuição da velocidade e qualidade reduzida.


Solução: chegar a um acordo com a equipe de back-end e zombar de todas as solicitações.

Na abordagem clássica, temos uma lacuna entre as tarefas. Na "abordagem simulada", todo o trabalho é executado como um fluxo


1. Coordene com a equipe de back-end os endpoints e as entidades.


2A. Implemente a API de back-end com respostas de stub. A biblioteca Faker pode ajudar na geração de dados de amostra.


2B. Ou implemente stubs no frontend. Pode ser um objeto com dados diretamente no código. Por exemplo, em Node.js, você pode implementar isso de forma eficiente usando importações dinâmicas e evitando aumentar o tamanho do pacote:

 getUser() { return import('../../assets/mocks/users') .then(data => data.userById) .then(deserializeUser); };

Isso também pode ser um serviço HTTP simulado que busca arquivos JSON de ativos em vez de fazer solicitações reais.


  1. Oculte o recurso atrás de um sinalizador de recurso.


  2. Quando o back-end estiver pronto, mude para a API real se você usou a abordagem de stubs de front-end e verifique se tudo funciona conforme o esperado. E ative esse recurso.

2. Sinalizador de recurso

Agora, como você provavelmente notou, na seção anterior, mencionei sinalizadores de recurso. Em poucas palavras, sinalizadores de recursos, também conhecidos como alternância de recursos, permitem que os desenvolvedores ativem ou desativem recursos em um ambiente ao vivo. Há também alguns casos em que são úteis: lançar novos recursos gradualmente, realizar testes A/B, habilitar recursos beta e implementar hotfixes.


Usamos o Gitlab para armazenar sinalizadores de recursos. É um repositório dedicado que é consumido por projetos de back-end e front-end. A grande notícia é que ele possui uma interface de usuário amigável, portanto, os gerentes de produto podem gerenciar os recursos por conta própria. Anteriormente, costumávamos usar sinalizadores de recursos para cada repositório de projeto separadamente. No entanto, essa abordagem não fornecia a capacidade de desabilitar recursos para todo o produto de uma só vez. Então, movemos tudo para o repositório único.


No código, parece bem simples:

  1. No projeto, buscamos todos os sinalizadores de recursos ativos. Como sob o capô, o Gitlab é baseado no Unleash (serviço de alternância de recursos), usamos seu cliente oficial.
  2. E então, basta colocar if features.YOUR_FEATURE no código que precisa ser oculto.
  3. Você pode expandir os casos de uso adicionando valores diferentes no sinalizador de recurso. Por exemplo, adicionando o valor da cor ou o valor do desconto.


3.Monitoramento de erros para rastreamento de problemas em um ambiente de produção

Quando nosso produto fez a transição do estágio MVP para um aplicativo de produção, ficamos preocupados com a possibilidade de os usuários receberem erros que não poderíamos reproduzir e nem saber. Depois de pesquisar ferramentas de rastreamento de erros, decidimos pelo Sentry. A experiência foi positiva. E agora, vamos passar por algumas nuances importantes.

Erros inúteis

Sob o capô, qualquer exceção não capturada será rastreada. À medida que o aplicativo e o número de usuários crescem, o número de erros pode se tornar tão grande que fica quase impossível notar algo realmente importante. Sentinela pode se transformar em uma lixeira se você não filtrar as coisas desnecessárias. Por exemplo, eventos como solicitações canceladas, erros de conexão e erros de scripts conectados são totalmente inúteis e só enviarão spam para seu e-mail de trabalho com notificações. Como solução, você pode adicionar filtros à configuração. Para fazer isso, simplesmente defina um callback beforeSend e coloque-o em seu sentryPackage.init . Neste callback, você pode analisar cada erro detectado e então descartá-lo (retornando null) se for inútil. Aqui está um exemplo de um filtro que exclui erros desnecessários:

 function beforeSend(event, hint) { const error = hint.originalException; const externalScripts = [ 'gtm.js', // Google Tag Manager 'watch.js', // X Analytics ].join('|'); const errorsToIgnore = [ AxiosError.ERR_NETWORK, AxiosError.ECONNABORTED, AxiosError.ETIMEDOUT ]; if (axios.isCancel(error) || errorsToIgnore.includes(error.code) || error.stack?.match(externalScripts)) { return null; } return event; }


Inclua mais dados para melhor depuração

Por padrão, o Sentry pode não incluir o conteúdo da solicitação e resposta no relatório de erro. Sem essas informações, a depuração adequada é impossível. Felizmente, no manipulador beforeSend , podemos incluir essas informações.

 function beforeSend(event, hint) { const error = hint.originalException; if (error.isAxiosError) { const url = error.request?.responseURL; const response = error.response?.data; const request = error.config?.data; event.extra = { ...(event.extra || {}), url, response, request }; } return event; }

Filtrar informações confidenciais

Dados como senhas, endereços de e-mail e chaves não devem ser incluídos no conteúdo do erro. O Sentry possui um mecanismo interno para ocultar esse tipo de informação. Você pode configurá-lo nas configurações de segurança. Além disso, você também pode remover algo no objeto de evento em beforeSend

Solução independente

Se a natureza do seu negócio proibir o armazenamento desse tipo de dados em um servidor em outro lugar, o Sentry oferece a possibilidade de usá-lo em seus próprios servidores.

4. Rastreamento

O caminho do ID de rastreamento

Imagine uma situação em que você capturou com sucesso um erro no Sentry, mas as informações na descrição são insuficientes. Você recorre aos logs, mas como identificar o erro específico entre milhares de solicitações e ainda mais linhas de log por segundo? Como distinguir os corretos, construir a cadeia de solicitações e apontar o erro exato, principalmente quando sua empresa possui várias equipes e integra com outros serviços? É aqui que o rastreamento entra em jogo.


  1. O rastreamento fornece um diagrama completo de invocações e identifica o método preciso que falhou, mesmo quando você tem comunicação assíncrona executada por um intermediário de mensagem.
  2. Ele permite que você determine facilmente de que lado ocorreu o erro ao integrar com diferentes equipes.
  3. O rastreamento também é útil para depuração de desempenho. Por exemplo, pode ajudar a esclarecer se a renderização leva mais tempo ou se um método em um microsserviço não é otimizado o suficiente.


Em nossa implementação específica, usamos Jaeger , que é baseado na API OpenTracing.


Resumindo, cada solicitação e todas as suas chamadas de método são marcadas com um rótulo exclusivo. Cada rótulo tem uma referência ao seu pai e alguns metadados. A estrutura desse número depende da implementação, mas quanto ao OpenTracing, você pode ler como ele funciona e se familiarizar com termos como span, referência, filho, pai e assim por diante na página oficial do repositório . Na vida real, o rastreamento, felizmente, raramente será usado. No entanto, nesses raros acidentes, você pode economizar tempo.

5.Otimização de desempenho

Quando implementamos o MVP do app da fintech, tínhamos um formulário bastante complicado. Naquela época, eu ainda era jovem e inexperiente. E, finalmente, percebemos que nosso projeto estava desacelerando. Tivemos que gastar horas adicionais para descobrir o motivo. Tivemos muitas re-renderizações desnecessárias porque ignoramos regras básicas relacionadas a props no React. Eu queria fazer todo o possível para evitar tais situações no futuro.


Então, adicionei ao projeto linters como este e uma configuração inicial adicional para package.json para executar why-did-you-render . Resumindo, este plug-in emite um aviso se algo for renderizado novamente desnecessariamente e sugere como evitá-lo. Além disso, incluímos a execução do Lighthouse no modo headless . Algumas pessoas dizem que otimizações prematuras são ruins, mas para mim é um princípio: faça certo desde o início .

6. Estilo de código definido para todos os projetos de equipe

Você provavelmente já ouviu falar da teoria das janelas quebradas. Se houver uma janela quebrada em um prédio e ninguém a substituir, eventualmente não haverá uma única janela intacta naquele prédio.

Quanto menos regras e controles houver em um projeto, maior será a tentação de escrever um código de baixa qualidade ou em um estilo totalmente diferente. Um código inconsistente aumenta o tempo de compreensão, enquanto um código claro, familiar e conciso permite uma leitura rápida. Em uma de nossas equipes, descrevemos o estilo de codificação em um só lugar . Como um excelente ponto de partida, você pode usar o estilo de código Prettier ou Airbnb .

7. Testes de regressão

Uma quantidade significativa de literatura já foi escrita sobre os diferentes tipos de testes, abordagens e como escrevê-los adequadamente. A única coisa que vale a pena mencionar aqui é que nenhum aplicativo de produção pode sobreviver sem testes de regressão. É por isso que concentramos todos os nossos esforços na criação de uma estrutura de teste abrangente de ponta a ponta e, com base nela, escrevemos testes vinculados a cenários de BDD e histórias de usuários. Usamos o padrão Page Object para organizar nosso código e o framework Playwright para interagir com o navegador. Para testar em diferentes navegadores, incluindo o Safari, você pode usar uma solução chamada Moon . Ele pode ser implantado em um de seus servidores.

Conclusão

Obrigado por reservar um tempo para ler este artigo! Em conclusão, este artigo destaca as principais práticas de engenharia de software que aprimoram os processos de desenvolvimento e a qualidade do código. Ao adotar técnicas como simulação de resposta de back-end, sinalizadores de recursos, monitoramento de erros, otimização de desempenho, padrões de estilo de código, testes de regressão e rastreamento, você pode criar um software mais eficiente e confiável. Vamos continuar a melhorar nosso software e manter contato! :)