Monorrepositórios: por favor, deve

Monorrepositórios: por favor, deve

Tradução do artigo elaborado para alunos do curso "Práticas e ferramentas DevOps" no projeto educacional OTUS.

Você deve escolher um monorepositório porque o comportamento que ele promove em suas equipes é a transparência e a responsabilidade compartilhada, principalmente à medida que as equipes crescem. De qualquer forma, você terá que investir em ferramentas, mas é sempre melhor se o comportamento padrão for o que você deseja em seus comandos.

Por que estamos falando sobre isso?

Matt Klein escreveu o artigo "Monorepos: Por favor, não!"  (nota do tradutor: tradução em Habré “Monorepositórios: por favor, não”). Gosto do Matt, acho que ele é muito inteligente e você deveria ler o ponto de vista dele. Ele postou originalmente a enquete no Twitter:

Monorrepositórios: por favor, deve

Tradução:
Neste dia de Ano Novo, vou discutir sobre como os monorepositórios são ridículos. 2019 começou tranquilo. Nesse espírito, ofereço-lhe uma pesquisa. Quem são os grandes fanáticos? Apoiadores:
- Monorepo
- Ferrugem
- Enquete incorreta/ambos

Minha resposta foi: “Sou literalmente as duas pessoas”. Em vez de falar sobre como Rust é uma droga, vamos ver por que acho que ele está errado sobre os monorrepositórios. Um pouco sobre você. Sou o CTO da Chef Software. Temos cerca de 100 engenheiros, uma base de código que remonta a cerca de 11 a 12 anos e 4 produtos principais. Parte desse código está em um polirrepositório (minha posição inicial), parte está em um monorepositório (minha posição atual).

Antes de começar: todos os argumentos que apresento aqui se aplicarão a ambos os tipos de repositórios. Na minha opinião, não há razão técnica para você escolher um tipo de repositório em vez de outro. Você pode fazer qualquer abordagem funcionar. Fico feliz em falar sobre isso, mas não estou interessado em razões técnicas artificiais que explicam por que uma coisa é superior a outra.

Concordo com a primeira parte do argumento de Matt:

Porque em escala, um monorrepositório resolverá todos os mesmos problemas que um polirrepositório resolve, mas ao mesmo tempo forçará você a acoplar seu código e exigirá esforços incríveis para aumentar a escalabilidade de seu sistema de controle de versão.

Você terá que resolver os mesmos problemas independentemente de escolher um monorrepositório ou um polirrepositório. Como você lança lançamentos? Qual é a sua abordagem em relação às atualizações? Compatibilidade com versões anteriores? Dependências entre projetos? Quais estilos arquitetônicos são aceitáveis? Como você gerencia sua infraestrutura de construção e teste? A lista não tem fim. E você resolverá todos eles à medida que crescer. Não existe queijo grátis.

Acho que o argumento de Matt é semelhante às opiniões compartilhadas por muitos engenheiros (e gerentes) que respeito. Isso ocorre da perspectiva do engenheiro que trabalha no componente ou da equipe que trabalha no componente. Você ouve coisas como:

  • A base de código é volumosa - não preciso de todo esse lixo.
  • É mais difícil testar porque tenho que testar todo esse lixo que não preciso.
  • É mais difícil trabalhar com dependências externas.
  • Preciso de meus próprios sistemas de controle de versão virtual.

Claro, todos estes pontos são justificados. Isso acontece em ambos os casos - no polirrepositório tenho meu próprio lixo, além daquele necessário para a construção... Também posso precisar de outro lixo. Então eu “simplesmente” crio ferramentas que verificam todo o projeto. Ou crio um monorepositório falso com submódulos. Poderíamos andar por aí o dia todo. Mas acho que o argumento de Matt ignora o motivo principal, que inverti fortemente em favor do monorrepositório:

Provoca comunicação e mostra problemas

Quando separamos os repositórios, criamos um problema de facto de coordenação e transparência. Isto corresponde à forma como pensamos sobre as equipes (especialmente a forma como os membros individuais pensam sobre elas): somos responsáveis ​​por um determinado componente. Trabalhamos em relativo isolamento. Os limites são fixados em minha equipe e no(s) componente(s) em que estamos trabalhando.

À medida que a arquitetura se torna mais complexa, uma equipe não consegue mais gerenciá-la sozinha. Muito poucos engenheiros têm todo o sistema em mente. Digamos que você gerencia um componente compartilhado A que é usado pelas equipes B, C e D. A equipe A está refatorando, melhorando a API e também alterando a implementação interna. Como resultado, as alterações não são compatíveis com versões anteriores. Que conselho você daria?

  • Encontre todos os locais onde a API antiga é usada.
  • Existem locais onde a nova API não pode ser usada?
  • Você pode consertar e testar outros componentes para garantir que não quebrem?
  • Essas equipes podem testar suas mudanças agora?

Observe que essas perguntas são independentes do tipo de repositório. Você precisará encontrar as equipes B, C e D. Você precisará conversar com eles, saber os horários, entender suas prioridades. Pelo menos esperamos que você faça isso.

Ninguém realmente quer fazer isso. Isso é muito menos divertido do que apenas consertar a maldita API. É tudo humano e confuso. Em um polirrepositório, você pode simplesmente fazer alterações, entregá-las às pessoas que trabalham naquele componente (provavelmente não B, C ou D) para revisão e seguir em frente. As equipes B, C e D podem ficar com a versão atual por enquanto. Eles serão renovados quando perceberem a sua genialidade!

