Pull/Merge Requests

Pull/Merge Request se destacou como um mecanismo importante junto ao controle de versão de código, principalmente na sinalização de mudanças. Ele também facilitou a revisão de código e o diálogo nos times. Seu uso permite também a aplicação de várias outras boas práticas que agregam valor. O tema destaca esta boas práticas e pontos de atenção para que o uso de Pull/Merge Request não se torne apenas uma etapa burocrática no processo.

O controle de versão de código fonte foi um grande passo para o trabalho colaborativo entre desenvolvedores(as) e para a organização na entrega de softwares. Mas no início houveram várias lacunas com relação a forma de trabalho e uso das ferramentas.

Ainda é comum, mesmo com o controle de versão, que times entreguem implementações sem que o código passe por uma verificação ou que haja uma sinalização a todos das alterações realizadas. Muitas vezes o controle de versão se restringe a comparação das modificações e a possibilidade de voltar para uma versão anterior do código caso ocorram problemas.

Como já apresentado no tema gerenciamento de projetos com código fonte, times de desenvolvimento precisam atualmente fazer mais do que apenas o controle de versão do código fonte de um software. Um dos itens inclusos no gerenciamento de um projeto é o uso de Pull/Merge Requests!

Um Pull/Merge Request é um mecanismo criado para sinalizar a outras pessoas que um trecho de código foi incluído e/ou modificado e que quem o desenvolveu deseja fazer o merge do mesmo nas ramificações principais do repositório.

Pull Request

O uso deste mecanismo ganhou força a partir do surgimento da ferramenta Git e de soluções de gerenciamento e hospedagem de repositórios. A popularização veio através da ferramenta GitHub, onde tal mecanismo se tornou parte central de um modelo de trabalho. Atualmente outras soluções famosas como GitLab e BitBucket, dentre outras, também trabalham em torno do uso de PRs, oferecendo recursos como:

  • Gatilho que sinaliza o desejo de um merge de código,
  • Execução automática de processos complementares.
  • Revisão do código de forma mais simplificada antes do merge.
  • Verificação de qualidade do código.
  • Registro do diálogo entre desenvolvedores(as) sobre partes específicas do código.
  • Uso de regras de validação e aprovação para permitir o merge do código.
  • Integrações com outras ferramentas.
  • Coleta de métricas para entendimento da cadência de times

Estas são algumas das vantagens no uso de Pull/Merge Requests, também conhecidos pela sigla PRs, a qual será usada no restante do tema.

Sendo o Git amplamente utilizado como a ferramenta de controle de versão para as soluções de hospedagens de repositório, e sendo tais ferramentas as que se destacam na disponibilização do mecanismo de PRs, a sequência do tema detalha a composição e as vantagens já citadas deste mecanismo, considerando o Git como ferramenta base para tal.

Composição

Um PR é composto por algumas informações básicas e obrigatórias, as quais orientam sobre a que se refere o desejo de merge. Abaixo elas são citadas junto a boas práticas:

  • Título: Um PR sempre possui um título, e embora muitas ferramentas sugiram um título, é importante garantir que ele seja autoexplicativo e focado em expressar o motivo ou resultado esperado com a mudança.
  • Branch origem: É a branch onde estão os commits com código modificado, podendo ser uma feature branch ou ainda branches permanentes do projeto.
  • Branch destino: É a branch na qual o merge será realizado, normalmente sendo uma branch permanente do projeto.
  • Status: Indica se o PR está aberto ou fechado, ou outros status de acordo com a ferramenta utilizada.
  • Autor: O usuário que solicitou o merge.

Além das informações obrigatórias em todas ferramentas que implementam o recurso de PRs, há também outras informações complementares que podem variar de acordo com a ferramenta, são algumas:

  • Número de aprovações: Indica que o merge só pode ser realizado caso ocorra o número de aprovações esperadas.
  • Lista de aprovadores: São os usuários sugeridos para a aprovação de um o PR.
  • Comentários: Representam o diálogo entre desenvolvedores(as) que comentam de forma geral ou direcionada a linhas específicas do código.
  • Labels: Uma forma genérica de organizar os PRs, podendo ser relacionadas a qualquer forma de agrupamento como: Prioridade, Status, Epics, Módulos, etc.
  • Milestone: Indica a versão planejada a qual o PRs será entregue.

Ainda há recursos como controle de estimativa e tempo gasto, restrições de visibilidade, controle de notificações, dentre outros.

