Gerenciamento de código e compartilhamento de conhecimento em equipes de desenvolvimento ágil

Bruno Melo
Aug 28, 2017 · 8 min read

Uma breve história sobre controle de versão e colaboração.

Pré-história

Em tempos remotos da humanidade, quando os primeiros desenvolvedores tentavam se adaptar a um meio ambiente digital de extrema vulnerabilidade e munidos apenas de poucas tecnologias, toda a gestão de arquivos era feita de forma manual.

A organização destes arquivos dependia muito da lógica que a equipe, ou mesmo o próprio desenvolvedor, decidia utilizar. Variando as estratégias e sem uma metodologia padrão para criar seu sistema de arquivos. Gerenciando as versões (se é que podemos definir isto como gestão) baseado em algumas pastas. Tudo de forma manual e muito trabalhosa.

Este modelo se tornou obsoleto por trazer uma carga de complexidade enorme entregando pouca ou nenhuma eficiência. Tornando a gestão de projetos de software uma saga infernal.

Evoluindo para o controle de versão Centralizado

Confrontados com a problemática de gerir seus entregáveis, tecnologias foram desenvolvidas para facilitar e adicionar uma camada de controle e histórico para os projetos.

Com este formato já era possível controlar vários arquivos ao mesmo tempo. Ferramentas como SVN, TFS são as mais utilizadas para esta estratégia que centraliza todo o código gerido em apenas um servidor.

Neste fluxo somos obrigados resolver todos os conflitos localmente antes de integrar o código com o servidor do repositório para cada commit.

A necessidade de resolver os conflitos, adicionado a um servidor único, gera lentidão e constate retrabalho sempre que um integrante da equipe insere suas modificações no código base. Pois todos são obrigados a atualizar suas versões locais, resolver os conflitos quando houverem, para que possam efetivamente integrar seus commits ao repositório oficial. Tornando o fluxo de trabalho um pouco "travado".

Apesar dos sensíveis ganhos com esta abordagem, encontramos alguns problemas de integração que são vivenciados diariamente.

Controle de Versão distribuído

Com a chegada de tecnologias como GIT e Mercurial, foram desenvolvidos novos paradigmas para a gestão de projetos de software.

Em uma abordagem descentralizada conseguimos gerir várias alterações. Ampliando o poder e o desacoplamento das modificações.

O fluxo de conflitos foi invertido. Com esta abordagem nós conseguimos seguir o fluxo localmente sem problemas, inserindo commits, deixando os conflitos para o momento da integração com o servidor central.

Outro ganho da distribuição é a existência de múltiplos hosts para o projeto. Facilitando com que todos possam trabalhar independentemente e integrando seus códigos pontualmente.

Mas para que este fluxo, mais atual, funcione com a confiabilidade e segurança que desejamos é necessário aplicar algumas práticas para que não entremos na saga infernal do controle de versão.

Referência: http://ericsink.com/vcbe/html/history_of_version_control.html

Comparando Fluxos para controle de versão

Duas abordagens básicas para times ágeis utilizando GIT como controle de versão.

Feature Branch Workflow

A ideia central é que todas as features devem ser implementadas em uma branch dedicada a alteração em questão, e então integrada a branch principal (master). Esse encapsulamento facilita a contribuição de diversos contribuidores trabalharem em paralelo sem interferir no código base. Isto significa que a branch master nunca conterá códigos quebrado, o que é uma grande vantagem para a integração contínua.

Encapsular suas modificações em uma branch possibilita a vantagem de criar Pull Requests. Esta ação possibilita iniciar discussões sobre a implementação, compartilhar conhecimento, manter padrões, sugerir melhorias, etc.

Neste fluxo ainda temos um repositório central e mantemos uma branch principal (master) para refletir nosso histórico. Mas em vez de criar commits diretamente na branch principal, nós criamos uma branch para a feature que estamos trabalhando com um nome descritivo como por exemplo animated-menu-itens, feature/authentication ou mesmo issue-#1012. A ideia é representar de forma clara e descritiva o propósito que estamos desenvolvendo em cada branch.

Feature branch é uma forma incrivelmente flexível para desenvolver projetos. O problema é, algumas vezes é flexível demais. Para times muito grandes é melhor definir uma metodologia com regras mais específicas.

Gitflow Workflow

Gitflow Workflow é similar aos outros modelos no que diz respeito a descentralização dos repositórios e os desenvolvedores conseguem trabalhar localmente subindo suas alterações para o repositório central. A principal diferença está na estrura de branches do projeto.

Gitflow — Historical Branches

Em vez de uma única branch (master), o fluxo usa duas branches principais para manter o histórico do projeto. A branch master mantém os releases oficiais, enquanto a branch develop serve como um ponto de integração para features. É convencionado que ao integrar as alterações da branch Develop na master sejam criadas tags com todos os commits contendo um número de versão.

O resto do fluxo orbita entre estas duas branches

Gitflow — Feature branches

Cada nova feature deve ser desenvolvida em sua própria branch. Elas devem ser criadas a partir da branch Develop, como sua branch pai.

Quando a feature estiver completa e chegarmos ao momento de integrar o nosso código, o Pull Request deve ser aberto para integrar com a branch develop, e nunca diretamente para a branch master.

Perceba que a feature branch combinada com develop branch de forma geral segue o fluxo feature branch. Mas quando falamos de Gitflow ele não para aqui.

Gitflow — Release Branch

Somente quando a branch develop conter features suficientes para a criação de um release. Você deverá criar um fork da branch develop para criar o release. Criar essa branch começa o ciclo de release, e a partir deste ponto não serão integradas novas features. Apenas correções de bugs, documentação e outras atividades relacionadas a release poderão ser adicionadas a branch release.

