Segundo Birrell (1988), o desenvolvimento de software vem amadurecendo bastante nos últimos anos. Temos sistemas mais robustos, linguagens modernas para atender as necessidades de milhões de usuários acessando a mesma aplicação e tudo isso deve ser feito com rapidez e qualidade. Juntar essas duas características não é fácil. Acabamos nos deparando com algo conhecido no mundo da tecnologia: Qualidade x Preço x Prazo.
Ainda de acordo com Birrell (1988), toda a empresa de desenvolvimento de software já tem alguma metodologia para construir software. Mas apesar disso, enquanto alguns sistemas são desenvolvidos de acordo com práticas modernas do desenvolvimento de software, a maioria ainda trabalha de forma arcaica. Podemos falar então sobre técnicas e metodologias para desenvolvimento de sistemas em termos de melhorar as práticas atuais, substituindo-as com novas técnicas que melhorem o processo de desenvolvimento de software e a qualidade do produto gerado.
Observando esse cenário, temos que pensar em como gerenciar nosso software. Isso envolve gerenciarmos várias etapas do processo, como: requisitos do sistema, arquitetura, padrões de codificação, gerência de configuração, deploy etc. São diversos passos para administramos até o produto final estar concluído e, além disso, o software está em constante mudança. De acordo com Roger S. Pressman (2011), o moderno ambiente dos sistemas e produtos da área é acelerado e está em constante mudança. Então, como vamos controlar tudo isso?
O Gitflow que é um framework criado para trabalhar em conjunto com o sistema de controle de versão Git e pode nos ajudar a melhorar a organização de duas áreas: a gerencia de configuração e a gerencia de projetos. Para que tudo isso funcione, é necessário adequar os processos de gerência de configuração, entrega contínua e gerência de projetos do fluxo de desenvolvimento para acomodar a nova ferramenta.
Workflows (fluxos de trabalho)
Para melhorarmos a forma como utilizamos os controles de versão, podemos escolher alguns fluxos de trabalho para ajudar na organização do processo de desenvolvimento de software. De acordo com Yan Pritzker (2009), existem diversos tipos de workflows diferentes que podemos utilizar com os DVCSs. Vamos conhecer alguns deles.
Centralized Workflow: Esse fluxo se assemelha muito a quem já está acostumado a trabalhar com VCSscentralizados. Como o SVN, ele utiliza um servidor central como repositório que serve como um ponto único para mudanças e ele tem uma linha chamada master. Esse tipo de fluxo não precisa de nenhum outro branch, a não ser o master. O problema desse fluxo é a grande possibilidade de existir conflitos constantes.
Feature Branch Workflow: É extremamente parecido com o workflow anterior; a diferença é que nesse podemos ter diversos branches para criação de novas funcionalidades. Os desenvolvedores devem criar um branch para cada funcionalidade nova no projeto, além disso, o nome do branch deve ser bem descritivos. A grande vantagem desse tipo de fluxo é que podemos fazer uma estratégia de revisão de código através de Pull Requests (PR). Os PR são muito utilizados em projetos de código aberto, onde nem todo mundo tem permissão de comitar no repositório; mas através de um PR, ele pode modificar o código e enviar uma sugestão ou correção para ser analisada. Se a proposta for aprovada, é feito o merge com o repositório central. Uma grande empresa que utiliza esse fluxo é o Github (GitHubFlow).
Forked Workflow: Esse fluxo é totalmente diferente dos outros citados até agora. Ao invés de termos um repositório central em um servidor, cada desenvolvedor terá um repositório que será seu servidor. Como nos outros fluxos de trabalho, esse fluxo começa com um repositório público oficial armazenado em um servidor. Mas quando um novo desenvolvedor quer começar a trabalhar no projeto, eles não clonam diretamente do repositório oficial. Ao invés disso, eles fazem um fork do repositório oficial e criam uma cópia no servidor. Esta nova cópia serve como seu repositório público pessoal, outros desenvolvedores não têm permissão para comitar nele, mas eles podem receber as mudanças a feitas nele (vamos ver por que isso é importante em um próximo momento). Depois de ter criado a sua cópia do no servidor, o desenvolvedor faz um clone para obter uma cópia do seu repositório em sua máquina local. Isto serve como seu ambiente de desenvolvimento privado.
Gitflow
Como afirma Vincent Driessen (2010), o Gitflow foi criado em 2010 e considerado um ótimo modelo de branching. Para entendermos melhor, um branch é uma ramificação da árvore principal do seu código; por exemplo, para quem trabalha com SVN existe o trunk e o branch. Já para quem utiliza GIT, tudo é branches, mas por convenção, novos branches são criados a partir do master, que seria a raiz do seu código.
Driessen (2010) afirma que o Gitflow é um modelo fortemente baseado em branches, mas focados em entregas de projetos. Apesar dele ser um pouco mais complexo que outros workflows, ele disponibiliza um framework robusto para gerenciar projetos mais complexos ou de grande porte.
Esse workflow não traz nenhum conceito novo para o Git, ele define os papéis de cada branch e como eles devem interagir. Mas como tudo isso funciona? O Gitflow ainda utiliza um repositório centralizado (lembrando que ele é um DVCS) como o centro de comunicação entre todos os desenvolvedores. Observem a Figura 01:
Historic Branches: Ao invés de trabalhar apenas com o branch master, esse workflow utiliza dois branches principais para guardar histórico do projeto. O branch master guarda o histórico oficial das entregas, já o branch develop serve como integração entre todos os branches de funcionalidades (feature branches).
Feature Branches: Cada funcionalidade deve ter seu próprio branch, e ele deve ser criado a partir do branch develop. Quando uma funcionalidade for concluída, ela é mesclada (merged) novamente com o seu branch pai. As features nunca devem interagir diretamente com o master.
Release Branches: Quando o branch develop estiver com funcionalidades suficientes para uma entrega, nós criamos um branch de entrega (release branch). Com isso, nós damos início ao próximo ciclo de entrega, ou seja, nenhuma nova funcionalidade pode ser incluída a partir desse momento. Quando estivermos prontos para realizar a entrega, o release é mesclada com os branches master e develop.
Maintenance Branches: Também conhecidos como hotfix. Eles são usados para corrigir rapidamente algum problema em produção. Este é o único branch que deve ser criado a partir do master. Assim que a correção for finalizada, o branch é fechado e mesclado com o master e develop, mantendo assim as linhas completamente atualizadas.
Basicamente, esses conceitos são o suficiente para entendermos o fluxo básico sobre o Gitflow, mas ainda temos um desafio pela frente: como implantá-lo em sua empresa ou projeto?
Estudo de caso
A empresa em questão atua na área de tecnologia da informação e está situada em João Pessoa, Paraíba. A empresa possui diversos produtos com foco em ajudar e melhorar os processos do setor público brasileiro através de sistemas de gerenciamento da informação. Por exemplo, um dos produtos propõe a desburocratização do processo de abertura de empresas, que graças a organização pode ser feito pelo empresário diretamente pela Internet e sem demora.
O cenário antes da implantação do VCS Git na empresa era um pouco caótico. Havia um servidor central com os projetos em SVN, o deploy não era feito de forma automática, ou seja, a equipe responsável por colocar o código em produção deveria autenticarse nos servidores e fazer isso com comandos do SVN. Apesar disso, tínhamos duas linhas de produção, chamadas de trunk e branch. A linha trunk representava o produto que estava em produção. Já a linha branch eram as novas funcionalidades que iriam para produção quando estivessem prontas.
Podemos ver que esse modelo dificultava que tivéssemos mais linhas de novas funcionalidades (mais de um branch), uma vez que manter apenas uma já era extremamente complicado – devido à quantidade enorme de conflitos que ocorriam no código ao mesclar com o trunk. Outra coisa importante era que os erros (bugs) encontrados no sistema no trunk nunca desciam para o branch, distanciando as duas linhas.
Após analisarmos esse cenário, vimos que poderíamos aumentar nossa produtividade, controle e qualidade de código se migrássemos para o GIT, mas para fazer isso precisávamos de um plano de ação. Esse plano foi composto pelos setores de Negócio, Gerência e Arquitetura. Chegamos a uma conclusão e criamos um passo a passo do que deveria ser feito e claro quanto tempo seria necessário para executar cada tarefa.
O projeto foi iniciado em maio de 2014 e foi feito para ser finalizado em 02 meses, por tanto precisávamos organizar as tarefas dentro desse cronograma. A preparação dos ambientes seria a primeira tarefa a ser executada e teve duração de 03 semanas. Após isso, a migração dos projetos do SVN para o GIT deveria ser feita – essa tarefa exigiu 03 semanas de trabalho. Em paralelo a essa tarefa, nós efetuamos a migração dos hooks do SVN para o GIT e também foi feita a integração com o bug tracker mantis. A última etapa do projeto foi a adequação das ferramentas de deploy para o novo VCS e foi finalizada em uma semana.
Preparando o ambiente
Primeiramente, montamos um servidor específico para o GIT. O servidor deveria ser robusto o suficiente para aguentar mais de 200 commits por dia, já que essa era nossa média. Como interface gráfica do servidor do GIT, escolhemos uma plataforma de código aberto chamada GitLab, que é responsável por facilitar o gerenciamento do VCS. Com tudo isso montado, nós poderíamos botar em prática a segunda etapa do projeto.
Migrando para o GIT
Na segunda fase, precisávamos migrar todos os projetos do antigo SVN para o GIT. Isso parece uma tarefa relativamente fácil, mas existiam alguns problemas. O primeiro deles era que em 2 projetos nós deveríamos manter a sincronia entre o SVN e GIT, pois não podíamos parar os desenvolvedores por mais de quatro dias para migrá-los. Por essa razão, precisávamos encontrar uma estratégia de sincronia de VCS e essa foi uma das etapas mais críticas do projeto, pois tínhamos que manter os repositórios funcionando e com seu histórico intacto. Após diversas pesquisas, encontramos uma empresa especializada em GIT e ela disponibilizou um artigo público que ajuda na criação dessa sincronia entre os diferentes VCSs.
É possível fazermos a sincronia em duas direções SVN para o GIT e GIT para SVN. Nós optamos fazer apenas uma via, onde os programadores devem apenas comitar para o repositório SVN e não para o GIT. Quando você estiver confiante que o seu time está pronto para fazer a troca, podemos finalizar a migração e começar a comitar diretamente para o Git.
Durante a migração, cerca de 4 projetos perderam o seu histórico, isso foi causado pela incompatibilidade das mensagens e dos autores dos commits com o formato do GIT e também pelo tamanho dos projetos, que poderiam ser superiores a 30 GB (contando com o histórico).
Com a migração dos projetos concluída, só restaram migrar os dois últimos, mas ainda encontramos um outro problema. Nós temos alguns servidores nos quais podemos colocar as linhas de produção, no geral são quatro. O servidor de produção é onde fica o código da linha master e onde o sistema está disponível para o cliente final. Também temos os servidores de demonstração, que servem para mostrar novas funcionalidades dos produtos antes de irem para o ar. Os servidores de homologação servem para homologarmos as novas funcionalidades (isso normalmente é feito pelas equipes de qualidade e donos do produto). E ainda temos os servidores de desenvolvimento que tem o propósito de disponibilizar um ambiente para os desenvolvedores testarem seu código em sua fase inicial. Nós conseguimos migrar rapidamente todos os servidores menos o de produção, pois ele não podia ser migrado sem subir as novas funcionalidades que já estavam em desenvolvimento. Dessa forma, observamos que a linha de produção master no GIT estava congelada e os desenvolvedores só podiam comitar no trunk do SVN (que era sincronizado com o master automaticamente), todas as outras linhas do Gitflow já estavam implementadas e rodando em todos os servidores e com sprints (expressão utilizada pela metodologia SCRUM) em andamento. Quando tivemos a aprovação da gerência e infraestrutura, nós efetuamos a migração do servidor de produção para o GIT e partir desse momento todas as equipes começaram a trabalhar com o Gitflow completo.
Integrando o Git
A terceira etapa do projeto constava em alterar os hooks do GIT para realizarmos integrações e validações. Os hooks são responsáveis por executar comandos automaticamente a partir de um evento que ocorra no VCS. Nós utilizávamos três hooks no SVN e precisávamos convertelos para o GIT. Os hooks eram os commitmsg , precommit e postupdate.
O commitmsg é o hook responsável por padronizar o formato que os desenvolvedores escrevem as mensagens dos commits. O precommit verifica se existem erros de sintaxe nos arquivos comitados, e se não existem configurações de debug ativadas. E o hook postupdate é responsável em atrelar os commits com casos da nossa ferramenta de bugtracker (rastreador de erros). Essa foi a etapa mais simples e rápida do projeto, pois tivemos que fazer poucas alterações nos hooks que são escritos em Shell Script.
Deploy
A última etapa do projeto era talvez a mais desafiadora: deveríamos implantar a automatização do deploy, fazendo integração com o bugtracker. Para fazermos isso teríamos que alterar a cultura da empresa, mudando a forma como o fluxo é feito. Fizemos diversas pesquisas até chegarmos em algumas ferramentas de Integração Contínua e Entrega Contínua. Para Integração Contínua, nós utilizamos uma ferramenta chamada Jenkins, que é responsável por executar os testes unitários, de estresse e de carga na aplicação. A ferramenta também pode encarregar-se de fazer o deploy automático a partir de pipelines – nós ainda não adotamos essa abordagem, apesar de estar caminhando para isso. Atualmente, fazemos o deploy integrado ao bugtracker Mantis , onde criamos botões para publicação de cada caso em seu ambiente correto. Para isso, funcionar corretamente nós utilizamos a ferramenta Fabric que é escrita em Python.
Durante a execução do projeto, a equipe de arquitetura preparou diversos treinamentos para o Git e Gitflow que foram ministrados para as equipes de desenvolvimento, qualidade, gerencia e suporte, mostrando as vantagens da utilização desse novo fluxo de desenvolvimento. Com essa conscientização foi mais simples de quebrar as resistências das equipes.
Considerações finais
Esse artigo nos mostrou os diferentes tipos de VCSs que podemos escolher, além explicar vários fluxos de trabalho para utilizarmos em nossos projetos. Ainda mostramos como podemos utilizar o Gitflow em nosso dia-a-dia e qual o processo para implantá-lo.
Porém, é importante ressaltar que existem contextos diferentes, por tanto, antes de tentar implantá-lo faça um estudo aprofundado com análises técnicas mostrando as vantagens e desvantagens de sua utilização.
O resultado após a implantação do gitflow na empresa do estudo de caso foi ótimo. Tivemos um grande ganho de produtividade e organização. O fluxo de trabalho nos ajudou a melhorar a dinamização das equipes de desenvolvimento, fazer entregas de valor de negócio para o cliente mais constantes, além de facilitar o acompanhamento de branches e deploy .
Espero que tenham gostado! Essa foi uma parte do meu TCC em Engenharia de Software e quis compartilhar com vocês como foi o processo de implantação dessa metodologia.