Em nosso trabalho, temos vários aplicativos .net diferentes que compartilham muita funcionalidade básica. Criamos esses aplicativos usando uma arquitetura limpa de n camadas, mas chegamos ao momento em que percebemos que reimplementamos as mesmas funções várias vezes. Obviamente, isso viola a DRY, e gostaríamos de corrigir isso. Já estamos usando o Nuget com sucesso para obter códigos comuns de cola (conectando IoC, registro, configurações), mas também gostaríamos de compartilhar nossas camadas de dados e negócios entre todos os nossos aplicativos. A ideia é que a interface do usuário lide apenas com as partes da camada de negócios que realmente precisa.
Isso parece um problema direto no começo, mas o desenvolvimento contínuo pode fornecer algumas armadilhas e não temos certeza de como proceder. Digamos que criamos nossa camada de negócios única para governá-los todos. Por uma questão de brevidade, chamarei de "Fundação". Portamos nossos aplicativos para usar a Foundation, e tudo está indo muito bem. A Fundação é distribuída para iluminar as camadas da interface do usuário via nuget, e estamos com uma boa aparência. Mas então começamos a adicionar recursos aos nossos aplicativos e encontramos problemas.
Digamos que estamos trabalhando no Projeto A e adicionamos um novo recurso que requer alterações no Foundation. Fazemos as alterações na fundação (Foundation-A) e as empurramos para o feed de pepitas como um pacote instável. O Projeto A recebe o pacote mais recente de pepitas e tudo está bem. Enquanto isso, outro desenvolvedor está trabalhando no Projeto B. Ele obtém o Foundation mais recente do controle de origem, mas o retira de uma ramificação estável, para que não tenha alterações no Projeto A. Ele faz alterações e criou a Foundation-B. E tudo está bem. Porém, descobrimos que as funcionalidades de implementação Foundation-A e Foundation-B que realmente poderiam compartilhar código, então as combinamos. Enquanto isso, a Foundation-C está flutuando com suas próprias mudanças. Eventualmente, o Foundation-B está pronto para a produção, então nós o expomos. Mas precisamos atualizar a produção A, B,
Parece que poderia funcionar, mas estamos preocupados em trabalhar com diferentes esquemas de banco de dados e manter tudo sincronizado entre as várias ramificações do repositório Foundation, bem como os repositórios do Projeto A, B e C. Parece que provavelmente será necessário muito trabalho manual, o que abre a possibilidade de erros. Eu gostaria disso o mais automatizado possível.
Aqui está a pilha que estamos usando: C #, TFS com integração contínua, Nuget. Nossos aplicativos são todos os tipos de aplicativos ASP.NET. Estamos dispostos a olhar para diferentes SCMs, se isso facilitar as coisas.
Estou procurando maneiras de manter o Nuget com os nossos diferentes ramos de código-fonte. Não queremos inserir código de desenvolvimento acidentalmente em produção porque fazemos referência ao Pacote Nuget errado.
Respostas:
Aqui é onde seu problema começa ... Não faça isso.
Quaisquer alterações no Foundation v1.0 devem ser inerentemente valiosas para todos os consumidores do Foundation, caso contrário, ele não pertence ao Foundation. Portanto, ao criar o pacote nuget, faça-o como uma versão oficial e estável do Foundation (por exemplo, v1.1), ou não faça nada.
O Projeto B deve criar os aprimoramentos do Foundation como faria normalmente, mas (no bom modo de gerenciamento de origem) deve mesclar-se às alterações de tronco (v1.1) antes de enviar um Foundation (v1.2) estável para o nuget.
Outros projetos que podem usar os aprimoramentos do Foundation podem atualizar suas referências de nuget, quando apropriado, ou seguir as versões mais antigas, se necessário.
Eu concordo com @Giedrius ; isso me parece ser mais um problema de controle / ramificação de origem, no sentido de que, se a ramificação / fusão do Foundation for tratada adequadamente, os problemas de gerenciamento de pacotes se tornarão discutíveis.
fonte
Refatore seu código duplicado em funções aplicáveis de uma maneira mais abstrata e coloque-as em suas próprias bibliotecas ou estruturas. Torne-os fracamente acoplados e independentes de arquitetura, e você nunca deve ter nenhum problema. Se você precisar de inspiração, estude como a estrutura .NET abstrai conceitos usando coisas como interfaces, genéricos e padrões de software como
Dispose()
.Além disso, lembre-se de que nem todo código duplicado é realmente duplicado; algumas são códigos de cola ou códigos necessários para sustentar a arquitetura; portanto, não fique obcecado por ficar muito seco.
fonte
Reutilização de código
Houve várias abordagens para a reutilização de código que foram favorecidas ao longo dos anos. Cada abordagem tem seu lugar e, mais importante, seus problemas , mas as maneiras viáveis de reutilizar o código no .NET são:
Biblioteca comum. O código necessário em mais de um local é colocado em uma biblioteca comum e todas as outras partes da base de código têm uma única referência a esse código. A principal desvantagem é que você acaba com a maior parte do seu projeto, dependendo dessa biblioteca, que contém muitas funções não relacionadas. Esta é uma péssima ideia do ponto de vista da garantia de qualidade.
Código-fonte comum. O código necessário em mais de um local é gravado uma vez e colocado em um arquivo de origem em uma estrutura de diretório comum. Todos os projetos que precisam desse código incluem esse arquivo como um de seus arquivos de origem. Isso fornece a reutilização de código, e as vantagens de escrever uma vez usam muitos. Contudo. Sua desvantagem é que é possível ter diferentes partes do projeto compiladas com diferentes versões deste código - o que pode introduzir alguns defeitos sutis que podem ser muito difíceis de detectar e identificar pela garantia da qualidade.
Serviço. O código comum é implementado como um serviço, que outros aspectos podem acessar. Isso tem a vantagem de haver um único serviço em uma implantação e evita dependências. No entanto, introduzirá latência e falhas. Esse tipo de abordagem funciona bem em grandes produtos distribuídos, onde alta disponibilidade e tolerância a falhas já são entendidas e gerenciadas.
Gerenciando o NuGET
Aqui você tem um problema muito mais interessante. Gerenciando várias configurações. Meu conselho aqui é não gerenciar uma base de clientes diversificada com diferentes versões de código, mas com arquivos de configuração. Existem pelo menos três camadas de dados de configuração para gerenciar. Configuração básica (interna) do produto que o cliente nunca vê. As opções de configuração padrão que seu cliente pode alterar e a camada final de opções de configuração que seu cliente alterou. Ao separar essas diferentes camadas, você poderá implementar atualizações sem destruir as configurações de seus clientes.
fonte
Acho que o problema não está no nuget / controle de origem / ramificação, mas no que entra no código de colagem.
Robert tem uma boa resposta, só para ver uma imagem completa, recomendo pensar em quais dependências esses utilitários comuns trarão em cada projeto:
http://ayende.com/blog/3986/let-us-burn-all-those-pesky-util-common-libraries http://blog.jordanterrell.com/post/CommonUtility-Libraries-Dead.aspx
A melhor maneira de evitar o inferno que você está tendo é abrir seu código de cola. Dessa forma, você começará a se importar, que nenhuma lógica de negócios seja divulgada, de modo que nenhuma dependência concreta do projeto caia no código da cola, que seria abstrato o suficiente para ser reutilizado por qualquer pessoa, mesmo fora da sua empresa - e se essa cola código será bom o suficiente - você também receberá informações da comunidade.
fonte
A solução é simples: crie um projeto separado para ele e gerencie-o como algo separado: são requisitos próprios, testes, convenções, documentação, planejamento, pessoas etc. avaliados primeiro antes de criarem um problema.
Ou melhor ainda: torne-o "open-source" dentro da sua organização. Portanto, qualquer pessoa pode alterar o código, mas apenas poucas pessoas selecionadas terão direitos completos de confirmação. E essas pessoas serão responsáveis por garantir a qualidade e os recursos corretos.
fonte