As ferramentas evoluem constantemente as possibilidades relacionadas ao uso de PRs, isso inclui também a possibilidade de integração com ferramentas terceiras as quais podem oferecer informações e controles adicionais que auxiliam na composição de PRs.

Além de todos os recursos e informações citadas, há outra informação que serve como base para muitas outras possibilidades, ela é a descrição, a qual não é obrigatória, mas muito relevante e que é detalhada separadamente no subtópico a seguir.

Descrição

Todas as informações de um PR contribuem para um modelo colaborativo de trabalho entre desenvolvedores(as), mas a descrição de um PR é o ponto vital para isso.

Por ser um campo textual livre, ele permite que desenvolvedores(as) exercitem sua capacidade de descrever o que as linhas de código de fato representam. Tal informação pode ser usada para ir além das informações óbvias e expor as motivações de negócio que motivaram as mudanças no código.

É comum que ferramentas deem suporte ao formato Markdown, o que dá maior poder na composição da descrição. Na sequência segue algumas informações úteis que podem estar presentes na descrição.

☛ Detalhamento do problema

Todo código nasce para resolver um problema, e tal problema pode estar detalhado na descrição do PR para aqueles que revisarem as mudanças compreendam as motivações, além de servir como histórico.

O detalhamento pode estar descrito no próprio PR, ou o PR pode conter um link para tal detalhamento.

☛ Detalhamento da solução

Estando detalhado o problema, pode-se também detalhar a solução proposta, para aqueles que revisarem as mudanças compreendam “a intenção do código que foi implementado”.

É importante estar atento para que o código por si só, quando bem escrito, declare sua intenção. Sendo assim, detalhar a solução não é o mesmo que converter o código para uma forma descritiva, ou seja, repetir o que o código já mostra. Deve-se focar na visão de negócio ou na ideia mais ampla.

☛ Validação da implementação

Um PR pode também oferecer informações referentes a como validar que de fato a solução resolve o problema, para isso pode-se incluir:

  • Um passo-a-passo para execução da parte do software que foi modificada, sugerindo dados de entrada e resultado esperado.
  • Um checklist de questões a serem verificadas no review, como:
    • Uso de boas práticas no código.
    • Comunicações para o time ou outras áreas.
    • Atividades complementares.

Em geral, é válido qualquer informação que contribua para validar a qualidade da entrega e dos passos a serem executados para atualização do software.

Templates

Compor um PR com todos os dados citados no tópico anterior pode ser muitas vezes complexo. Para ajudar com essa tarefa muitas ferramentas possibilitam o uso de templates.

Os templates possuem a composição estrutural de um PR, desta forma ao criar um novo PR, o mesmo nascerá com o conteúdo existente no template e o criador do PR precisará apenas ajustar/complementar os dados relacionados ao seu PR.

Algumas ferramentas disponibilizam esse recurso através de telas de configuração no projeto na própria ferramenta, já outros permitem o uso de arquivos versionados junto ao código do projeto.

Relação com branches

Um PR está sempre associado a uma branch de origem e outra de destino, sendo normalmente a branch de origem uma feature branch e a destino uma branch permanente de acordo o fluxo de trabalho utilizado como develop, staging ou production, ou ainda branches relacionadas a uma milestone.

Trabalhar com PRs requer saber trabalhar com branches, isso porque durante o ciclo de vida de um PR pode ser necessário várias intervenções com relação a trazer implementações de uma branch permanente para a branch do PR, resolver conflitos da branch do PR com a branch de destino, dentre outros cenários.

Um primeiro passo é adotar o uso feature branches no fluxo de trabalho, isso permite o uso maximizado dos recursos de um PR. Uma feature branch pode ser criada antes mesmo do PR existir, sendo ideal que o PR seja criado apenas quando de fato deseja-se que os possíveis gatilhos configurados para integração contínua sejam disparados.

Entender a diferença entre criar uma feature branch, trabalhar nela, sincronizar com o repositório central e criar um PR somente quando necessário pode fazer diferença com relação ao consumo de recursos de ferramentas auxiliares, infraestrutura de Cloud para builds, testes, dentre outros. Em resumo, deve-se criar uma feature branch ao iniciar as implementações, e um PR somente quando for necessário iniciar o processo de CI para solicitar um merge. Pode-se ainda configurar a ferramenta de CI para não executar o pipeline sobre PRs que estejam como Drafts, uma opção disponibilizada em algumas ferramentas.

É importante também conhecer no uso do git a diferença entre merge e rebase. Conforme as implementações em uma feature branch avançam, pode ser necessário o uso de tais opções.