Com a release pronta para a entrega, ela será integrada a branch master e criamos uma tag com o número da versão. A release também deve ser integrada a develop, o que provavelmente deve ter progredido desde que o release foi criado.

Use uma branch dedicada a preparação da release para tornar isso possível que um time trabalhe na release corrente enquanto os outros times continuam a trabalhar nas features para a nova release.

Convenções:

  • branch off: develop
  • merge into: master
  • naming convention: release-* or release/*

Gitflow — Maintenance Branches

Branches de manutenção, ou "hotfix" são usadas para pequenas alterações em releases. Esta é a única branch que pode ser integrada diretamente a Master. Assim que a correção estiver disponível, a branch hotfix deve ser incorporada tanto a branch master quanto a branch develop, ou mesmo a feature corrente. A branch master, após receber a correção deve ser tagged com uma versão de atualização.

Seguir esse fluxo libera o seu time para continuar trabalhando em features sem interrupções.

Compartilhando Conhecimento no dia a dia Ágil

Estratégia de apoio a contribuição com foco em compartilhamento de conhecimento.

Pull Requests

Isolar features em branches torna possível discussões via Pull Request. Quando alguém conclui uma feature ele não deve integrar diretamente a Master. Em vez disso, ele enviam o sua feature branch para o repositório central, abre um Pull Request solicitando o merge de suas alterações para Master. Este é o momento que outros desenvolvedores podem compartilhar suas percepções a respeito do código, testar a feature e garantir que a integração ocorrerá sem problemas. Neste momento também podemos trocar experiências, discutir sobre possibilidades de melhorias, mitigar possíveis problemas e também contribuir para a feature em questão sempre que for conveniente.

Issue Tracking

Devemos manter os ambientes, tanto no Github (PR, commits e/ou issues), tanto no board (trello card) linkados. O github deve conter o link para o card ao qual estamos atendendo com as alterações propostas. Isso é possível com a criação de issues.

Também devemos manter link de nossos PR e/ou issues no Card referente a tarefa que estamos atendendo. Criando uma dupla ligação para que seja fácil a navegação entre ferramentas.

Revisão de Código (Code Reviews)

A revisão de código deve acontecer sempre que um PR é aberto. Em um mundo perfeito devemos ter o PR aceito por dois integrante da equipe, que efetivamente revisaram e testaram a branch em questão.

Este é o momento perfeito para entendermos o que foi implementado, discutir a respeito da implementação com o seus pares. Comentar e discutir as alterações propostas através de Pull Requests é uma excelente forma de entender as features que estão sendo inseridas no sistema/projeto.

Este também é o momento de discutirmos sobre a aderência do código aos padrões acordados, ou mesmo (re)definir padrões, assim como decisões arquiteturais.

Se você estiver trabalhando em par na feature em questão. É importante solicita a revisão de um novo par de olhos no código. Assim garantimos que estamos seguindo na direção correta além de receber um feedback de alguém de fora (da tarefa). O olhar apurado de alguém que não está "viciado" no código em questão é fundamental para ampliar a percepção da revisão.

Programação em Par ( Pair Programming)

Pessoalmente eu acredito na programação em par como uma das formas mais efetivas de contribuição e compartilhamento de conhecimento em equipes.

Com a programação em par conseguimos que o time trabalhe junto e integrado, criando, não só um ambiente de compartilhamento intenso, mas também integração entre a equipe.

Para efetivamente praticar a programação em par é necessário que o par sente junto para unir forças na implementação da mesma solução. Eles devem utilizar a mesma estação de trabalho, o mesmo monitor dividindo em a execução da tarefa em piloto e co-piloto.

O piloto, geralmente o mais experiente deve pilotar a máquina, enquanto o co-piloto acompanha a implementação do piloto com atenção para garantir que nada passou despercebido. O co-piloto tem a responsabilidade de identificar possíveis bugs, erros de lógica, e até padrão de código. Enquanto o co-piloto acompanha atentamente a implementação poderá tirar dúvidas e discutir com o piloto a melhor abordagem para a implementação da solução.

Também é indicado que os papeis sejam alternados de tempos em tempos, para que a visibilidade esteja equilibrada entre ambos.

Programação da Máfia (Mob Programming)

Nos últimos anos mob programming vem ganhando espaço na industria de software como prática de desenvolvimento e alternativa ao pair programming. Esta prática envolve reunir toda a equipe para a implementação de uma feature. Da mesma forma como acontece no pair, só que adicionando mais pessoas do time para o desenvolvimento da solução.

Testes

Testes podem servir como documentação do seu código. Além de manterem o seu código estável. Prefira especificações executáveis a documentos estáticos.

Documentação

Mantenha sua documentação simples o suficiente, mas não muito simples. Uma boa documentação é simples o suficiente para concluir o trabalho.

O ideal é que todos os projetos mantenham uma documentação necessária para executar o projeto no README.md da aplicação facilitando para que o desenvolvedor consiga executar o projeto.

Para documentações mais detalhadas é importante manter a wiki do projeto, no caso do Github, isto pode ser feito no próprio repositório, pois ele já prove as ferramentas necessárias para documentar seu projeto.

O histórico da branch principal de um repositório também pode fornecer informações importantes sobre a evolução e documentação do código contido. Sendo assim devemos ter zelo com nosso histórico o mantendo de forma atômica, facilitando a gestão do projeto.

Encontros, Dojo, Coffee/Beer Code

Para assuntos mais específicos e que provavelmente não façam parte do nosso dia a dia, podemos agendar encontros fora do horário produtivo para discussão/disseminação de conteúdo relevante para o time, ou mesmo alguns integrantes que podem inclusive ser de outras squads. Criando um ambiente descontraído e de contribuição entre colegas e equipes.

Fontes:

)