Este é um debate do qual participo. Gostaria de obter mais opiniões e pontos de vista.
Temos algumas classes que são geradas em tempo de construção para lidar com operações de banco de dados (neste caso específico, com SubSonic, mas não acho que seja muito importante para a questão). A geração é definida como uma etapa de pré-construção no Visual Studio. Portanto, toda vez que um desenvolvedor (ou o processo de compilação oficial) executa uma compilação, essas classes são geradas e depois compiladas no projeto.
Agora, algumas pessoas estão afirmando que ter essas classes salvas no controle de origem pode causar confusão, caso o código que você obtém não corresponda ao que seria gerado em seu próprio ambiente.
Gostaria de encontrar uma maneira de rastrear o histórico do código, mesmo que geralmente seja tratado como uma caixa preta.
Algum argumento ou contra-argumento?
ATUALIZAÇÃO: Eu fiz essa pergunta porque realmente acreditava que havia uma resposta definitiva. Olhando para todas as respostas, eu poderia dizer com alto nível de certeza, que essa resposta não existe. A decisão deve ser tomada com base em mais de um parâmetro. Ler as respostas abaixo pode fornecer uma orientação muito boa para os tipos de perguntas que você deve se fazer ao decidir sobre esse assunto.
Não selecionarei uma resposta aceita neste momento pelos motivos mencionados acima.
fonte
Respostas:
Salvar no controle de origem é mais problemático do que compensa.
Você tem que fazer um commit toda vez que você fizer uma build para que tenha qualquer valor.
Geralmente deixamos o código gerado (idl, material jaxb, etc) fora do controle de origem onde trabalho e nunca foi um problema
fonte
Coloque-o no controle do código-fonte. A vantagem de ter o histórico de tudo o que você escreve disponível para futuros desenvolvedores supera a pequena dor de ocasionalmente reconstruir após uma sincronização.
fonte
Sempre que desejo mostrar alterações em uma árvore de origem em meu repositório pessoal, todos os 'arquivos gerados' aparecerão como tendo sido alterados e precisam ser corrigidos.
Eu preferiria ter uma lista mais limpa de modificações que incluísse apenas atualizações reais que foram realizadas, e não alterações geradas automaticamente.
Deixe-os de fora e, após uma construção, adicione um 'ignorar' em cada um dos arquivos gerados.
fonte
Veja desta forma: você verifica seus arquivos de objeto no controle de origem? Os arquivos de origem gerados são artefatos de construção exatamente como arquivos de objeto, bibliotecas e executáveis. Eles devem ser tratados da mesma forma. A maioria argumentaria que você não deveria verificar arquivos de objetos gerados e executáveis no controle de origem. Os mesmos argumentos se aplicam à fonte gerada.
Se você precisa olhar para a versão histórica de um arquivo gerado, você pode sincronizar com a versão histórica de suas fontes e reconstruir
Verificar arquivos gerados de qualquer tipo no controle de origem é análogo à desnormalização do banco de dados. Ocasionalmente, há motivos para fazer isso (normalmente para desempenho), mas isso deve ser feito apenas com muito cuidado, pois se torna muito mais difícil manter a correção e a consistência depois que os dados são desnormalizados.
fonte
Eu diria que você deve evitar adicionar qualquer código gerado (ou outros artefatos) ao controle de origem. Se o código gerado for o mesmo para a entrada fornecida, você pode apenas verificar as versões que deseja comparar e gerar o código para comparação.
fonte
Eu chamo o princípio DRY. Se você já tem os "arquivos de origem" no repositório que são usados para gerar esses arquivos de código em tempo de construção, não há necessidade de ter o mesmo código confirmado "duas vezes".
Além disso, você pode evitar alguns problemas dessa forma se, por exemplo, a geração de código for interrompida algum dia.
fonte
Não, por três razões.
O código-fonte é tudo o que é necessário e suficiente para reproduzir um instantâneo de seu aplicativo a partir de algum momento atual ou anterior - nada mais e nada menos. Parte do que isso implica é que alguém é responsável por tudo o que é verificado. Em geral, fico feliz em ser responsável pelo código que escrevo, mas não pelo código que é gerado como consequência do que escrevo.
Eu não quero que alguém fique tentado a tentar um atalho para uma compilação de fontes primárias usando código intermediário que pode ou não ser atual (e mais importante pelo qual não quero aceitar a responsabilidade). tentador para algumas pessoas se envolverem em um processo sem sentido sobre depuração de conflitos em código intermediário com base em compilações parciais.
Assim que estiver no controle de origem, aceito a responsabilidade por a. estando lá, b. sendo atual, e c. sendo integrável de forma confiável com todo o resto. Isso inclui removê-lo quando não estiver mais usando. Quanto menos responsabilidade, melhor.
fonte
Eu realmente não acho que você deveria fazer o check-in.
Certamente, qualquer mudança no código gerado será ruído - mudanças entre ambientes ou mudanças como resultado de outra coisa - por exemplo, uma mudança em seu banco de dados. Se os scripts de criação de seu banco de dados (ou quaisquer outras dependências) estão no controle de origem, por que você também precisa dos scripts gerados?
fonte
A regra geral é não , mas se levar tempo para gerar o código (por causa do acesso ao banco de dados, serviços da web, etc.), você pode querer salvar uma versão em cache no controle de origem e evitar a dor de todos.
Suas ferramentas também precisam estar cientes disso e lidar com o check-out do controle de origem quando necessário, muitas ferramentas decidem efetuar o check-out do controle de origem sem qualquer motivo.
Uma boa ferramenta usará a versão em cache sem tocá-la (nem modificar os intervalos de tempo no arquivo).
Além disso, você precisa colocar um grande aviso dentro do código gerado para que as pessoas não modifiquem o arquivo, um aviso no topo não é suficiente, você tem que repeti-lo a cada dez linhas.
fonte
Também não armazenamos código de banco de dados gerado: uma vez que é gerado, você pode obtê-lo à vontade em qualquer versão dos arquivos de origem. Armazená-lo seria como armazenar bytecode ou algo semelhante.
Agora, você precisa garantir que o gerador de código usado em uma determinada versão esteja disponível! Versões mais recentes podem gerar códigos diferentes ...
fonte
Deixe isso de lado.
Se estiver fazendo check-in dos arquivos gerados, você está fazendo algo errado. O que está errado pode ser diferente, pode ser que seu processo de criação seja ineficiente ou outra coisa, mas eu não consigo ver isso nunca ser uma boa idéia. O histórico deve ser associado aos arquivos de origem, não aos gerados.
Isso só cria uma dor de cabeça para as pessoas que acabam tentando resolver as diferenças, encontrar os arquivos que não são mais gerados pela compilação e depois excluí-los, etc.
Um mundo de dor aguarda aqueles que fazem o check-in dos arquivos gerados!
fonte
Há um caso especial em que você deseja fazer o check-in dos arquivos gerados: quando você pode precisar construir em sistemas onde as ferramentas usadas para gerar os outros arquivos não estão disponíveis. O exemplo clássico disso, e com o qual trabalho, é o código Lex e Yacc. Como desenvolvemos um sistema de tempo de execução que deve ser construído e executado em uma grande variedade de plataformas e arquiteturas, só podemos contar com os sistemas de destino para ter compiladores C e C ++, não as ferramentas necessárias para gerar o código de lexing / análise para nossa definição de interface tradutor. Assim, quando mudamos nossas gramáticas, verificamos o código gerado para analisá-lo.
fonte
chegando um pouco atrasado ... enfim ...
Você colocaria o arquivo intermediário do compilador no controle de versão de origem? No caso de geração de código, por definição, o código-fonte é a entrada do gerador, enquanto o código gerado pode ser considerado como arquivos intermediários entre a fonte "real" e a aplicação construída.
Então eu diria: não coloque o código gerado sob controle de versão, mas o gerador e sua entrada.
Concretamente, trabalho com um gerador de código que escrevi: nunca tive que manter o código-fonte gerado sob controle de versão. Eu diria até que como o gerador atingiu um certo nível de maturidade, não precisei observar o conteúdo do código gerado, embora a entrada (por exemplo, a descrição do modelo) tenha mudado.
fonte
Em alguns projetos, adiciono código gerado ao controle de origem, mas realmente depende. Minha orientação básica é se o código gerado for uma parte intrínseca do compilador, não o adicionarei. Se o código gerado for de uma ferramenta externa, como SubSonic, neste caso, eu adicionaria if ao controle de origem. Se você atualizar o componente periodicamente, quero saber as mudanças na fonte gerada no caso de surgirem bugs ou problemas.
Quanto ao código gerado que precisa ser verificado, o pior cenário é diferenciar manualmente os arquivos e revertê-los, se necessário. Se você estiver usando svn, você pode adicionar um gancho de pré-commit no svn para negar um commit se o arquivo não tiver realmente mudado.
fonte
O trabalho de gerenciamento de configuração (do qual o controle de versão é apenas uma parte) é ser capaz de fazer o seguinte:
O primeiro garante que quando você disser ao cliente ou usuário final "o bug que você relatou na semana passada foi corrigido e o novo recurso foi adicionado", eles não voltem duas horas depois e digam "não, não voltou". Também garante que eles não digam "Por que está fazendo X? Nunca pedimos X".
O segundo significa que quando o cliente ou usuário final relatar um bug em alguma versão lançada há um ano, você pode voltar a essa versão, reproduzir o bug, corrigi-lo e provar que sua correção eliminou o bug em vez de alguma perturbação do compilador e outras correções.
Isso significa que seu compilador, bibliotecas etc também precisam fazer parte do CM.
Portanto, agora, para responder à sua pergunta: se você pode fazer tudo acima, não precisa registrar nenhuma representação intermediária, porque é garantido que você obterá a mesma resposta de qualquer maneira. Se você não puder fazer todos os itens acima, todas as apostas estão canceladas porque você nunca pode garantir que fará a mesma coisa duas vezes e obterá a mesma resposta. Portanto, você também pode colocar todos os seus arquivos .o sob o controle de versão.
fonte
Depende muito. Em última análise, o objetivo é ser capaz de reproduzir o que você tinha, se necessário. Se você puder regenerar seus binários com exatidão, não há necessidade de armazená-los. mas você precisa se lembrar que, para recriar suas coisas, você provavelmente precisará da configuração exata com a qual fez isso em primeiro lugar, e isso não significa apenas seu código-fonte, mas também seu ambiente de construção, seu IDE, talvez até mesmo outras bibliotecas , geradores ou coisas, na configuração exata (versões) que você usou.
Tive problemas em projetos em que atualizamos nosso ambiente de compilação para versões mais novas ou mesmo para outros fornecedores, onde não foi possível recriar os binários exatos que tínhamos antes. É uma dor real quando os binários a serem implementados dependem de um tipo de hash, especialmente em ambiente seguro, e os arquivos recriados de alguma forma diferem por causa de atualizações do compilador ou o que quer que seja.
Então, você armazenaria o código gerado: Eu diria que não. Os binários ou resultados que são lançados, incluindo as ferramentas que você os reproduziu com eu armazenaria. E então, não há necessidade de armazená-los no controle de origem, basta fazer um bom backup desses arquivos.
fonte
A resposta correta é "Depende". Depende de quais são as necessidades do cliente. Se você pode reverter o código para uma versão específica e resistir a qualquer auditoria externa sem ele, então ainda não está em terreno firme. Como devs, precisamos considerar não apenas 'ruído', dor e espaço em disco, mas o fato de que temos a tarefa de gerar propriedade intelectual e pode haver ramificações legais. Você poderia provar a um juiz que é capaz de regenerar um site exatamente da maneira que um cliente o viu há dois anos?
Não estou sugerindo que você salve ou não salve os arquivos gerados, seja qual for a maneira que você decidir se não está envolvendo os Especialistas no Assunto da decisão, provavelmente você está errado.
Meus dois centavos.
fonte
Existem bons argumentos a favor e contra apresentados aqui. Para registro, eu construo o sistema de geração T4 no Visual Studio e nossa opção out-of-the-box padrão faz com que o código gerado seja verificado. Você tem que trabalhar um pouco mais se preferir não fazer o check-in.
Para mim, a principal consideração é diferenciar a saída gerada quando a entrada ou o próprio gerador são atualizados.
Se você não fez o check-in de sua saída, terá que fazer uma cópia de todo o código gerado antes de atualizar um gerador ou modificar a entrada para poder compará-la com a saída da nova versão. Acho que este é um processo bastante tedioso, mas com a saída marcada, é uma simples questão de comparar a nova saída com o repositório.
Nesse ponto, é razoável perguntar "Por que você se preocupa com as mudanças no código gerado?" (Especialmente em comparação ao código-objeto.) Acredito que haja alguns motivos principais, que se resumem ao estado da arte atual, e não a qualquer problema inerente.
Você cria um código manuscrito que combina perfeitamente com o código gerado. Esse não é o caso geral dos arquivos obj atualmente. Quando o código gerado muda, infelizmente é muito comum que algum código escrito à mão precise ser alterado para corresponder. As pessoas geralmente não observam um alto grau de compatibilidade reversa com pontos de extensibilidade no código gerado.
O código gerado simplesmente muda seu comportamento. Você não toleraria isso de um compilador, mas para ser justo, um gerador de código de nível de aplicativo está direcionando um campo diferente de problema com uma gama mais ampla de soluções aceitáveis. É importante verificar se as suposições que você fez sobre o comportamento anterior foram quebradas.
Você simplesmente não confia 100% na saída do seu gerador de uma versão a outra. Há muito valor a ser obtido das ferramentas geradoras, mesmo que elas não sejam criadas e mantidas com o rigor do fornecedor do compilador. A versão 1.0 pode ter sido perfeitamente estável para o seu aplicativo, mas talvez a 1.1 tenha algumas falhas para o seu caso de uso agora. Alternativamente, você altera os valores de entrada e descobre que está exercitando uma nova parte do gerador que não tinha usado antes - você pode se surpreender com os resultados.
Essencialmente, todas essas coisas se resumem à maturidade da ferramenta - a maioria dos geradores de código de aplicativos de negócios não está perto do nível que os compiladores ou mesmo as ferramentas de nível lex / yacc estão há anos.
fonte
Ambos os lados têm argumentos válidos e razoáveis, e é difícil concordar em algo comum. Os Sistemas de Controle de Versão (VCSs) rastreiam os arquivos que os desenvolvedores colocam nele e presumem que os arquivos dentro do VCS são feitos à mão por desenvolvedores e os desenvolvedores estão interessados no histórico e nas mudanças entre qualquer revisão dos arquivos. Essa suposição equaliza os dois conceitos: "Quero obter este arquivo quando fizer o checkout." e "Estou interessado na alteração deste arquivo."
Agora, os argumentos de ambos os lados poderiam ser reformulados assim:
Felizmente, parece que os dois requisitos não são conflitantes fundamentalmente. Com alguma extensão dos VCSs atuais, deve ser possível ter ambos. Em outras palavras, é um falso dilema. Se refletirmos um pouco, não é difícil perceber que o problema decorre da suposição que os VCSs sustentam. Os VCSs devem distinguir os arquivos, que são feitos à mão pelos desenvolvedores, dos arquivos que não são feitos à mão pelos desenvolvedores, mas que estão dentro deste VCS. Para a primeira categoria de arquivos, que geralmente chamamos de arquivos de origem (código), os VCSs fizeram um ótimo trabalho agora. Para a última categoria, os VCSs ainda não tiveram esse conceito, até onde eu sei.
Resumo
Vou usar o git como um exemplo para ilustrar o que quero dizer.
git status
não deve mostrar os arquivos gerados por padrão.git commit
deve incluir arquivos gerados como instantâneos.git diff
não deve mostrar os arquivos gerados por padrão.PS
Os ganchos do Git podem ser usados como uma solução alternativa, mas seria ótimo se o git suportasse nativamente.
gitignore
não atende aos nossos requisitos, pois os arquivos ignorados não irão para os VCSs.enter code here
fonte
Eu argumentaria por. Se você estiver usando um processo de integração contínua que verifica o código, modifica o número do build, constrói o software e o testa, então é mais simples e fácil ter apenas esse código como parte do seu repositório.
Além disso, é parte integrante de cada "instantâneo" que você tira do seu repositório de software. Se for parte do software, deve fazer parte do repositório.
fonte
Eu diria que sim, você deseja colocá-lo sob controle de origem. Do ponto de vista do gerenciamento de configuração, TUDO que é usado para produzir uma construção de software precisa ser controlado para que possa ser recriado. Eu entendo que o código gerado pode ser facilmente recriado, mas pode-se argumentar que ele não é o mesmo, já que os carimbos de data / hora serão diferentes entre as duas compilações. Em algumas áreas, como governo, muitas vezes é necessário que isso seja feito.
fonte
Em geral, o código gerado não precisa ser armazenado no controle de origem porque o histórico de revisão desse código pode ser rastreado pelo histórico de revisão do código que o gerou!
No entanto, parece que o OP está usando o código gerado como a camada de acesso a dados do aplicativo, em vez de escrever um manualmente. Nesse caso, eu mudaria o processo de construção e comprometeria o código para o controle de origem, porque é um componente crítico do código de tempo de execução. Isso também remove a dependência da ferramenta de geração de código do processo de construção, caso os desenvolvedores precisem usar versões diferentes da ferramenta para diferentes ramos.
Parece que o código só precisa ser gerado uma vez, em vez de cada construção. Quando um desenvolvedor precisa adicionar / remover / alterar a forma como um objeto acessa o banco de dados, o código deve ser gerado novamente, da mesma forma que faz modificações manuais. Isso acelera o processo de construção, permite que otimizações manuais sejam feitas na camada de acesso a dados e o histórico da camada de acesso a dados é mantido de maneira simples.
fonte
Eu (lamentavelmente) acabo colocando um monte de fontes derivadas sob controle de origem porque trabalho remotamente com pessoas que não se incomodam em configurar um ambiente de construção adequado ou que não têm as habilidades para configurá-lo para que o fontes derivadas são construídas exatamente da maneira certa. (E quando se trata de autotools Gnu, eu mesmo sou uma dessas pessoas! Não posso trabalhar com três sistemas diferentes, cada um dos quais funciona com uma versão diferente de autotools - e apenas essa versão.)
Esse tipo de dificuldade provavelmente se aplica mais a projetos de meio período, voluntários e de código aberto do que a projetos pagos em que a pessoa que paga as contas pode insistir em um ambiente de construção uniforme.
Ao fazer isso, você está basicamente se comprometendo a construir os arquivos derivados apenas em um site ou apenas em sites configurados corretamente. Seus Makefiles (ou qualquer outro) devem ser configurados para notar onde estão rodando e devem se recusar a derivar novamente as fontes a menos que saibam que estão rodando em um site de construção seguro.
fonte
Se for parte do código-fonte, deve ser colocado no controle de origem, independentemente de quem ou o que o gera. Você deseja que o controle de origem reflita o estado atual do sistema sem ter que gerá-lo novamente.
fonte
Com certeza tem o código gerado no controle de origem, por vários motivos. Estou reiterando o que muita gente já disse, mas algumas razões pelas quais eu faria isso são
fonte
CodeCompileUnit
em uma ordem canônica.Eu deixaria os arquivos gerados fora de uma árvore de origem, mas colocaria em uma árvore de construção separada.
por exemplo, o fluxo de trabalho é
Provavelmente há boas maneiras no Subversion / Mercurial / Git / etc de amarrar o histórico dos arquivos fonte reais em ambos os lugares.
fonte
Parece que existem opiniões muito fortes e convincentes de ambos os lados. Eu recomendaria ler todas as respostas mais votadas e, em seguida, decidir quais argumentos se aplicam ao seu caso específico.
ATUALIZAÇÃO: Eu fiz essa pergunta porque realmente acreditava que havia uma resposta definitiva. Olhando para todas as respostas, eu poderia dizer com alto nível de certeza, que essa resposta não existe. A decisão deve ser tomada com base em mais de um parâmetro. Ler as outras respostas pode fornecer uma orientação muito boa para os tipos de perguntas que você deve se perguntar ao decidir sobre esse assunto.
fonte