Somos uma organização composta por cerca de 200 desenvolvedores que estão trabalhando continuamente em um único produto (usando o controle de revisão Git), que está planejado para ser lançado em uma determinada data.
Devido ao grande número de desenvolvedores, estamos tentando criar equipes "multifuncionais", com cerca de 10 desenvolvedores em cada equipe, resultando em cerca de 20 equipes de desenvolvimento na organização.
Como gostaríamos de manter um continuamente "alto padrão" (ou seja, quando o desenvolvedor faz um puxão, o produto deve ser compilável, etc.) do produto no repositório principal, gostaríamos de usar algum tipo de porta de qualidade.
Estou um pouco inseguro sobre como formular a pergunta, mas gostaria de saber se poderia obter alguns conselhos sobre metodologias de desenvolvimento para um grupo tão grande de desenvolvedores trabalhando em um único produto.
Em nossa opinião, uma extremidade do espectro é permitir que cada desenvolvedor se comprometa diretamente com o repositório principal, no entanto, tememos que, devido ao grande número de desenvolvedores / confirmações, o "repositório principal" esteja constantemente em um estágio quebrado, devido não podemos ter um "portão de qualidade" exigente para cada confirmação.
A outra extremidade do espectro pode ser (achamos que Linus Torvalds / Linux faz isso) uma árvore ou uma estrutura de pirâmide, onde o "repositório principal" tem apenas três fontes de recebimento, esses três apenas um punhado de fontes de recebimento confiáveis, etc. Entretanto, sentimos que, com uma estrutura como essa, as mudanças têm uma longa cadeia de escalar para entrar no "repositório principal". Além disso, se ocorrer um conflito de mesclagem, o problema cairá em outro desenvolvedor que não seja o "desenvolvedor original".
Com todas essas informações e opiniões básicas declaradas, como podemos aprender e ler as metodologias de desenvolvimento recomendadas para tantos desenvolvedores? Como as grandes organizações (Microsoft, Facebook, Ubuntu, etc?) Estruturam seu desenvolvimento?
Respostas:
Você certamente deve dividir o produto em módulos com a (s) equipe (s) de interface, reunindo esses módulos em um produto. Por sua vez, isso significaria dividir os repositórios para corresponder ao particionamento e hierarquia do módulo. Se parecer que você não pode fazer isso, o projeto provavelmente sofrerá uma interrupção induzida pela mesclagem, considerando o número de desenvolvedores contribuindo.
Se você planeja usar o Git para controle de versão, recomendo o uso de um sistema de revisão de código (como o Gerrit ) para melhorar a transparência e garantir a qualidade de cada repositório. Dessa forma, todo o trabalho teria que ser aprovado antes de ser mesclado em qualquer repositório oficial. Nesse cenário, faz sentido conceder a certas pessoas confiáveis permissões para enviar de um repositório sob um sistema de revisão de código para outro repositório (também possivelmente sob um sistema de revisão de código). Se usado corretamente, esse deve ser um processo rápido e muito benéfico, que não atrapalha o processo de desenvolvimento.
Em relação à verificação de compilação, você precisaria de um servidor de integração contínua (CI), cujo objetivo é criar e verificar automaticamente o código. Ao verificar o código, quero dizer que o código é compilado e testado com êxito. Attentive Jenkins (CI Server) pode ser vinculado ao sistema de revisão de código da Gerrit como parte do estágio de verificação da Gerrit , automatizando totalmente o processo.
Além dessas ferramentas de integração, é importante buscar a integração frequente como parte da metodologia de desenvolvimento, para minimizar o tempo de fusão.
Pode valer a pena considerar um processo de desenvolvimento Agile como o Scrum, cujo objetivo é dividi-lo em um produto complexo em pedaços gerenciáveis de incremento de produto (chamados Sprints). Isso forneceria oportunidades de integração entre repositórios.
fonte
Claramente, com uma equipe de desenvolvimento de 200 pessoas, você deve ter algum tipo de estrutura hierárquica. Um indivíduo ou um pequeno grupo de pessoas está tomando decisões sobre o design do produto de software. Seu processo de desenvolvimento deve refletir isso: você precisa de revisões e testes de código para garantir que o software que está sendo criado realmente corresponda ao que você queria criar (além de propósitos de qualidade).
Até as equipes pequenas precisam de líderes para orientá-las e revisar seu trabalho à medida que desenvolvem componentes individuais. Devem ser também processos de controle de qualidade implementados no nível da equipe.
Portanto, sim, você deve seguir uma estrutura hierárquica em relação ao repositório. Isso corresponde à estrutura hierárquica do projeto em geral.
Componentes individuais devem ser construídos e testados com um certo nível de adequação antes mesmo de pensar em reuni-los. Permitir que 200 pessoas se comprometam diretamente com o projeto principal seria um caos. Você deve ter áreas separadas para cada grupo em que os indivíduos possam confirmar suas alterações no dia-a-dia, sem afetar a construção principal do projeto.
É uma coisa muito boa se "as alterações tiverem uma longa cadeia para subir para entrar no repositório principal" porque essa cadeia permite garantir a qualidade. Pode parecer mais rápido se todas as alterações se aplicarem imediatamente ao repositório principal, mas na verdade isso será apenas uma grande dor de cabeça, pois você terá uma compilação principal constantemente incorreta e inutilizável do seu software.
Também é bom que "se ocorrer um conflito de mesclagem, o problema caia em outro desenvolvedor" - especificamente, um desenvolvedor de nível superior deve decidir como resolver um conflito.
fonte
Quando você tem algo grande e (como conseqüência) incontrolável, a saída é dividi-lo em pedaços menores e gerenciáveis.
Existem várias etapas que o ajudarão a manter melhor a equipe e o projeto:
divida a funcionalidade em módulos. A funcionalidade deve ser dividida em módulos maximamente independentes, usando os princípios de alta coesão, baixo acoplamento e inversão de dependência. O primeiro princípio ajudará você a criar módulos logicamente consistentes. O segundo ajudará a manter esses módulos o mais independentes possível. O terceiro ajudará a desenvolver módulos dependentes simultaneamente (se o módulo A depender do módulo B, B deve fornecer uma interface que A possa usar, mesmo quando B não estiver completamente pronto).
tenha documentação clara. Quando há tantas pessoas trabalhando juntas, as coisas podem ser facilmente esquecidas ou incompreendidas. Portanto, você precisa prestar atenção especial a toda a documentação, desde requisitos a soluções arquitetônicas.
pessoas para tarefas (nunca tarefas para pessoas). Depois de dividir a funcionalidade em conjuntos menores, crie equipes para trabalhar nesses conjuntos. Criar equipes será mais fácil nesse estágio, porque você já sabe no que cada equipe deve trabalhar. E tarefas como revisões de código seriam realizadas dentro de cada equipe.
sistema claro de tarefas. Cada um dos 200 desenvolvedores deve saber claramente no que trabalhar. Isso o ajudará a acompanhar o que já foi feito, o que cada pessoa está trabalhando e quanto resta.
fonte de controle. (Eu acho que isso está bem descrito em outras respostas)))
E, finalmente, tente criar uma estrutura tão simples quanto possível de equipes e módulos. Você não pode pagar complexidade com um projeto tão grande.
fonte
Além das outras respostas que sugerem uma estrutura hierárquica: isso implica que você terá que agendar pontos de 'integração' no tempo em que o foco é inteiramente em mover o código para cima na hierarquia e 'juntar tudo'. Isso não é muito diferente de projetos menores, com uma fase final em que nenhum outro trabalho é feito além de testes e correções de bugs, apenas com mais frequência. Como você está trabalhando em um grande grupo, buscando padrões elevados, a maior parte disso (estado de espírito) provavelmente já estará em vigor.
fonte
Além da resposta da hotpotato (que está diretamente na marca IMHO), eu também sugeriria implementar algumas portas de controle de origem, como você sugere. Quando movemos uma grande equipe e uma base de código para o git para o SCM, decidimos usar o que é chamado de método "ditador benevolente", semelhante ao modelo que você descreveu.
Nesse cenário, existem várias ramificações da base de código completa que são atualizadas regularmente a partir de sua ramificação de origem, mas a responsabilidade de promover o código em áreas mais visíveis / públicas fica com uma única pessoa (ou pequeno grupo de pessoas) e normalmente é vinculado a um processo de revisão de código. Com uma estrutura de ramificação bem organizada, isso pode funcionar MUITO bem. Para mais informações, confira este link .
fonte
Eu trabalhei em um sistema enorme, com centenas de desenvolvedores trabalhando simultaneamente com cerca de 150 milhões de SLOC. Como era em um mainframe, não estamos falando do Visual Studio, mas os princípios ainda podem ser adotados.
Primeiro de tudo, se você estiver usando Java, eu definitivamente diria que use Maven. Se você estiver usando o VS, também poderá usar o Nuget, embora não tenha muita certeza se o Maven ainda existe ou não (também é um pouco diferente). O uso de um sistema como esse permitirá que você puxe suas dependências e funcione individualmente. Você teria um script de compilação para extrair as dependências relevantes e compilar como um lote.
Dado que você não está fazendo uma pergunta diretamente, mas pedindo uma metodologia, eu vou lhe dizer como meu empregador anterior lidou com isso.
O sistema foi dividido em clusters . Clusters representavam áreas de negócios e áreas de infraestrutura de sistemas. Não vou dar o nome deles, mas para um grande negócio de varejo, você pode pensar em coisas como marketing, operações de varejo, operações on-line, compras e distribuição. A infraestrutura do sistema representava coisas como clientes e segurança. Dentro de cada cluster, havia componentes . Usando a analogia anterior, você pode considerar componentes de segurança, por exemplo - logon único, serviços de diretório, auditoria, relatório etc. Cada componente possui suas rotinas relativas armazenadas.
Como um espaço para nome ou pacote, você teria Organisation.Security.DirectoryServices, por exemplo. Ao conter toda a lógica de suas áreas relevantes, as equipes trabalharam de maneira bastante autônoma. Obviamente, grandes projetos que exigiam a contribuição de várias equipes ocorreram, mas foram operações bastante tranqüilas.
Eu espero que isso ajude.
fonte