A escolha de um modelo de repo é estratégico para organizações cujo código-fonte é um dos principais ativos.
A Google fez escolhas estruturantes em relação à organização de seus repositórios desde 1999. Opções que se mostraram lucrativas em termos de desempenho.
Quais escolhas a Google fez? Por quais motivos? Que organização teve que ser criada para apoiar tais escolhas?
Abordamos essas questões para entender e ser capazes de traçar possíveis paralelos que sejam relevantes para nossas organizações.
Como uma introdução aos repos, pode consultar este artigo Os principais modelos de Monorepo e Multirepo que precisa de conhecer.
Segue a QE Unit para aceder a mais conteudo exclusivo de Quality Engineering.
O contexto do repositório na Google
Como qualquer empresa, a Google começou bem com algumas linhas de código.
A Google usa o modelo de monorepo para 95% de sua base de código, deixando repos específicos para o Google Chrome e Android.
Historicamente no CVS, o código-fonte foi rapidamente migrado para o Perforce.
Os primeiros engenheiros defendiam com ardor um modelo de monorepo centralizado em uma arquitetura monolítica, escolha ainda tradicional na altura.
As equipas da Google não planejaram necessariamente criar um dos maiores e mais valiosos repo do mundo.
A herança da Google é de tamanho considerável:
- 2 bilhões de linhas de código representando 86 Tb de armazenamento
- 40.000 commits por dia por mais de 10.000 engenheiros (e não só)
- Mais de 35 milhões de commits registrados desde os anos 2000
Aqui estão as estatísticas detalhadas impressionantes de seu repositório em 2015, para o qual é difícil obter dados mais recentes.
O número de ficheiros conta tanto os de configuração, documentação, bem como os excluídos, explicando este alto volume.
Para efeito de comparação, o kernel do Linux de código aberto tem cerca de 15 milhões de linhas de código com 40.000 ficheiros.
O desenvolvimento e o crescimento da Google resultaram amplamente em uma atividade sustentada de mudanças em seu repo.
O crescimento do monorepo da Google
Como Nova York, o monorepo da Google nunca dorme.
Centralizado e compartilhado com mais de 25.000 desenvolvedores hoje, a Google tem iterado para melhorar sua capacidade de crescimento da sua base de código.
Em uma semana típica de 2015, aproximadamente 15 milhões de linhas e 250.000 ficheiros estavam sujeitos a alterações.
Este volume de mudança é impressionante em termos de seu valor absoluto e de crescimento constante.
Lembre-se de que cada uma dessas alterações é feita por engenheiros de desenvolvimento em uma arquitetura monolítica.
Um monorepo sobre esse tipo de arquitetura levanta questões organizacionais reais, por exemplo, conflitos, que discutiremos na segunda parte.
No entanto, esse desempenho impressionante não foi suficiente para suportar os ciclos de inovações direcionadas.
A Google elevou a barra ainda mais ao ultrapassar 35 milhões de commits.
Também observamos um pico no período anterior a 2015, seguido por uma aceleração contínua.
A expressão “(e não só)” assume toda a sua importância aqui.
O crescimento quase exponencial na atividade de código não é de origem humana, mas de automação.
Mais de 24.000 alterações são feitas diariamente por sistemas automatizados, fazendo uma média de 500.000 requests por segundo.
Por que usar commits automatizados?
Garanto que (ainda) não estamos falando sobre código funcional gerado automaticamente.
A Google construiu ao longo dos anos um ecossistema de soluções para enfrentar os desafios de crescimento do seu monorepo.
Qual sistema suporta o repositório da Google?
A Google construiu um verdadeiro sistema para enfrentar os vários desafios de seu monorepo.
As dificuldades tradicionais de um monorepo são as seguintes:
- Muito tempo para descarregar o repositório
- Lentidão e frustrações para encontrar ficheiros
- Menos ênfase na boa modularização do código
- Gerenciamento das dependências que podem se tornar cíclicas
- Dificuldade em orquestrar o processo de build
- Ciclos de teste realizados mais complexos por esses outros fatores
Então, vamos dar uma olhada em como a Google respondeu a esses diferentes problemas, em sua ordem de uso.
Primeiro, vamos ter em mente que a organização, cultura e comunicação da Google sempre apoiaram um modelo monorepo : base de código única, compartilhamento, visibilidade transversal.
O alinhamento resulta em commits frequentes para uma base de código, onde o tamanho do repositório é o principal desafio.
O armazenamento de seus 86 Tb de código-fonte é suportado por Piper, uma solução de armazenamento distribuída em escala que suporta a actividade sustentada do repo.
O acesso é, por defeito, aberto a todos os desenvolvedores com rastreabilidade integrada, alguns ficheiros são restritos por exceção.
Navegar na enorme base de código da Google e ao mesmo tempo contribuir para ela é suportada pelo CitC (“Cliente in the Cloud”), um armazenamento na nuvem que oferece uma interface leve.
A solução atua como um proxy onde apenas os arquivos modificados são baixados localmente.
O caso da procura de ficheiros neste enorme repositório é suportado por CodeSearch, facilitando a busca entre os diferentes espaços de trabalho e uma edição simplificada.
Plugins para Eclipse e eMacs também foram desenvolvidos para centralizar a experiência de desenvolvimento em um IDE.
Esses três elementos permitem a colaboração em escala em um monorepo, onde a arquitetura e os processos de entrega são centrais.
Qual organização do repositório da Google?
A arquitetura e organização do repositório não está ligada à escolha de mono ou multi-repos, mas permanece estruturante.
Verifique este artigo, se necessário, para relembrar os mitos dos repo.
A Google organiza seu monólito em diferentes diretórios em espaços de trabalho, cada um com uma equipe e um engenheiro responsável.
A comunicação entre os diferentes componentes é alcançada por meio de modularização, interface e padrões de serviço. Eles protegem a nomenclatura, o controle de versão, os protocolos por casos de uso, o gerenciamento de erros e assim por diante.
O gerenciamento de dependências é apoiado de forma proativa por práticas de documentação de API e ferramentas de análise estática que veremos mais tarde.
As ferramentas do repositório permitem uma análise de dependências, permitindo avaliar e tratar os impactos transversais. O monorepo também facilita uma análise de repo completa, evitando o problema de dependências cíclicas ou “diamond-dependency”.
Os processos de desenvolvimento são depois suportados por meio de um modelo de branching.
Qual modelo de branching o repo da Google oferece suporta?
A Google também é conhecida por usar trunk-based development em escala com sucesso.
Esse modelo rima com uma cultura de compromissos e entregas regulares, permitindo a integração o mais rápido possível para reduzir os riscos de integração.
Em termos de agências, as alterações são enviadas para que a agência principal seja submetida a uma série de análises que compartilhamos.
O modelo de monorepo gerido com trunk-based development remove pesadelos de merge com branches de desenvolvimento.
Uma ramificação de release é usada para dar suporte a deploys geralmente gerenciados em A/B testing, com features-flags, de maneira a gerenciar o risco de ativação e não bloquear a mainline do repo..
Alinhado com o modelo de branching, a Google investiu fortemente em análise estática, limpeza de código e processos de revisão.
Cada alteração é proposta com um changelog das alterações realizadas antes de ser submetida às várias etapas de validação.
Quais processos de validação e revisão são usados?
As primeiras verificações automáticas são realizadas pelo seu sistema de presubmit, Tri-corder10.
Os controles padrão e específicos do repo fornecem feedback inicial rápido e automático para o desenvolvedor, independentemente da sua localização e do seu fuso horário.
Essas verificações são o resultado de vários anos de iterações, incorporando mecanismos semelhantes aos ramos de desenvolvimento para realizar testes localizados nos componentes impactados.
As várias verificações são realizadas periodicamente, além de cada proposta de mudança.
Uma vez que este primeiro passo tenha sido dado, o código será revisado, comentado e possivelmente retrabalhado, antes de ser aceito por meio de uma “commit approval” por um dos gerentes do espaço de trabalho.
Essas etapas são realizadas com a solução Critique, ferramenta da Google que dá suporte ao processo de revisão de código (envio, comentários, validação).
A etapa de validação é seguida pela execução de uma série de testes que irão acionar o commit no repositório automaticamente.
Estamos finalmente chegando à construção de nosso código?
Isso é possível com a obtenção da aprovação da ferramenta de teste e compilação da Google, Pipe.
Se a mudança for considerada muito arriscada, o commit é automaticamente retirado para não impactar a mainline.
O processo descrito deve ser imaginado em escala com centenas de commits por hora que são avaliados regularmente.
O refactoring em tal código básico pode ser como fazer obras numa capital, um pesadelo.
Como a Google efetua refactoring a escala num monorepo?
É aí que entra Rosie, uma solução da Google para realizar refactoring, otimização e limpeza de código em massa.
A Rosie está ao serviço de engenheiros que podem fazer patches estruturantes em todo o repositório.
A solução garantirá as ações mais arriscadas, mais demoradas e menos interessantes por meio da automação.
Os patches de estruturação são, por exemplo, divididos em alterações menores que serão revisadas por cada proprietário, antes de serem construídas e testadas de forma independente.
É interessante notar que as propostas de mudança são analisadas por um comitê que equilibra o esforço de revisão necessário, os impactos no repositório e o valor criado.
Esse processo de revisão ampliada foi implementado em 2013, estabilizando o volume de periódicos gerenciados por Rosie.
Além disso, uma equipa é responsável por manter uma cadeia de integração atualizada, utilizável e eficiente do compilador.
Portanto, a Google investiu estruturalmente em um sistema de gerenciamento de código holístico para enfrentar os desafios de um monorepo em escala.
Vamos, portanto, dar um passo para trás para avaliar tal sistema.
Quais são as vantagens de um monorepo em escala?
Portanto, vamos identificar as vantagens e desvantagens para termos uma perspectiva transversal do assunto.
A Google beneficia de várias vantagens estruturais de seu monorepo:
- Visibilidade global de seus ativos de código
- Versionamento centralizado e integrado o mais rápido possível
- Suporte a partilha e reutilização de código
- Gerenciamento de dependência simplificado
- Mudanças atômicas que permanecem sob controle
- Capacidade de realizar mudanças estruturais e refactoring
Sua capacidade de fornecer uma experiência de desenvolvimento satisfatória é chave. Tempos de carregamento infinitos, análises de impacto árduas e medo de refactoring não existem.
Seu ecossistema permite uma velocidade sem precedentes de atualização de seu código, dando suporte a uma colaboração extensa.
O uso de static linking também resolve o problema dos binários, abrindo espaço para mudanças simples e rapidamente integradas ao principal, se eles passarem pelos vários estágios de revisão.
Como lidar com as desvantagens de um modelo monorepo?
Seu sucesso também está relacionado ao tratamento das principais desvantagens de um modelo em monorepo.
A Google classifica esses pontos em 3 categorias:
- A complexidade e o tamanho da base de código, o que torna difícil de entender, pesquisar, escalar e manter
- Investimento em ferramentas em toda a cadeia, desde o repositório até a build, teste e deploy
- Gerenciamento de qualidade do repositório : código, documentação e refactoring
Os vários elementos compartilhados melhoraram os problemas normalmente encontrados.
Duas dificuldades principais ainda precisam de ser aceitas neste modelo.
A primeira é que as equipas costumam consultar os detalhes de implementação das várias APIs, que estão disponíveis no repositório.
É uma particularidade a aceitar, a trabalhar na cultura e nas práticas sem restringir o acesso, sendo a visibilidade um ponto forte de um monorepo.
A segunda dificuldade é o desenvolvimento e integração de componentes de código open-source. A Google consegue isso mantendo um espaço específico em seu repositório para este caso. Requer atenção especial no contexto do monorepo.
Será que a Google mudará para um modelo multi-repo?
Os engenheiros da Google regularmente se perguntam uma passagem para multi-repos e o uso do Git.
Multirepos são utlizados para seus outros projetos, como Android, Chrome e grandes iniciativas open-source.
Isso é o que permite que eles também capturem a comunidade por meio do uso generalizado do Git.
Por que não substituir Piper pelo Git em seu monorepo?
O Git foi construído para suportar um modelo de desenvolvimento distribuído, principalmente em multi-repo.
Querer usar o Git significaria, portanto, mudar o monorepo para uma multidão de repos, o objetivo oposto da organização de código da Google.
Ao longo dos anos, apesar de já ter feito a pergunta várias vezes, o monorepo da Google continuou sendo a opção escolhida.
Desde 2015, a Google tem trabalhado com a comunidade Mercurial para facilitar workflows das suas equipas.
O que lembrar e aplicar do modelo de repo da Google?
A estratégia de monorepo e uma arquitetura monolítica claramente apoiou o desempenho da Google.
Um ponto estruturante é o alinhamento dessa estratégia com a organização, cultura e processos da organização.
A identificação, gestão e melhoria de trade-offs também é fundamental para limitar as restrições e limites do modelo escolhido.
Essa perspectiva global é o que permite fazer escolhas reais e alinhar investimentos estratégicos.
Lembre-se de que adotar um monorepo ou uma arquitetura monolítica não nos fará a próxima Google.
Dependendo do contexto, um monorepo também pode evoluir para um multi-repo, desde que estejam alinhados e relevantes para sua empresa.
É o sistema no seu todo que permite uma orquestração bem-sucedida de sua organização, a serviço dos negócios.
Referências
1. Bloch, D. Ainda tudo em um servidor: Perforce em escala. White Paper da Google, 2011; http://info.perforce.com/rs/perforce/images/GoogleWhitePaper-StillAllonOneServer-PerforceatScale.pdf
Build in the Cloud: Como funciona o Build System. Postagem do blog sobre as ferramentas de engenharia da Google, 2011; http://google-engtools.blogspot.com/2011/08/build-in-cloud-how-build-system-works.html
Wright, HK, Jasper, D., Klimek, M., Carruth, C., e Wan, Z. Refatoração automatizada em grande escala usando ClangMR. Em Proceedings of the IEEE International Conference on Software Maintenance (Eindhoven, The Netherlands, September 22-28). IEEE Press, 2013, 548–551
Por que a Google armazena bilhões de linhas de código em um único repositório https://research.google/pubs/pub45424/