Carreira Dev

7 jul, 2023

Cinco técnicas para guiar a escrita de bons códigos

Publicidade

O que pode ser considerado um “bom código”? Um bom código faz somente o que precisa ser feito de forma simples, direta e natural. Segundo Robert C. Martin, no livro “Código Limpo” um código bom é aquele que é fácil de ler, entender e manter. Ele é elegante e eficiente, mas também é claro e conciso. Em contrapartida, um código ruim é confuso, difícil de entender e, consequentemente, difícil de manter.

E por que precisamos escrever bons códigos? 

Necessidade de evolução contínua é uma realidade do desenvolvimento de software. Correção de defeitos, alteração de regras de negócio, mudanças de legislação e inclusão de novas funcionalidades são exemplos de necessidades comuns de um sistema em produção.

Um código limpo e bem estruturado pode permitir que sua evolução seja realizada de forma eficiente. Um código que possui fácil leitura e entendimento, permite a implementação de alterações de forma fácil e assertiva, o que pode minimizar a geração de impactos indesejados e defeitos no futuro.

Se a leitura é essencial para evolução, e todo software em uso precisa evoluir, escrever bons códigos é um investimento no futuro da saúde da empresa. É bom tanto para garantir o posicionamento do produto no mercado, permitindo que correções e novas funcionalidades sejam disponibilizadas em tempo hábil, quanto para garantir o bem estar de seus programadores. Podemos concordar que sustentar e evoluir um bom código é imensuravelmente melhor que trabalhar em correções de códigos complexos, acoplados e difíceis de entender.

Como escrever bons códigos?

Como o desenvolvedor é o escritor de fato, ele se torna o primeiro responsável pela escrita do código limpo, portanto o aperfeiçoamento do profissional é a primeira iniciativa necessária para a boa escrita. Um escritor experiente naturalmente será capaz de ser mais claro e conciso.

Se você é programador e está em busca do seu aperfeiçoamento pessoal, vou deixar três recomendações para adicionar à sua lista de estudos, recomendo seguir essa ordem de aprendizado para adquirir a base do conhecimento necessário para a escrita de um código elegante e eficiente.

1- O livro “Código Limpo”, de Robert C. Martin: Essa é a bíblia dos programadores que se importam em escrever bons códigos. Todo o básico é possível encontrar nesse livro, eu recomendo que leiam ele no início da carreira e voltem a ler novamente após alguns anos, eu fiz isso e tive uma visão muito mais ampla e questionadora na segunda leitura, recomendo;

2- Princípios S.O.L.I.D.: É claro que antes de aprender esses princípios é necessário uma base sobre orientação a objetos. Após o entendimento do clean code, podemos encontrar nos 5 princípios SOLID os valores que devemos usar como pilares da escrita dos nossos códigos;

3- Padrões de projetos: O livro clássico sobre o assunto é “Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos” (Gang of Four). Entender sobre padrões de projeto garante a projeção de código elegante, e também nos ajuda no entendimento das linguagens, frameworks e bibliotecas, porque essas ferramentas geralmente aplicam muitos padrões.

Mesmo que a empresa invista na aprendizagem dos seus programadores, essa responsabilidade ainda é pessoal e depende de cada indivíduo. Sendo assim, o objetivo desse artigo é apresentar algumas ferramentas e práticas que possam ser implementadas no processo de desenvolvimento para guiar a escrita de bons códigos. O que pode inclusive auxiliar na evolução dos profissionais envolvidos.

1) Revisão de código

Se no final das contas nosso maior desejo é que as pessoas entendam os nossos códigos, por que não submetê-los a leitura de outros desenvolvedores antes mesmo de liberar para teste? É validar a nossa ideia de imediato, além de investimento na qualidade do código, o processo de revisão também permite a troca de conhecimento entre os desenvolvedores. Para mais detalhes sobre o assunto acesse o artigo do nosso blog:

https://desenvolvimento.shift.com.br/revis%C3%A3o-de-c%C3%B3digo-uma-vis%C3%A3o-geral-c9764fe01096

2) Testes unitários

Testar a menor parte do seu código é, em primeira instância garantir que a lógica dele funciona, e em um segundo momento garantir a qualidade das alterações realizadas nele. Um código com testes facilita a sua manutenção, evolução e refatoração. Para cumprir seu papel, é necessário que o teste unitário seja parte do código e evolua com ele, mantendo a saúde do software.

Além de garantir o funcionamento de um método, os testes podem ser usados para explicitar a implementação das regras de negócio. Essa prática auxilia na criação de melhores códigos e no controle eficiente de alterações. Por exemplo uma mudança de uma regra de negócio, provavelmente deve gerar uma alteração em um teste unitário porque deve mudar a lógica do código. Enquanto uma refatoração, após implementada não deve gerar nenhuma alteração nos testes unitários, já que a alteração visa apenas melhorar a leitura e não muda a lógica interna. A resolução de um defeito por outro lado, pode ser um cenário que não foi mapeado nos testes unitários e pode gerar o incremento de algum cenário.

O desenvolvimento orientado a testes (TDD) pode auxiliar nessa prática, onde o primeiro passo é entender todas as regras de negócio, depois escrever os testes que esperam a implementação de cada regra e por último implementar os métodos necessários.

Independente da forma de desenvolver, ao escrever testes com base nas regras de negócio, o desenvolvedor traduz o seu entendimento, garantindo a clareza das implementações, o que pode auxiliar também na revisão do código. Os testes se tornam uma documentação semântica das implementações enquanto garantem seu funcionamento correto com base nas regras do negócio.

3) Refatoração

