Gerência de Projetos Dev & TI

12 nov, 2018

Qualidade além do código: além do time

Publicidade

No último artigo falamos um pouco sobre como podemos alcançar a qualidade de código através de um bom gerenciamento de times. Porém, obviamente, este não é o único meio de melhorar sua qualidade final.

A partir deste artigo focaremos um pouco menos em temas humanos e começaremos a apresentar algumas ferramentas e técnicas que vão ajudar muito na hora de melhorar e manter a qualidade do código do seu time.

Organização de repositório

Sempre pensamos em fazer um código legível, fácil de manter e simples de entender, porém, para alcançar estes objetivos, muitos programadores esquecem que a organização do repositório que contém este código é essencial para que o código em si esteja organizado.

Precisamos manter um ambiente organizado para que não só nossos colegas, mas também nós mesmos possamos encontrar o que estamos procurando de forma fácil e eficaz. Uma boa analogia é nosso espaço de trabalho, seja ele um escritório ou a sua própria casa.

Se você não mantem este local organizado, terá uma perda grande de eficiência quando for procurar alguma coisa ou então quando for se instalar para poder começar a trabalhar.

Imagine um escritório de contabilidade que utiliza arquivos físicos para armazenar informações de seus clientes. Se estes arquivos estão desorganizados, fora de ordem e sem nenhum critério, se qualquer colaborador precisar achar algum arquivo, poderá levar horas. A simples organização por nome e cliente pode poupar diversas horas de trabalho – um ato simples que dá um ganho impressionante.

Quando estamos falando de desenvolvimento de software não é diferente. Mantemos nosso código em um “arquivo” que é nosso repositório de versionamento – seja ele Git, Mercurial, SVN ou qualquer outro – é extremamente importante manter este local organizado para encontrarmos o que procuramos. Mas como podemos começar a fazer essa organização?

Branches

Não vou me aprofundar no que é um branch, se não este artigo ficará muito extenso, mas se você nunca ouviu falar deste conceito, dê uma olhada na documentação oficial do git sobre branches. Em suma, um branch é uma ramificação do seu código principal, como se você tivesse uma linha do tempo.

A cada commit de código você tem um novo registro nesta linha, o branch permite que façamos uma bifurcação e podemos começar o desenvolvimento de outra funcionalidade sem atrapalhar o desenvolvimento na linha principal. Claro, nem todo sistema de versionamento utiliza a nomenclatura de branches, mas todos têm algo que se assemelha a isso.

É uma boa prática consolidada na comunidade utilizar um branch diferente para cada funcionalidade nova ou alteração que é feita na base de código. Desenvolver o que está sendo desenvolvido nesta branch, totalmente à parte da linha inicial, e depois mesclar ambos juntos:

No exemplo anterior temos uma branch principal (geralmente chamada de master), na qual temos uma série de alterações já consolidadas. Essa é a branch que reflete o que está em produção

Quando precisamos desenvolver uma nova funcionalidade, criamos uma nova branch chamada de feature/<nome-da-funcionalidade> e aplicamos nossas alterações nela para, no final, mesclar tudo junto. Então nosso branch fará parte das funcionalidades já em produção.

As vantagens deste sistema são várias:

  • É possível isolar completamente uma funcionalidade em um branch enquanto outros trabalham em funcionalidades diferentes
  • Evita conflitos em arquivos na hora do desenvolvimento quando duas pessoas alteram o mesmo arquivo
  • Permite testar separadamente uma funcionalidade

Para nos auxiliar, ao longo dos anos, a comunidade de desenvolvedores criou um padrão chamado git-flow, que é um conjunto de regras de uso de branches e fluxos de desenvolvimento que se aplicam a, basicamente, qualquer sistema. Você pode dar uma olhada no cheatsheet desse padrão aqui.

Code Review

Utilizar branches para desenvolvimento nos dá uma outra facilidade, que são os chamados Code Reviews. Um Code Review, ou Revisão de Código, é um processo que se inicia quando uma solicitação de mesclagem (merge request ou pull request dependendo do sistema) é submetida juntamente com toda a descrição da alteração que foi feita para um sistema de gerenciamento de versões, por exemplo, o GitHub.

A partir daí a solicitação é analisada por outros colegas que vão procurar erros no código e testar a funcionalidade extensivamente para, no final, dar um “ok”, comentar sobre algo ou então solicitar alguma alteração, este é o que chamamos de, neste caso, Github Workflow:

Realizar esse tipo de fluxo é extremamente eficiente para o time porque permite que, como falamos no artigo anterior, o time trabalhe como um só, colocando várias cabeças para pensar e criticar uma solução. Muitas vezes outras soluções melhores aparecem em uma pull request através de um comentário de um colega ou de uma indagação sobre algo que você pode não ter pensado no momento.

O time tem total capacidade e liberdade de comentar o código linha por linha para entender melhor o que foi feito ali, sugerir alterações ou propor novas ideias:

Um dos grandes problemas que enfrentamos quando temos Code Reviews é o fato de que, muitas vezes, o time não irá, de fato, testar o código – dará somente uma olhada por cima e aprovará o que foi feito. Essa prática é altamente prejudicial, pois aumenta muito as chances de que um código errado seja enviado para produção.

