Acelere a colaboração e o desenvolvimento ágil com componentização
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
Seu produto é bem-sucedido, sua organização está crescendo e é hora de aumentar sua base de código para corresponder a esse sucesso. À medida que você expande as equipes de 2 a 3 trabalhando em uma única base de código em um único produto, você pode se ver fazendo perguntas como:
Como minhas equipes podem compartilhar componentes reutilizáveis com eficiência?
Como faço para permitir que minhas equipes de recursos iterem rapidamente sem pisar no trabalho de outras equipes?
Como dar autonomia às minhas equipes para iterar no ritmo certo para elas?
As equipes, em qualquer estágio, podem se beneficiar ao considerar essas questões. Se você é uma equipe estabelecida com uma base de código herdada, pode estar fazendo essas mesmas perguntas à medida que está sendo solicitado a entregar mais valor, mais rápido do que nunca. Independentemente da sua situação, a componentização pode ajudá-lo a criar uma base de código que se adapte ao tamanho da sua equipe e à velocidade do desenvolvimento atual.
Neste artigo, exploramos como a composição binária por meio dos Artefatos do Azure pode ajudá-lo a gerenciar e compartilhar suas dependências externas, seu software de código aberto e seus componentes compartilhados isolados.
Componentes e composição
Componentização é o processo de dividir e organizar seu produto em componentes distintos. A maioria dos projetos .NET já tem alguma noção de componentes na forma dos projetos dentro da solução. Por exemplo, um site básico pode consistir em um componente front-end, um componente de acesso a dados e um componente de modelo/armazenamento de dados.
Composição da fonte
À medida que seu produto cresce, a solução e o modelo de projeto podem se tornar ineficientes. As alterações levam mais tempo para serem integradas e são mais difíceis de mesclar, a compilação fica mais lenta e os componentes começam a crescer de um único projeto para vários projetos. Geralmente, este é o ponto em que as equipes começam a dividir esses conjuntos de projetos relacionados em soluções separadas.
Uma vez que você tenha superado uma única solução, como você componentizar torna-se uma questão interessante. Começamos com a composição do código-fonte, onde cada componente é referenciado por meio de uma referência de projeto no Visual Studio. A composição do código-fonte é possível desde que o código-fonte viva em um único limite de composição: uma única solução dentro de um único repositório de código-fonte.
Infelizmente, essas referências de projeto começam a quebrar quando várias soluções estão envolvidas. Neste ponto, quando a solução A depende da solução B, ela deve se referir aos binários construídos (como DLLs) produzidos pela solução B - esta é a composição binária.
Assim, esses binários agora precisam ser criados e disponibilizados para a solução A antes que ela possa ser compilada com êxito. Há algumas maneiras de fazer isso:
Você pode verificá-los no controle do código-fonte. Dependendo do seu sistema de controle de origem, os binários podem aumentar rapidamente o tamanho do seu repositório, diminuindo os tempos de check-out e o desempenho geral do repositório. Se você começar a trabalhar em ramificações, várias equipes podem acabar introduzindo o mesmo binário em versões diferentes, levando a conflitos de mesclagem desafiadores.
Como alternativa, você pode hospedá-los em um compartilhamento de arquivos, embora essa abordagem venha com certas limitações. Os compartilhamentos de arquivos não possuem um índice para pesquisas rápidas e não fornecem proteção contra a substituição de uma versão no futuro.
Composição da embalagem
Os pacotes abordam muitos dos desafios de referenciar binários. Em vez de verificá-los no código-fonte, você pode fazer com que uma solução B produza seus binários como pacotes NuGet que outra solução A pode consumir. Se a solução A e a solução B são mantidas como componentes separados, onde alterações simultâneas entre A e B são raras, a composição do pacote é uma ótima maneira de gerenciar a dependência de A em B. A composição do pacote permite que B itere em sua própria cadência, enquanto A é livre para obter atualizações de B quando o cronograma de A permitir, e permite que várias equipes iterem e atualizem a solução B sem afetar a solução A (ou outras soluções C ou D).
No entanto, a composição da embalagem vem com seu próprio conjunto de desafios. Até agora, examinamos um exemplo simples. Dimensionar a composição do pacote até o tamanho de uma grande base de código (algo como Windows ou Bing) pode causar uma série de desafios:
Entender o impacto de quebrar alterações em um componente baixo no gráfico de dependência torna-se muito desafiador.
As dependências de diamante podem se tornar um obstáculo significativo para a agilidade. Em uma dependência de diamante, os componentes B e C dependem de um componente A compartilhado, enquanto o componente D depende de B e C. Quando o componente A introduz uma nova versão com alterações de quebra, se B atualiza para a nova versão, mas C não, D não pode aceitar as atualizações de B sem introduzir um conflito de dependência. Neste exemplo simples, uma conversa com C pode ser tudo o que é necessário para resolver o conflito. No entanto, em um gráfico complexo, os diamantes podem rapidamente se tornar insolúveis.
Quando as modificações precisam ser aplicadas a dois componentes que são compostos usando pacotes, o ciclo de iteração do desenvolvedor se torna consideravelmente mais lento. Se o Componente A for atualizado, será necessário reconstruir, reempacotar e republicá-lo. Posteriormente, o componente B deve atualizar para a versão publicada recentemente para validar a alteração feita no componente A. Empregar a composição do código-fonte, que permite a construção simultânea do componente A e B, fornecerá consistentemente um ciclo de iteração mais rápido para os desenvolvedores.
O que você deve usar
Em geral, vimos grandes equipes serem mais bem-sucedidas quando usam uma mistura de estratégias de composição. Para ajudar a determinar o que é certo para sua base de código, comece mapeando o gráfico de dependência do seu produto e comece a agrupar seus componentes em conjuntos de componentes relacionados.
Por exemplo, você pode ter uma coleção de componentes constituindo sua estrutura e outro conjunto de componentes formando seu serviço voltado para o usuário. Em seguida, para cada grupo de componentes relacionados, faça estas perguntas:
Posso antecipar check-ins frequentes nos conjuntos que estabeleci para minhas equipes?
Uma única equipe é responsável por todo o conjunto?
Para um único conjunto, existe uma cadência de lançamento compartilhada?
Em nossa experiência, descobrimos que o uso da composição do código-fonte é mais eficaz para projetos relacionados manipulados por uma única equipe ou um grupo de equipes relacionadas. Por outro lado, a composição binária se mostra vantajosa para software de código aberto, dependências externas (componentes de equipes distantes ou isoladas) e componentes compartilhados independentes.