Padrões de commits - Como e por que?
Luiz Eduardo Cardozo
Posted on September 19, 2020
Se existe algo que programadores gostam (ou, ao menos deveriam gostar mais) são as chamadas “boas práticas”. Elas existem com a finalidade de padronizar o desenvolvimento, criando alguns padrões visuais que exigem menos esforço para se reconhecer do que se trata. Isso além de agilizar o desenvolvimento, também evita erros, aumentando a pouco falada “eficiência”.
Já foram criados padrões para nome de variáveis, nomes de funções, classes… Mas ainda existe um mundo caótico lá fora: as mensagens de commit do git.
Para não perder o costume, vamos a nossa historinha:
Faz alguns poucos meses onde eu e meu time estamos trabalhando em um e-commerce. Estavamos quase ficando sem prazo por conta de alguns imprevistos, então decidimos partir para o stop-the-line para agilizar o processo e isso não acabar se tornando um problema para a nossa fábrica.
Foram 3 dias de trabalho incessante: cerca de 7 programadores trabalhando em cima do mesmo código. Milhões de commits e várias branches abertas, para gerenciar os conflitos.
Por fim, terminamos o projeto bem antes do prazo previsto, com uma sobra de umas duas semanas, que destinamos a testes, antes do deploy final.
Faltando cerca de 3 dias para o lançamento, o Stakeholder do projeto me liga (eram umas 4 da manhã, ele tinha costume de fazer isso) me falando que “as fotos estavam repetidas no site.
Explicando melhor, na página de produto tinha um carrossel. Fazíamos um request à uma api externa, que nos retornava os dados do produto em questão. Por fim, dentro da resposta, possuíam as fotos que o produto deveria apresentar na página inicial. Esses links eram passados para o componente do carrossel.
Bom, o primeiro passo que tive foi lógico: ao final de cada turno, faço um “checklist” de requisitos do sistema, colocando a data. Vi que a última vez que testei o carrossel, foi a cerca de 5 dias antes. Então, fui ao github, e passei a ler todos os commits de cinco dias atrás, caçando algum santo que tenha feito uma modificação no carrossel. Infelizmente, os commits estavam uma bagunça, e eu me vi às 5:30 da manhã, abrindo cada um dos 500 commits feitos, um a um, e lendo os arquivos modificados…
(In)felizmente, não foi culpa nossa… Houve uma falta de sincronia nos serviços da API, e ela acabava fornecendo os dados errados. Coisa que pode ser resolvida com um simples “refresh” no sistema.
Esse fato me fez refletir bastante. Sou um fã assumido de Lean (o modelo de gestão, no caso) e tento aplicar em tudo o que posso. Os commits caóticos me fizeram desperdiçar tempo, e desperdício é o pecado número um do Lean.
Comecei então a bolar métodos de commits que fossem mais claros. Esses métodos têm sido desenvolvidos desde então. Hoje, irei contar um pouco dos meus aprendizados com commits, e como eles facilitam a vida de um tech-leader, ou qualquer desenvolvedor que lide com um equipe grande.
Tudo começa no desenvolvimento
Como você, caro leitor, provavelmente é programador, vamos começar pelo código!
Cada empresa tem a sua particularidade no uso do git: uma branch para cada programador, para cada fase, cada sprint, uma só branch de desenvolvimento, dar push na master...
Como utilizamos o Jira para nos organizar, na empresa onde sou tech-leader, implementei a regra de que cada item do Jira deve possuir uma branch só para ele, nomeada de acordo com o nome sugerido no Jira.
Vamos supor que estamos trabalhando no terceiro item do backlog, cujo o nome é PROJ-003. Então, você deverá dar push todo o seu código relativo a esse item do backlog nessa branch.
Porém, há um adendo: na organização, foco é o primeiro passo.
Faça commit APENAS de itens relativos à branch. Caso ache algum arquivo que precise de modificações, mas não é da alçada daquele item do backlog, não faça commit dessa modificação na branch que está trabalhando atualmente: ou abra uma nova, ou faça na branch correta, depois volte para a sua branch que estava trabalhando.
Isso evita o problema número um que tive com o e-commerce: se algo quebrar em algum ponto, facilmente poderemos rastrear se aquele arquivo foi, ou não, modificado: basta procurar na mensagem de commit.
Como eu devo organizar a minha mensagem?
Bom, existe n formas de se fazer isso. O importante é combinar com a sua equipe um padrão, para que se torne algo “homogêneo” e suficientemente informativo.
Em umas experiências anteriores, nosso chefe nos instruiu a realizar commit apenas após terminar todo o item do backlog. Isso reduz o número de commits, fato, mas aumenta a quantidade de itens commitados, o que é péssimo, já que você vai ter um trabalho bem grande quando for rastrear algum bug.
Em um trabalho posterior, a equipe chegou à conclusão de que o melhor era commitar a cada arquivo modificado, explicando as modificações no arquivo. Isso gera MUITOS problemas:
Quantidade enorme de commits: em caso de bug, só com ctrl + f para achar palavras chaves;
Texto de commit enorme: na hora do desespero, você dificilmente vai conseguir ler tudo;
Prejudica a produtividade: tanto para quem está codando, quanto para quem está tendo que ler os commits, às 5:30 da manhã, com um Stakeholder gritando no telefone;
Agilidade pouco importa no desenvolvimento, se você não tem precisão: Melhor um software bem feito, que uma manutenção rápida.
A maneira mais eficiente que conseguimos chegar de realizar os commits são baseadas em dois eventos:
Quando algo funcional novo foi adicionado;
Quando um bug é corrigido, ou uma funcionalidade foi refatorada
Isso porque: uma funcionalidade, dependendo da arquitetura do sistema, deve interagir com o restante do código. Possivelmente, essa nova funcionalidade pode acabar causando algum “unexpected behavior”. Citar cada funcionalidade nova nos commits, é citar cada ponto de interação do sistema, o que facilita o rastreio do causador do problema.
Já diziam os magos da programação: programar é a arte de gerar bug no código. Eles sempre irão ocorrer, não tem jeito. Eventualmente, a correção de um bug pode gerar um outro bug. Isso se você considerar que o sistema possui testes automatizados, se não, esse “pode gerar um outro bug” se torna um “certamente irá gerar vários outros bugs”, pois é extremamente difícil de manter um padrão de desenvolvimento, se não foi você quem começou ele.
Citar as correções feitas pode facilitar a rastrear algum bug que possa ter ocorrido durante a refatoração de alguma parte do código.
Quanto ao tamanho da mensagem, é relativo: dê preferência por mensagens curtas e objetivas, porém pouco genéricas. Isso ajuda a manter a produtividade durante o processo de escrever código e, é claro, ajuda quem vai ter que rastrear as modificações.
A primeira parte do commit é o motivo dele estar sendo feito. Para eu e minha equipe, temos apenas 5 motivos para isso: adição de algo novo (add), remoção de algo novo velho (remove), correção de um bug (bug-fix) e refatoração de algum código (refact).
Isso ajuda a, no momento que você ver a mensagem de commit, você já ter uma ideia do que houve ali, e se aquilo pode estar ou não integragindo com o seu problema.
A segunda parte é a mais complexa de todas: a mensagem.
A mensagem deve ser curta, no máximo 72 caracteres, e deve ser imperativa. Deve resumir as modificações e especificar o que foi feito e, principalmente, aonde foi feito.
Deve-se também ter cuidado para a mensagem não ficar redundante com a primeira parte. Não existe problemas em se repetir, mas lembre-se dos 72 caracteres. Palavras redundantes são desperdício de tempo e espaço.
Ex:
Mudanças no código - Errado. Vago de mais, que mudanças? Em que parte do código?
Refact: mudanças no código - Errado, porém melhor. Tá, a mudança foi um refatoramento, mas em que parte do código?
Refact: mudanças no componente de produtos - Errado, porém já diz bem mais. Já sabemos que foi um refatoramento, e que foi em um componente de produtos, mas qual foi esse componente?
Refact: mudanças no componente ProductCard - Errado, mas quase bom. Qual forams as mudanças?
Refact: troca do forEach por um map durante o preenchimento dos campos no componente ProductCard - Muito bom! Explica o que foi feito e aonde foi feito. O unico problema é que deveria ser menor…
Refact: forEach trocado por map para preencher campos no componente ProductCard - Perfeito! Pequeno e traz todas as informações necessárias!
Existem algumas ferramentas, como um lint para commits. Eu, particularmente, acho elas um pouco desnecessárias: a maioria te força a usar um idioma e acaba tirando um pouco da sua produtividade. Gosto mais que meu time seja livre, mas tenha conhecimento dos benefícios que seguir um padrão pode trazer.
Esse foi o post hoje e, provavelmente, semana que vem irá sair mais uma parte da minha série de posts sobre testes automatizados. Estou ainda pesquisando materiais para tornar a segunda parte mais densa em conteúdos e, por conta disso, achei melhor postar algo mais “leve” hoje, para não ficarmos sem conteúdo.
Bons estudos a todos!
Luiz Eduardo Cardozo
Posted on September 19, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.