É uma tarefa do time como um todo implantar a cultura de observar e tratar cada código como se fosse seu próprio.
Para maiores informações sobre Pull Requests e tratamentos de código pelo time, separei dois ótimos artigos do Training Center que iluminam bastante o caminho:

Padronizando Pull Requests

Outro grande problema que temos com Pull Requests é que, muitas vezes, as descrições não são muito amplas e não dizem muito sobre o que aquela alteração realizou. Alguns sistemas como o Github possuem os chamados templates.

Templates são arquivos que podem ser criados como modelos para que todas as novas Pull requests criadas já venham com este modelo preenchido em sua caixa de texto.

Desta forma a pessoa que estiver criando a Pull Request se adequará ao modelo e, com o tempo, todas as Pull Requests serão padronizadas com um mesmo texto. Veja mais sobre templates na documentação do Github. Se você usa o Gitlab veja a documentação de description templates.

Um bom template contém, no início, um checklist de todas as coisas que a pessoa deveria lembrar e marcar antes de submeter para revisão. Após isto, uma descrição do problema, como ele foi resolvido, os passos para testar essa resolução e o resultado esperado deste teste, como no modelo a seguir:

Lembrando que este modelo não é obrigatório. Cada time pode criar um de acordo com suas necessidades.

Versões, releases e changelogs

Desenvolvimento de software é geralmente separado em ciclos de releases. Uma release é uma versão funcional do software que contém novas funcionalidades e/ou correções em relação a versão anterior.

Também é uma boa prática que está, inclusive, descrita e explicada no Git-Flow que comentamos antes: incluir tags nos commits. Uma tag é uma identificação que aponta para um commit específico, dando um nome ao mesmo. Você pode saber mais sobre tags aqui.

Todo o ponto de tags, releases e tudo mais, é justamente agrupar tudo o que foi feito em um único lugar e dizer: “Este pacote é a versão X.Y.Z que contém tais alterações”. Isso facilita muito o processo de publicação e faz com que o time tenha que verificar tudo o que está sendo lançado.

Outra boa prática – que também está no Git-Flow – é a criação de uma branch somente para releases, então todos podem clonar essa branch e testar exatamente o que deverá ir para a produção. Isso diminui drasticamente a quantidade de erros propagados.

O grande problema é que, muitas vezes, as releases são feitas sem ter nenhum tipo de descrição sobre elas. É ai que entram os changelogs.

Changelogs são descrições de tudo o que mudou entre a versão anterior e a versão atual, e podem ser incluídos na descrição da release que foi feita.

Eles ajudam o time a saber exatamente o que foi feito, onde está e quem fez a alteração de forma que qualquer erro possa ser mitigado de maneira muito mais simples, pois uma vez que se sabe o código que foi escrito para introduzir o erro, é muito mais fácil corrigi-lo e, quando temos um local que diz aonde todos estes códigos estão, fazemos isso de forma muito mais eficiente.

É como no nosso exemplo anterior. Ao invés de termos que procurar em todos os arquivos por um cliente problemático, já sabemos que o nome deste cliente começa, por exemplo, com a letra K e ele trabalha para a empresa XPTO Company que deve estar nos clientes com a letra X, então podemos achar todas as informações em uma fração do tempo do que se tivéssemos que procurar em todos os arquivos.

Não há uma convenção sobre como changelogs devem ser escritos. Eu, pessoalmente, gosto da divisão em: bugs, features/funcionalidades e melhorias. Tudo isso identificado por um ícone característico que pode ser escolhido pelo time.

As informações devem ser divididas em pontos com descrições curtas, pois as descrições mais longas estarão dentro das Pull Requests através de templates, conforme mostramos antes, e entre parênteses um link para a Pull Request que contém essa alteração.

Se a alteração está distribuída em vários repositórios, por exemplo, um sistema baseado em microsserviços que precisou de alterações em três componentes para a implementação de um botão de notificações, então os links para as Pull Requests em todos os três repositórios devem estar descritos, juntamente com os nomes destes repositórios se a Pull Request é no próprio repositório do sistema do Github. No caso, sugerirá a inclusão ao se digitar # na caixa de texto. Veja um exemplo:

Milestones

Milestones – ou marcos, em português – são agrupadores presentes na maioria dos sistemas de controle de versão gerenciados – como o GitHub e o GitLab. Com eles podemos criar um grupo que será, por exemplo, o número de uma versão e agrupar todas as Pull Requests e issues dentro dele.

A grande vantagem é que podemos definir uma data de finalização para este Milestone, o que funciona muito bem com as metodologias ágeis que vamos cobrir nos próximos artigos. Desta forma, é possível não só saber a data de publicação de uma release, mas também o que estava dentro dela e como ela foi chamada:

O Milestone é um adendo ao changelog e também permite uma melhor gerência do que foi feito até agora. Se você quer saber um pouco mais sobre eles, a documentação do GitHub possui uma página sobre Milestones.

Conclusão

Aqui vimos um pouco mais sobre ferramentas e técnicas de organização de repositórios. Tudo isso pode parecer irrisório, mas se aplicados corretamente e seguidos pelo time, resultam em um ganho extremo de performance e eficiência para o desenvolvimento, além de reduzir a quantidade de erros significativamente.

Nos próximos artigos abordaremos temas mais técnicos como testes, guias de estilo e também temas mais gerenciais como metodologias ágeis! Fiquem ligados para as próximas atualizações.

Até mais!