Calma, não é pra reescrever todo código ruim que encontrar, algumas refatorações são mais delicadas, mas também não podemos tratar o assunto como tabu, podemos encontrar um meio termo e utilizar a regra do escoteiro para pequenas parcelas de código, por exemplo alterar o nome de uma variável local de um método. Refatorar é melhorar o código sem modificar sua lógica, portanto realizar pequenas melhorias podem ajudar a manter o código saudável.

A regra do escoteiro diz para deixar sempre melhor do que encontrou, então se puder fazer isso de forma controlada faça. O contrário da melhoria contínua pode levar a famosa colcha de retalhos. Nesse cenário o código cresce a cada necessidade, até se tornar tão grande e complexo que para realizar uma nova alteração ou evolução se torna inviável. O que nos leva a necessidade da refatoração total.

Lidar com a refatoração é inevitável, cabe a nós escolher quando.

A escolha do momento certo para realizar a refatoração é uma decisão importante. Refatorar muito cedo pode levar a um desperdício de tempo, pois as necessidades e requisitos do projeto ainda podem mudar significativamente. Por outro lado, adiar por muito tempo pode resultar em um código que acumulou muitas dívidas técnicas. Em geral, é necessário encontrar um equilíbrio entre refatorar o código de forma contínua para mantê-lo limpo e saudável e não se deixar levar pela tentação de refatorar em excesso, prejudicando a produtividade e a entrega. O entendimento das melhores práticas de refatoração, bem como a comunicação e colaboração com a equipe de desenvolvimento, são essenciais para tomar decisões sobre lidar com a refatoração no contexto específico de um projeto.

4) GIT — Sistema de controle de versões

Se manter é preciso, controlar versões se torna inevitável, são tantas as facilidades garantidas pelo versionamento que merece um artigo completo. Mas fora o controle de versões de código e todas as funcionalidades gerais, pensando apenas no auxílio a qualidade do código, através de uma ferramenta GIT é possível:

  • Auto revisão: Que o programador revise o seu próprio código antes de realizar um commit, conferindo tudo que foi alterado e realizando uma primeira revisão da implementação.
  • Submeter um código para revisão de outro desenvolvedor: através dos pull requests é possível revisar, comentar e aprovar o código de outro desenvolvedor.
  • Exibir um resumo da alteração aplicada: ao utilizar textos relevantes nos commits podemos, de forma colaborativa, manter uma documentação de todas as alterações realizadas no código. As definições de padrões de commits da empresa podem inclusive permitir a rastreabilidade das implementações e seus originadores.
  • Correções e modificações seguras: com o comando “git blame” é possível obter um histórico dos commits que incluíram cada uma das linhas de um arquivo. É especialmente útil para a rastreabilidade de uma alteração ou defeito, algumas vezes entender a origem de uma implementação facilita uma alteração eficiente, sem gerar impactos indesejados.
  • Colaboração: A colaboração entre equipes é inevitável, as ramificações de branchs de trabalho, definição de fluxo de branchs podem servir de apoio inicial para o compartilhamento do código. A utilização de ferramentas visuais para resolução de conflitos ajuda a minimizar erros nesse processo.
  • Monitoramento de código: Os hooks do Git são scripts personalizáveis que podem ser usados para automatizar a execução de tarefas, como execução de testes, verificação de padrões de código ou a execução de ferramentas de análise estática. Também existem ferramentas e plugins Git que permitem monitorar complexidade ciclomática, cobertura de testes, linhas de código dentre outros detalhes.

5) Ferramentas de análise estática

Podem ser principalmente úteis para guiar a escrita de códigos que tenham um padrão de qualidade definido. Basicamente a análise estática é uma garantia inicial que o código é legível. Ela pode ajudar na aplicação de práticas específicas da empresa, além de princípios do código limpo.

É importante entender como o processo da empresa lida com cada uma das ferramentas citadas nesse artigo, por exemplo, o processo de revisão de código pode ser realizado com ou sem intervenção humana, um time pode entender que seu código precisa ser revisado por outro desenvolvedor, enquanto outro define métricas mais detalhadas de análise estática e não precisa de intervenção humana no processo, ou em um terceiro caso, a equipe entende que ambas as abordagens devem ser aplicadas, a ferramenta de análise estática pode cuidar da revisão de código na abordagem sintática, enquanto as reuniões com outros desenvolvedores tem por objetivo a revisão semântica do código.

Existem muitas ferramentas disponíveis mas depende da linguagem utilizada no projeto, por isso é uma decisão que leva um tempo para ser analisada e implementada. Vale inclusive entender se a automatização pode gerar economias no futuro, por exemplo se a ferramenta passar a cuidar de um processo que antes era realizado manualmente, ela pode ajudar a evitar erros além de economizar tempo. Quanto menos tempo o desenvolvedor gastar com processos que podem ser automatizados, mais tempo ele tem para projetar códigos bons.

Conclusão

Em resumo, investir em processos que apoiem a construção de código limpo é uma decisão estratégica para empresas que se preocupam com a qualidade das funcionalidades que entregam para o mercado.

É importante entender como cada equipe funciona e adaptar as técnicas citadas nesse artigo de acordo com a sua realidade. Também é possível não acertar na primeira tentativa, então fazer experimentos, entender como os times reagem a novos métodos e adaptá-los ao longo do tempo faz parte do processo de melhoria contínua que apoia o crescimento da empresa. Assim como o código produzido pode melhorar, os processos também podem e devem melhorar ao longo do tempo. Aqui na Shift costumamos dizer que “nada é escrito na pedra” porque sempre podemos revisitar nossos processos e torná-los melhores. Uma empresa que evolui a cada dia também pode apoiar a evolução de seus colaboradores, de seu código e aumentar a satisfação de seus usuários.