Um passo final, muitas vezes ignorado, é a exclusão da feature branch após o fechamento de um PR. Após o merge, não é necessário manter a branch de origem. Algumas ferramentas possibilitam a sinalização de que a branch de origem deve ser apagada com o merge do PR.

Verificações de qualidade

Uma das vantagens que o uso PRs oferece é tornar claro o ponto no processo onde um código com baixa qualidade não prosseguirá. Antes do merge, é possível executar as mais diversas verificações e validações sobre o código para que o mesmo receba um atestado de qualidade.

Algumas verificações são através da execução de comandos, onde o resultado é apresentado junto ao PR. Outras são através da integração com outras ferramentas as quais também apresentam o resultado junto ao PR. É possível ainda que algumas verificações sejam apenas um checklist que precise manualmente ser verificado e marcado como ok para que o PR seja aprovado para o merge.

Na sequência o tema detalha melhor tais verificações.

Testes automatizados

Um código fonte bem estruturado e maduro normalmente possui um conjunto de testes automatizados que garantem a consistência do código a cada alteração. Estes podem ser executados via ferramenta de CI para validar o PR e permitir o merge.

Os testes devem gerar um relatório o qual pode ser visto a partir do PR. Deve-se também apresentar o resultado de cobertura dos testes. Com essas informações, sempre que houver uma quebra de testes ou diminuição da cobertura, pode-se impedir que o PR seja aprovado.

Sugere-se que estejam atrelados ao PR a execução de testes unitários, de componente e de integração caso este esteja no domínio/escopo do projeto do PR. Testes integrados executados de forma desvinculada do projeto e que influenciam no PR podem comprometer a cadência do time.

A execução de testes automatizados junto ao PR não substitui a necessidade da execução local dos testes, isso porque rodar os testes para um PR normalmente demanda o uso de recursos da infraestrutura ou de ferramentas, o que pode elevar o custo do projeto. Recomenda-se sempre a execução dos testes localmente e não havendo problemas, abrir então um PR, onde os testes servirão como barreira de garantia.

Análise estática de código

Muitas verificações relacionadas a forma como o código está escrito e formatado atualmente podem ser validados através de ferramentas de análise estática. Tais validações contribuem para que desenvolvedores(as) não precisem gastar tempo analisando questões que podem ser automatizadas.

Desta forma indica-se que todas ferramentas adotadas em um projeto sejam executadas junto ao PR para garantir que o mesmo está seguindo todas as convenções. Em caso de violações, pode-se impedir que o PR seja aprovado e/ou feito merge.

Abaixo, algumas verificações que podem ser executadas:

  • Formatação e estilo do código.
  • Complexidade do código.
  • Inconformidades com relação a tratamentos de erros.
  • Verificação de possíveis bugs.
  • Verificação de falhas de segurança.

Revisão de código

Revisar o código é uma das maiores vantagens que o PR oferece. É neste momento que os(as) demais desenvolvedores(as) poderão analisar a implementação e verificar se a mesma resolve o problema da melhor forma possível, se segue as práticas e convenções adotadas no projeto e se o código está legível e extensível.

A revisão de código, independente do uso de PRs, é um assunto extenso e por este motivo possui um tema próprio no guia. Mas ela possui uma relação muito próxima ao uso de PRs, e desta forma seguem algumas questões que envolve os dois temas:

☛ Tamanho do PR

Um PR deve focar em um único problema! Ou seja, não deve-se resolver no mesmo PR vários problemas.

Um PR com pouco código modificado!. Um PR com uma quantidade grande de código modificado normalmente torna a revisão mais difícil e/ou custosa. O tamanho ideal pode variar de acordo com a linguagem utilizada, necessidades de negócio, dentre outros. Algumas fontes recomendam um limite de 500 linhas, outras indicam limites de arquivos ou tempo máximo gasto na revisão.

Não há um número mágico, todos eles podem sofrer com exceções, desta forma é importante que o time entenda que os PRs devem ser pequenos para que sua revisão seja rápida e simples, porém o quão pequenos devem ser é uma escolha do time de acordo com cenário existente.

Sempre que um PR tentar resolver mais de um problema ou acumular muitas modificações de código, deve-se analisar e fazer a quebra em novos PRs.

☛ Revisar a parte criativa do código

Deve-se focar a atenção a verificar a lógica implementada com o código, se o mesmo atende as necessidades de negócio, se o algoritmo é o mais adequado para a situação, dentre outros.

