Estratégia de ramificação e versão para bibliotecas compartilhadas


12

Essas postagens parecem relacionadas, mas meu cérebro está começando a derreter, tentando pensar sobre isso: P

Meu empregador acabou de começar a usar o controle de origem, principalmente porque antes de contratar mais desenvolvedores, o "repositório" era o disco rígido do desenvolvedor solitário, que trabalha principalmente em casa. Todo o código .NET que ele havia escrito foi verificado em massa e há muitas funcionalidades duplicadas (leia-se: copiar e colar). No momento, nosso sistema SCM é um backup glorificado.

Eu gostaria de inserir parte do código duplicado em bibliotecas compartilhadas. Estou deixando o repositório original em paz para não quebrar nada - podemos mover e / ou refatorar o código existente conforme e quando necessário. Então, configurei um repositório apenas para o novo código, incluindo bibliotecas.

Meu problema gira em torno da versão das bibliotecas sem nos mirar em um processo excessivo: tendo reconhecido que precisamos de uma abordagem mais coerente, com mais desenvolvedores escrevendo códigos muito semelhantes, o gerenciamento e os demais desenvolvedores estão abertos para reorganizar as coisas, mas provavelmente não desça bem se a solução começar a afetar a produtividade.

A solução ideal em minha mente obsessiva é construir as bibliotecas separadamente, com cada projeto dependente construído contra versões compatíveis escolhidas deliberadamente. Dessa forma, sabemos exatamente quais clientes possuem quais versões de quais bibliotecas, podem reproduzir bugs com mais confiabilidade, manter ramificações independentes de lançamento de produtos e bibliotecas e não interromper os projetos uns dos outros ao alterar o código compartilhado.

Isso torna a atualização das bibliotecas complicada, principalmente para o desenvolvedor que trabalha em casa. Espero que as bibliotecas mudem rapidamente, pelo menos inicialmente, à medida que (finalmente) juntamos os bits comuns. É bem possível que eu esteja pensando demais sobre isso e ficaríamos bem apenas construindo tudo contra os commits mais recentes da biblioteca, mas eu gostaria de pelo menos estar preparado para o dia em que decidirmos que alguns componentes precisam ser versionados de forma independente e distribuído. O fato de que algumas das bibliotecas precisarão ser instaladas no GAC torna a versão particularmente importante.

Então, minha pergunta é: o que estou perdendo? Sinto que fixei uma solução e agora estou tentando encontrar variações que tornarão as alterações mais suaves. Que tipos de estratégias você já usou para resolver esse tipo de problema antes? Eu percebo que essa pergunta está em todo lugar; Farei o meu melhor para limpar e esclarecer quaisquer pontos de incerteza.

E por mais que eu adorasse usar o Mercurial, já gastamos dinheiro em um SCM comercial centralizado (Vault) e a troca não é uma opção. Além disso, acho que o problema aqui é mais profundo do que a escolha da ferramenta de controle de versão.


custo fixo é afundado
alternativo

Respostas:


1

Recomendo sua iniciativa. Isso deve gerar vários benefícios para a organização, à medida que você implementa isso. Eu moveria o código em vez de copiá-lo. Possuir cópias provavelmente resultará em alterações incompatíveis que precisarão ser resolvidas.

Haverá alguma dor à medida que as bibliotecas forem desenvolvidas e estabilizadas. Feito isso, os benefícios chegarão. Lembre-se de que as interfaces para a biblioteca são essencialmente um contrato com os projetos que trabalham com o contrato. Você pode ter a vantagem de remover interfaces antigas, pois pode determinar se elas são usadas.

Enquanto as bibliotecas estão se estabilizando, a obtenção de novas bibliotecas provavelmente deve fazer parte do processo de atualização de código. Convém agendar confirmações de alterações da biblioteca. Anunciar o código que está sendo movido pode ajudar a reduzir alterações conflitantes.

As bibliotecas devem ser tratadas como projetos separados e estabilizadas o mais rápido possível. Uma vez estabilizados (principalmente as interfaces), será mais fácil integrar as mudanças com outros projetos. Novas bibliotecas devem funcionar com código antigo. Identifique os releases da biblioteca estável com seu próprio ID de release. Tente tratar as bibliotecas como faria com as bibliotecas de terceiros.


6

O código compartilhado entre os projetos deve ser tratado como um projeto em si. Eles devem ser tratados com o mesmo rigor das bibliotecas de terceiros. Não há outra maneira.

Se você não conseguir que seu grupo adote uma estratégia para código compartilhado, você pode adotá-lo com a ajuda de ferramentas modernas de gerenciamento de código-fonte como Mercurial ou GIT, mesmo que o SCM que sua empresa não use oficialmente. Com um pouco de cuidado, dois SCMs podem usar o mesmo diretório de trabalho apenas dizendo a um para ignorar os arquivos internos do outro. Você usaria um SCM para lidar com o cotidiano e a empresa para integrar.

De qualquer forma, você deve estar encarregado de quando atualizar seu diretório de trabalho com as modificações que outros projetos fizeram no código compartilhado. Isso deve acontecer apenas quando você estiver pronto para lidar com as incompatibilidades que possam surgir; caso contrário, seu trabalho poderá se tornar instável além do possível.


4

Se você tem a capacidade de dividi-los em projetos separados de "módulos", eu adotaria essa abordagem. Uma coisa para se preocupar é o acoplamento de código. Você criaria uma separação de preocupações dividindo-as, o que é uma boa prática.

