Sugestão de modelo de ramificação para vários clientes do mesmo projeto

11

Temos um projeto muito grande que inclui vários aplicativos que funcionam como base para diferentes clientes.

Cada cliente tem sua própria personalização do produto, marcos diferentes, requisitos diferentes e assim por diante, e assim cada projeto evoluirá independentemente, com base em suas próprias necessidades.

O núcleo do projeto é semelhante (mas não igual) em todos os projetos e a organização é criada para que haja equipes que lidem com cada cliente de forma independente (mas com a comunicação entre eles conforme necessário). Até agora, não consegui encontrar nenhum esquema que atenda às nossas necessidades, pesquisando na Internet ou tendo alguma idéia brilhante :)

Até agora, estamos trabalhando para que o produto seja adequado a todas as necessidades, com ramificações específicas para as mudanças necessárias, mas, embora o produto tenha uma boa arquitetura, está lentamente se tornando um grande problema. Aqui estão os principais problemas que enfrentamos:

  • Marcos diferentes para cada cliente: o que significa que cada equipe deve produzir versões em momentos diferentes, sem que o restante dos comprometimentos afetem a estabilidade ou o produto.
  • Requisitos diferentes, que podem ou não afetar o núcleo do sistema em alguns casos.
  • Equipes grandes (mais de 20 membros da equipe)
  • Lidando com erros no sistema: O que você faz se uma equipe encontra um erro em seu projeto que pode afetar outros clientes?

Nota: Estamos falando de um projeto que possui 10 + M LOC.

Nota: Estamos usando o Team Foundation System, Visual Studio 2008 e C # (principalmente).

Alguma sugestão, fonte ou idéia sobre como lidar com a situação? Existe algum modelo no mercado que tenha um problema semelhante?

Jorge Córdoba
fonte

Respostas:

9

Na verdade, eu sugiro que você não precise de um modelo de ramificação, mas de uma abordagem abrangente e completa para lidar com as restrições multidimensionais em relação ao sistema sem ramificação. Na prática, acredito que sempre será um problema manter vários sistemas com algumas semelhanças, mas evoluirá de maneira diferente nas ramificações; portanto, é melhor transformar tudo em um único sistema que evoluirá como um todo, mas que consiste em configurações diferentes. Isso pode parecer simplista demais, mas há uma extensa pesquisa nessa área, com muitas aplicações industriais bem-sucedidas.

O nome dessa abordagem é Linhas de produtos de software ou, às vezes , Engenharia de linhas de produtos . Na página Linhas de Produto de Software da CMU SEI :

Uma linha de produtos de software (SPL) é um conjunto de sistemas com uso intensivo de software que compartilham um conjunto comum de recursos gerenciados que atendem às necessidades específicas de um segmento ou missão de mercado específico e que são desenvolvidos a partir de um conjunto comum de ativos principais de uma maneira prescrita .

A idéia principal é que todo requisito, todo marco, todo recurso (um termo-chave neste domínio) faça parte do sistema completo no mais alto nível. Os sistemas reais implantados em vários clientes são essencialmente uma coleção de recursos. No entanto, cada recurso não é apenas um componente físico incorporado no sistema, é definido como dependente ou ativado por outros recursos (para que, ao escolher um recurso, você possa incluir automaticamente suas dependências etc.)

Em vez de manter todas essas filiais, você acaba mantendo um sistema junto com um conjunto de configurações específicas do cliente.

Na prática, pode ser difícil ou até impossível migrar para uma abordagem desse tipo com um sistema muito grande, mas mesmo assim será útil investigar as abordagens usadas na SPL para avaliar quais abordagens usadas podem pelo menos (parcialmente). integrado no seu trabalho.

Alguns links úteis adicionais:

Deckard
fonte
11

Quando comecei no meu primeiro emprego, trabalhei em projetos semelhantes (mas em menor escala) e enfrentamos os mesmos problemas. Também começamos com os requisitos gerais de manipulação de soluções para todos os clientes, mas isso foi possível apenas no mesmo ponto em que os requisitos se tornam contraditórios. Fizemos o que você sugere e iniciamos uma versão separada para cada cliente. Mesmo isso resolveu o problema com requisitos e customização, tornando-se um pesadelo de manutenção para solucionar bugs e alterações globais.

Como o código no aplicativo era apenas semelhante, mesclar alterações de uma versão do cliente para outra era muito complexo e exigia um novo teste de cada versão separadamente (não havia testes automáticos!). Geralmente causava erros de regressão em diferentes versões. No seu cenário, isso pode ser ainda pior, porque uma equipe resolverá o erro em sua versão e outra equipe precisará mesclar essa alteração da versão que eles não entendem completamente (éramos uma equipe trabalhando em todas as versões).

A menos que você tenha algum núcleo global compartilhado, você terá os mesmos problemas. Antes de deixar a empresa, descobrimos que nossa abordagem estava incorreta. Para dar suporte a esse cenário de desenvolvimento, precisávamos de um núcleo extensível compartilhado e um modelo de dados que será configurável a partir das camadas de aplicativos personalizáveis ​​superiores. Esse núcleo deve ser usado como base para cada personalização específica do cliente e mantido por uma equipe separada. Isso incluirá algumas complicações de gerenciamento, porque vários gerentes de projeto precisarão de recursos da mesma equipe, mas é a única maneira de tornar a arquitetura consistente, controlar todo o processo e manter as versões sincronizadas.

Ladislav Mrnka
fonte
2

Posso ser a base, mas acho que o que você está enfrentando com o núcleo do seu sistema é o mesmo problema que todos enfrentam, que usam componentes e precisam manter e oferecer suporte a diferentes versões de seus softwares e cada versão diferente requer um conjunto diferente de versões de componentes.

Por exemplo

  • A versão 1.0 requer a biblioteca A 1.0, a biblioteca B 2.0, a biblioteca C 5.6
  • A versão 2.0 requer a Biblioteca A 1.0, Biblioteca B 3.7, Biblioteca C 5.7
  • a versão 3.0 requer a Biblioteca A 1.2, Biblioteca B 3.7, Biblioteca C 5.8

A maneira como resolvemos o problema do componente é ter todas as versões das bibliotecas em nosso sistema de controle de versão (as construímos na fonte) e fazer com que cada projeto use a versão apropriada da biblioteca, alterando seu caminho de pesquisa (caminho de referência?).

No Delphi, isso é feito facilmente através do arquivo de configuração do projeto (sob controle de origem) se você não precisar das bibliotecas no momento do design, caso contrário, ainda é possível, mas torna-se um pouco mais difícil, pois você precisa mudar o Delphi IDE para usar a versão correta também (os arquivos de registro (.reg) sob controle de versão podem ser encontrados aqui).

Uma solução para o seu sistema principal pode ser tratá-lo como uma biblioteca para a qual você mantém versões diferentes. O que, em essência, significa que você precisa configurar ramificações diferentes para cada versão. O aplicativo de um cliente pode usar a "versão" apropriada do seu sistema principal, referenciando a pasta de ramificação do sistema principal.

Onde as dependências do seu sistema principal se pareceriam com o exemplo acima, as dependências dos aplicativos clientes "apenas" terão uma referência extra: a versão do seu sistema principal.

A vantagem adicional do aplicativo cliente múltiplo aqui é que você pode escolher quando começar a usar uma versão específica do seu sistema principal e não será afetado por alterações no sistema principal que ainda não está pronto para usar em um aplicativo cliente específico.

Marjan Venema
fonte