Em um monorepositório, a responsabilidade é transferida por padrão. A Equipe A muda seu componente e, se não tomar cuidado, quebra imediatamente B, C e D. Isso faz com que B, C e D apareçam na porta de A, se perguntando por que a Equipe A quebrou a montagem. Isso ensina a A que eles não podem pular minha lista acima. Eles devem falar sobre o que vão fazer. B, C e D podem se mover? E se B e C puderem, mas D estiver intimamente relacionado a um efeito colateral do comportamento do antigo algoritmo?

Então temos que conversar sobre como sairemos dessa situação:

  1. Suporte para múltiplas APIs internas e marcará o algoritmo antigo como obsoleto até que D possa parar de usá-lo.
  2. Suporte para várias versões de lançamento, uma com a interface antiga e outra com a nova.
  3. Atrase a liberação das alterações de A até que B, C e D possam aceitá-las simultaneamente.

Digamos que selecionamos 1, várias APIs. Neste caso, temos dois trechos de código. Velho e novo. Bastante conveniente em algumas situações. Verificamos novamente o código antigo, marcamos-o como obsoleto e concordamos com um cronograma de remoção com a equipe D. Essencialmente idêntico para repositórios poli e mono.

Para lançar múltiplas versões, precisamos de um branch. Agora temos dois componentes – A1 e A2. As equipes B e C usam A2 e D usa A1. Precisamos que todos os componentes estejam prontos para lançamento porque atualizações de segurança e outras correções de bugs podem ser necessárias antes que D possa avançar. Em um polirrepositório, podemos esconder isso em um branch de longa vida que seja bom. Em um monorepositório, forçamos a criação do código em um novo módulo. A Equipe D ainda terá que fazer alterações no componente “antigo”. Todos podem ver o custo que estamos pagando aqui - agora temos o dobro de código e quaisquer correções de bugs aplicáveis ​​a A1 e A2 devem ser aplicadas a ambos. Com a abordagem de ramificação em um polirrepositório, isso fica oculto atrás da seleção seletiva. Consideramos o custo menor porque não há duplicação. Do ponto de vista prático, o custo é o mesmo: você construirá, lançará e manterá duas bases de código praticamente idênticas até poder excluir uma delas. A diferença é que com um monorrepositório essa dor é direta e visível. Isso é ainda pior, e isso é bom.

Finalmente chegamos ao terceiro ponto. Atraso na liberação. É possível que as mudanças feitas por A melhorem a vida da Equipe A. Importantes, mas não urgentes. Podemos apenas atrasar? Em um polirrepositório, enviamos isso para fixar o artefato. É claro que estamos contando isso para o Time D. Fique na versão antiga até se atualizar! Isso prepara você para bancar o covarde. A Equipe A continua trabalhando em seu componente, ignorando o fato de que a Equipe D está usando uma versão cada vez mais desatualizada (isso é problema da Equipe D, eles são estúpidos). Enquanto isso, a Equipe D fala mal sobre a atitude descuidada da Equipe A em relação à estabilidade do código, se é que falam sobre isso. Meses passam. Por fim, a Equipe D decide analisar a possibilidade de atualização, mas A só tem mais alterações. O Time A mal se lembra quando ou como quebrou D. A atualização é mais dolorosa e demorará mais. O que o envia ainda mais para baixo na pilha de prioridades. Até o dia em que temos um problema de segurança em A que nos obriga a fazer um ramal. A equipe A deve voltar no tempo, encontrar um ponto em que D estava estável, corrigir o problema ali e prepará-lo para o lançamento. Esta é a escolha de facto que as pessoas fazem e é de longe a pior. Parece ser bom tanto para o Time A quanto para o Time D, desde que possamos ignorar um ao outro.

Em um monorepositório, o terceiro não é realmente uma opção. Você é forçado a lidar com a situação de duas maneiras. Você precisa ver os custos de ter duas filiais de lançamento. Aprenda a se proteger contra atualizações que quebram a compatibilidade com versões anteriores. Mas mais importante: você não pode evitar uma conversa difícil.

Na minha experiência, quando as equipes ficam grandes, não é mais possível manter todo o sistema em mente, e essa é a parte mais importante. Você deve melhorar a visibilidade da discórdia no sistema. Você deve trabalhar ativamente para fazer com que as equipes desviem de seus componentes e olhem para o trabalho de outras equipes e consumidores.

Sim, você pode criar ferramentas que tentam resolver o problema do polirrepositório. Mas minha experiência no ensino de entrega contínua e automação em grandes empresas me diz o seguinte: o comportamento padrão sem o uso de ferramentas adicionais é o comportamento que você espera ver. O comportamento padrão de um polirrepositório é o isolamento, esse é o ponto principal. O comportamento padrão de um monorepositório é responsabilidade compartilhada e transparência, esse é o ponto principal. Em ambos os casos, vou criar uma ferramenta que suavizará as arestas. Como líder, sempre escolherei um monorepositório porque as ferramentas precisam reforçar a cultura que desejo, e a cultura vem de pequenas decisões e do trabalho diário da equipe.

Apenas usuários registrados podem participar da pesquisa. Entrarpor favor

Quem são os maiores fanáticos? Apoiadores:

  • Monorepo

  • Ferrugem

  • Enquete incorreta/ambos

33 usuários votaram. 13 usuários se abstiveram.

Fonte: habr.com

Adicionar um comentário