Questões que podem ser avaliadas por ferramentas de análise estática não devem requerer tempo das pessoas para revisão.

☛ Entenda o motivo da modificação

Deve-se ler atentamente a descrição do PR para então verificar o código. Se na descrição não houver detalhamento suficiente, informe para o(a) autor(a) e cobre que o mesmo melhore o detalhamento. Embora isso pareça antipático, é relevante para que se estabeleça uma disciplina que implicará na qualidade do trabalho.

A revisão adequada do código só é possível se a pessoa tiver informações corretas e entender a motivação da modificação.

☛ Não iniciar revisão caso CI aponte problemas

Se as rotinas executadas de forma automatizada pela ferramenta de CI apontarem problemas, não deve-se gastar tempo revisando o código, mas sim solicitar para o(a) autor(a) a correção e resolução dos problemas para que então aplique-se o tempo necessário para a revisão. Quando problemas ocorrem, alterações no código provavelmente serão necessárias e a revisão, ou parte dela, poderá ter sido em vão.

Aprovações

Todos os pontos citados no tema até o momento levam desenvolvedores(as) a um desfecho que é: aprovar ou não aprovar um PR. Embora muitas vezes pareça duro com demais integrantes do projeto, é importante que o time leve a sério o momento da aprovação ou não da modificação.

Ter disciplina com relação a esta etapa é essencial para a qualidade do código a médio e longo prazo. Isso não representa que em momentos extremos não se possa ser maleável com relação a aprovação, mas casos assim devem ser exceção e debatidos no time para compreensão de todos.

A aprovação de um PR é o resultado de todas as verificações de qualidade já citadas. Quando todas elas estão adequadas, aprovar o código se torna algo simples. Já a aprovação de um PR sem critérios, faz com que esta etapa do processo se torne apenas uma etapa burocrática que não gera valor ao software e ao time.

Por outro lado, a reprovação de um PR quando algo não está de acordo, pode gerar alguns reflexos indesejáveis como:

  • Atrasos em entregas.
  • Desmotivação dos envolvidos.
  • Impasses com relação a conceitos.
  • E o pior deles, conflitos entre pessoas.

Tais reflexos, mesmo sendo negativos, não devem ser abraçados como pretextos para baixar a necessidade de qualidade, porém isso não representa que não deve-se ter tato e cuidado na forma de tratar tais situações. Tal questão é complexa e por este motivo é melhor detalhada no tópico a seguir.

Diálogo

Um PR proporciona um espaço para que times possam aprofundar o diálogo sobre questões técnicas, sendo este diálogo vital para que todas as práticas já citadas criem o efeito de colaboração.

Para haver diálogo, é essencial que o time fale! Isso pode ser realizado através de várias formas, e no contexto do uso de PRs o primeiro passo é compor um PR conforme itens sugeridos até aqui, explicitar dúvidas, críticas e sugestões, e não apenas tratar o uso de PRs como uma etapa obrigatória do processo.

Ao utilizar o mecanismo de PRs o diálogo surge em função da necessidade de explicar algo para as demais pessoas e entender o que é dito pelas mesmas. Desta forma os PRs passam a ser o local onde formalmente serão registrados as motivações das mudanças, os comentários sobre os detalhes de implementação, o aprendizado e repasse de conhecimento sobre a composição do código e boas práticas de engenharia de software.

Como em qualquer diálogo, é importante saber se expressar e saber ouvir. No dia a dia haverá momentos onde as demais pessoas não compreenderão o PR, o que forçará o(a) autor(a) a detalhar mais a descrição, exemplificando melhor os cenários, organizando melhor o texto. Em outros momentos os comentários das demais pessoas podem não ser bem compreendidos, o que também os forçará a ter o mesmo cuidado com a escrita e detalhamento.

O diálogo, para ser colaborativo, precisa vir acompanhado de respeito, empatia e paciência. Tal diálogo deve estender os limites de um PR, e as conversas podem ser realizadas diretamente entre as pessoas quando necessário, ficando o PR apenas como uma fonte de registro da informação relevante.

Comentários

A construção do diálogo passa pela realização de comentários em um PR.

Todo PR deve ser criado com uma descrição bem elaborada, esse é o inicio do diálogo, vindo na sequência os comentários sobre o código, lógica utilizada, conceitos envolvidos, questões de negócio, dentre outros assuntos. Tais comentários podem ser construtivos ou apenas depreciativos e eles influenciam diretamente no tom e resultado do diálogo.

☛ Comentários construtivos