Alguns benefícios:

  1. Depuração mais simples de cada módulo.
  2. Ciclos de construção mais rápidos (sem reconstrução de bibliotecas que não foram alteradas)
  3. Quando algo funciona, é menos provável que você o altere alterando outra área fora desse módulo (não 100%, mas você reduz as chances).
  4. É mais fácil interromper as atribuições de trabalho se não houver uma grande confusão interdependente.
  5. Distribuição mais rápida de partes menores quando você corrige uma biblioteca (uma grande razão pela qual você tem arquivos .dll / .so).

Eu tenho uma pergunta sobre esta parte:

"A solução ideal em minha mente obsessiva é construir as bibliotecas separadamente, com cada projeto dependente construído contra versões compatíveis e deliberadamente escolhidas".

Você vincula estática todo o projeto? Nesse caso, isso levaria a: 6. Redução do inchaço desnecessário do código.

Alguns negativos:

  1. Se o projeto for pequeno, você estará adicionando complexidade onde não for necessário.
  2. A ramificação de muitos módulos pode se transformar em um problema de manutenção para projetos realmente grandes. Eu não sei "Vault", então não tenho certeza se as operações de ramificação são boas ou ruins.

É um código C #, então é um "não" para a vinculação estática no seu significado usual. Vault é como Subversion, pré-1.5: PI esperou tão ansiosamente para rastreamento de mesclagem no SVN, pensando que eu estava no céu quando ele finalmente chegou. Então eu encontrei o DVCS.
amigos estão dizendo sobre shambulator

1

No momento, parece que você tem uma base de código construída de uma só vez em um único destino. Você provavelmente não tem mais que cinco desenvolvedores. Realmente não vejo a utilidade de separar demais as bibliotecas. Você alteraria seu fluxo de trabalho de código -> compilação -> execução para código -> compilação -> cópia DLL -> compilação -> execução ... ick.

Algumas empresas (Google e Amazon) possuem infra-estrutura suficiente para o desenvolvimento, o que é bastante indolor ter muitas bibliotecas separadas construídas separadamente. A infraestrutura para torná-lo indolor envolve uma maneira de especificar versões da biblioteca que residem no seu SCM (que você provavelmente possui), uma maneira de especificar versões de dependência que residem no seu SCM, um servidor de construção que pode compreendê-lo e compilar tudo corretamente e uma maneira de capturar os artefatos de construção apropriados no servidor de construção e no espaço de trabalho local. Duvido que você tenha isso.

Sem essa infraestrutura, eu separaria o projeto quando uma das seguintes situações se aplicasse:

  • Você possui vários produtos ou aplicativos distintos, dependendo desta biblioteca
  • Você trabalha exclusivamente nessas bibliotecas por vários dias de cada vez
  • A funcionalidade da biblioteca é extremamente separada de qualquer coisa relacionada aos negócios (por exemplo, wrappers em torno de APIs específicas da plataforma)
  • Os tempos de construção para o projeto combinado aumentam muito

Eu me preocuparia em criar essa infraestrutura quando você tiver muitos projetos e alguns tiverem desenvolvedores dedicados e ciclos de lançamento independentes.

O que você pode e deve fazer agora é configurar um servidor de compilação para compilações confiáveis ​​e repetíveis e verifique se consegue encontrar a revisão de origem de um determinado executável. Você parece estar usando .NET; é bem simples configurar o CruiseControl.NET para inserir uma string de versão, incluindo o número da revisão.

Depois de ter um servidor de compilação, separar uma biblioteca será uma questão de movê-la no Vault, adicionar outro destino no CC.NET e copiar a DLL resultante na pasta da biblioteca do projeto principal e enviá-la. Mais fácil do lado do SCM do que o desenvolvimento do dia a dia.


1

Mercurial tem um recurso chamado subrepositórios. Recentemente, li este blog da Kiln explicando como eles funcionam.

Basicamente, você vincula seu projeto a uma revisão específica de um repositório de bibliotecas. Você pode atualizar a biblioteca o quanto quiser sem interromper os projetos dependentes. Quando estiver pronto, você poderá inserir os novos recursos da biblioteca em seu projeto e lidar com qualquer falha. Projetos diferentes podem ser vinculados a diferentes revisões da biblioteca, para que nem todos precisem estar sincronizados e usar a mesma revisão da biblioteca.

Talvez o Vault tenha um recurso semelhante.


1

Adicionamos um arquivo de metadados a cada módulo no SC que indica o nome de todos os outros módulos dos quais depende. Um produto terá um segundo arquivo de metadados indicando qual versão de cada módulo dependente é necessária para o produto. Além disso, há uma ferramenta para analisar os arquivos de metadados, verificar todos os módulos necessários e gerar um projeto para o nosso IDE.

Isso garante que nossas construções sejam sempre reproduzíveis e que os arquivos de cabeçalho corretos sejam sempre compartilhados entre os componentes. Outra complexidade pode ser aplicada à medida que a necessidade se desenvolve. Agora, temos ferramentas que podem gerar relatórios sobre as diferenças entre duas compilações de um produto, especificando arquivos de origem que foram alterados, comentários de check-in, comentários de versão, autores, em todos os módulos independentes no SC. Temos uma quantidade fenomenal de reutilização em nossa base de código.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.