São aqueles que alertam sobre algo na implementação mas que apresentam e fundamentam o porquê de tal alerta e principalmente propõem formas para tratar a situação exposta.

Em um comentário construtivo o foco sempre é a implementação e nunca a pessoa que implementou. Não deve haver julgamentos com relação ao motivo da implementação ter sido feita de forma A ou B, mas sim o alerta da consequência com relação a implementação e o debate sobre como evitar tal consequência.

Um comentário pode ser realizado também para destacar uma implementação bem realizada, que sirva de exemplo e aprendizado para outras pessoas.

☛ Comentários depreciativos

São aqueles que focam na crítica da implementação, e que não propõe formas mais adequadas para resolução.

Tais comentários podem atingir o objetivo de modificação do código, mas normalmente não contribuem na construção do diálogo, isso porque eles podem gerar desmotivação do(a) autor(a) e demais envolvidos(as), além da possibilidade de geração de atrito além dos limites do PR.

Em muitas situações, ao verificar implementações que fogem da qualidade esperada, ou que até não resolvem o problema expressado no PR, é comum haver uma reação inicial de criticar e apontar os problemas. De fato isso é necessário para manter a já citada qualidade do software, mas deve ser feito de forma respeitosa e empática, buscando-se compreender os motivadores do(a) autor(a). Tal postura ajuda com que um comentário depreciativo possa ser transformado em um comentário construtivo.

Todos comentários relevantes devem estar registrados no PR, porém as situações motivadoras de tais comentários podem ser debatidas diretamente com o(a) autor(a). Isso pode ser feito pessoalmente com uma ida à mesa da pessoa, ou através de uma conversa por chat, telefone, vídeo conferência, etc. O importante é que os comentários não se tornem longos debates a ponto de perderem o foco da implementação em questão e que o PR fique poluído com comentários fora de contexto.

Aprendizado

PRs proporcionam a oportunidade de aprender com a prática, ou seja, atuando diretamente sobre as implementações reais do dia a dia.

A forma mais direta de aprender com PRs é revisá-los! Através da revisão desenvolvedores(as) podem ver cada detalhe sobre a forma de programar das demais pessoas do projeto, podendo observar coisas como:

  • A forma como o código é escrito.
  • As boas práticas aplicadas na implementação.
  • Os algoritmos e lógicas utilizados para resolver o problema.
  • O uso dos recursos nativos e/ou avançados da linguagem.
  • O uso de bibliotecas utilitárias.
  • Utilização de padrões de projeto e arquiteturais.

Ao revisar PRs, pode-se aproveitar o momento para pedir mais explicações sobre um conceito ou uma prática aplicada. Pode-se ainda pedir referências para um aprofundamento posterior no assunto, como um artigo, livro, treinamento.

Sendo uma fonte de conteúdo prática, desenvolvedores(as) podem ir além e também aprender com PRs já concluídos, mesmo que não tenham participado de sua revisão.

Repasse de conhecimento

Há muitas formas de repassar conhecimento, e um PR, embora não seja uma forma formal e totalmente estruturada, certamente contribui para o repasse.

Um conhecimento o qual é repassado de forma implícita é a própria implementação realizada, ou seja, o código bem implementado já serve como base de conhecimento para as demais pessoas.

Além disso, os comentários em um PR podem ser úteis para que nos casos práticos sejam apresentados conceitos ou outras informações que contribuam para o aprofundamento de conhecimento das demais pessoas. Isso pode ser feito através dos comentários construtivos ou mesmo apenas com a citação de partes de uma implementação que demonstrem uma forma adequada de codificar e resolver problemas.

Em tais comentários pode-se:

  • Marcar pessoas para que analisem a implementação adequada.
  • Citar brevemente as vantagens que uma implementação irá oferecer.
  • Fazer o link a conteúdos externos que permitam um aprofundamento do conhecimento.
  • Reunir as pessoas e debater situações encontradas em PRs, tanto as desejáveis quanto as passíveis de melhorias.

O repasse de conhecimento é uma das melhores estratégias para amadurecimento dos times e melhorias na qualidade de um software, e os PRs podem ser utilizados como parte desta estratégia.



Pull/Merge Requests ganharam relevância em um processo moderno de desenvolvimento de software, sendo muitas vezes o centro para várias outras ações realizadas pelos times.

Compreender suas vantagens e os pontos de atenção faz com que esse mecanismo não se torne apenas mais uma etapa burocrática realizada por imposição, mas sim seja uma etapa que gere valor real para o software e para o time.

Histórico