Portanto, temos esse enorme arquivo de origem mainmodule.cpp (são 11000 linhas?) Em nosso projeto e toda vez que preciso tocá-lo, encolho-me.
Como esse arquivo é tão central e amplo, ele acumula cada vez mais código e não consigo pensar em uma boa maneira de fazê-lo começar a encolher.
O arquivo é usado e alterado ativamente em várias (> 10) versões de manutenção do nosso produto e, portanto, é realmente difícil refatorá-lo. Se eu fosse "simplesmente" dividi-lo, digamos, para começar, em 3 arquivos, então mesclar as alterações das versões de manutenção se tornará um pesadelo. Além disso, se você dividir um arquivo com um histórico tão longo e rico, rastrear e verificar alterações antigas no SCC
histórico torna-se repentinamente muito mais difícil.
O arquivo contém basicamente a "classe principal" (expedição e coordenação principal do trabalho interno) do nosso programa, portanto, toda vez que um recurso é adicionado, ele também afeta esse arquivo e toda vez que ele cresce. :-(
o que você faria nesta situação? Alguma idéia de como mover novos recursos para um arquivo de origem separado sem atrapalhar o SCC
fluxo de trabalho?
(Observação sobre as ferramentas: usamos C ++ com Visual Studio
; usamos AccuRev
como, SCC
mas acho que o tipo de SCC
realmente não importa aqui; usamos Araxis Merge
para comparar e mesclar arquivos de verdade)
fonte
Respostas:
Encontre um código no arquivo que seja relativamente estável (não mude rapidamente e não varie muito entre as ramificações) e que possa ser uma unidade independente. Mova isso para seu próprio arquivo e, para esse assunto, para sua própria classe, em todas as ramificações. Por ser estável, isso não causará (muitas) mesclagens "estranhas" que precisam ser aplicadas a um arquivo diferente daquele em que foram originalmente criadas, quando você mescla a alteração de uma ramificação para outra. Repetir.
Encontre algum código no arquivo que basicamente se aplique apenas a um pequeno número de ramificações e que possa ser autônomo. Não importa se está mudando rapidamente ou não, devido ao pequeno número de ramificações. Mova isso para suas próprias classes e arquivos. Repetir.
Então, nos livramos do código que é o mesmo em todos os lugares e do código específico para determinadas ramificações.
Isso deixa você com um núcleo de código mal gerenciado - é necessário em qualquer lugar, mas é diferente em todos os ramos (e / ou muda constantemente para que alguns ramos sejam executados atrás de outros), e, no entanto, é em um único arquivo que você está sem êxito, tentando mesclar entre os ramos. Pare de fazer isso. Ramifique o arquivo permanentemente , talvez renomeá-lo em cada ramificação. Não é mais "principal", é "principal para a configuração X". OK, então você perde a capacidade de aplicar a mesma alteração a várias ramificações mesclando, mas esse é o núcleo do código em que a mesclagem não funciona muito bem. Se você tiver que gerenciar manualmente as mesclagens para lidar com conflitos, não há perda em aplicá-las manualmente independentemente em cada ramificação.
Acho que você está errado ao dizer que o tipo de SCC não importa, porque, por exemplo, as habilidades de mesclagem do git são provavelmente melhores do que a ferramenta de mesclagem que você está usando. Portanto, o problema principal, "a fusão é difícil" ocorre em momentos diferentes para diferentes SCCs. No entanto, é improvável que você consiga alterar os SCCs, portanto o problema é provavelmente irrelevante.
fonte
A fusão não será um pesadelo tão grande quanto será quando você obter 30000 arquivos LOC no futuro. Assim:
Se você não pode simplesmente parar de codificação durante o processo de refatoração, você pode deixar este arquivo grande , como é por um tempo, pelo menos, sem adicionar mais código para isso: uma vez que contém uma "classe principal" você poderia herdar-lo e mantê classe herdada ( es) com funções sobrecarregadas em vários novos arquivos pequenos e bem projetados.
fonte
Parece-me que você está enfrentando uma série de cheiros de código aqui. Antes de tudo, a classe principal parece violar o princípio de abrir / fechar . Também parece que está lidando com muitas responsabilidades . Devido a isso, eu assumiria que o código é mais frágil do que precisa.
Embora eu possa entender suas preocupações com relação à rastreabilidade após uma refatoração, espero que essa classe seja bastante difícil de manter e aprimorar e que quaisquer alterações que você faça provavelmente causem efeitos colaterais. Eu suporia que o custo destes supera o custo de refatorar a classe.
De qualquer forma, como o cheiro do código só piora com o tempo, pelo menos em algum momento, o custo destes compensará o custo da refatoração. Pela sua descrição, eu assumiria que você passou do ponto de inflexão.
Refatorar isso deve ser feito em pequenas etapas. Se possível, adicione testes automatizados para verificar o comportamento atual antes de refatorar qualquer coisa. Em seguida, escolha pequenas áreas de funcionalidade isolada e extraia-as como tipos para delegar a responsabilidade.
Em qualquer caso, parece um grande projeto, então boa sorte :)
fonte
A única solução que eu já imaginei para esses problemas segue. O ganho real pelo método descrito é a progressividade das evoluções. Não há revoluções aqui, caso contrário, você estará com problemas muito rapidamente.
Insira uma nova classe cpp acima da classe principal original. Por enquanto, ele basicamente redirecionaria todas as chamadas para a classe principal atual, mas visa tornar a API dessa nova classe o mais clara e sucinta possível.
Feito isso, você tem a possibilidade de adicionar novas funcionalidades em novas classes.
Quanto às funcionalidades existentes, você deve movê-las progressivamente para novas classes à medida que elas se tornam estáveis o suficiente. Você perderá a ajuda do SCC para esse trecho de código, mas não há muito que possa ser feito sobre isso. Basta escolher o momento certo.
Sei que isso não é perfeito, embora espero que ajude, e o processo deve ser adaptado às suas necessidades!
Informação adicional
Observe que o Git é um SCC que pode seguir trechos de código de um arquivo para outro. Ouvi coisas boas sobre isso, para que possa ajudar enquanto você move progressivamente o seu trabalho.
O Git é construído em torno da noção de blobs que, se bem entendi, representam partes de arquivos de código. Mova essas peças em arquivos diferentes e o Git as encontrará, mesmo se você as modificar. Além do vídeo de Linus Torvalds mencionado nos comentários abaixo, não consegui encontrar algo claro sobre isso.
fonte
Confúcio diz: "o primeiro passo para sair do buraco é parar de cavar o buraco".
fonte
Deixe-me adivinhar: dez clientes com conjuntos de recursos divergentes e um gerente de vendas que promove a "personalização"? Já trabalhei em produtos como esse antes. Tivemos essencialmente o mesmo problema.
Você reconhece que ter um arquivo enorme é um problema, mas ainda mais problemas são as dez versões que você precisa manter "atual". Isso é manutenção múltipla. O SCC pode facilitar isso, mas não pode torná-lo correto.
Antes de tentar dividir o arquivo em partes, é necessário sincronizar os dez ramos novamente, para que você possa ver e modelar todo o código de uma só vez. Você pode fazer isso uma ramificação por vez, testando as duas ramificações no mesmo arquivo de código principal. Para impor o comportamento personalizado, você pode usar #ifdef e amigos, mas é melhor usar o if / else comum contra constantes definidas. Dessa forma, seu compilador verificará todos os tipos e provavelmente eliminará o código do objeto "morto" de qualquer maneira. No entanto, você pode desativar o aviso sobre código morto.
Uma vez que existe apenas uma versão desse arquivo compartilhada implicitamente por todas as ramificações, é bastante mais fácil iniciar os métodos tradicionais de refatoração.
Os #ifdefs são principalmente melhores para seções em que o código afetado só faz sentido no contexto de outras personalizações por ramificação. Pode-se argumentar que estes também apresentam uma oportunidade para o mesmo esquema de fusão de agências, mas não se torne uma loucura. Um projeto colossal de cada vez, por favor.
No curto prazo, o arquivo parecerá aumentar. Isto está bem. O que você está fazendo é reunir coisas que precisam estar juntas. Posteriormente, você começará a ver áreas claramente iguais, independentemente da versão; estes podem ser deixados sozinhos ou refatorados à vontade. Outras áreas diferem claramente dependendo da versão. Você tem várias opções neste caso. Um método é delegar as diferenças em objetos de estratégia por versão. Outra é derivar versões de clientes de uma classe abstrata comum. Mas nenhuma dessas transformações é possível desde que você tenha dez "dicas" de desenvolvimento em diferentes ramos.
fonte
Não sei se isso resolve o seu problema, mas acho que você deseja fazer é migrar o conteúdo do arquivo para arquivos menores, independentes um do outro (resumidos). O que eu também entendo é que você tem cerca de 10 versões diferentes do software flutuando e precisa suportá-las sem bagunçar as coisas.
Antes de tudo, não há como isso ser fácil e se resolver em poucos minutos de brainstorming. As funções vinculadas ao seu arquivo são vitais para o seu aplicativo, e simplesmente cortá-las e migrá-las para outros arquivos não salvarão o seu problema.
Eu acho que você só tem estas opções:
Não migre e fique com o que você tem. Possivelmente, saia do emprego e comece a trabalhar em software sério, com bom design, além disso. A programação extrema nem sempre é a melhor solução se você estiver trabalhando em um projeto de longo prazo com fundos suficientes para sobreviver a uma falha ou duas.
Elabore um layout de como você gostaria que seu arquivo fosse, assim que ele for dividido. Crie os arquivos necessários e integre-os ao seu aplicativo. Renomeie as funções ou sobrecarregue-as para obter um parâmetro adicional (talvez apenas um booleano simples?). Depois de trabalhar no seu código, migre as funções necessárias para o novo arquivo e mapeie as chamadas de função das funções antigas para as novas. Você ainda deve ter seu arquivo principal dessa maneira e ainda poder ver as alterações feitas nele, quando se trata de uma função específica que você sabe exatamente quando foi terceirizado e assim por diante.
Tente convencer seus colegas de trabalho com um bom bolo de que o fluxo de trabalho está superestimado e que você precisa reescrever algumas partes do aplicativo para fazer negócios sérios.
fonte
Exatamente esse problema é tratado em um dos capítulos do livro "Trabalhando efetivamente com o código herdado" ( http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 ).
fonte
Eu acho que seria melhor criar um conjunto de classes de comando que mapeiam para os pontos de API do mainmodule.cpp.
Uma vez implementados, você precisará refatorar a base de código existente para acessar esses pontos da API por meio das classes de comando; assim que estiver pronto, você poderá refatorar a implementação de cada comando em uma nova estrutura de classes.
Obviamente, com uma única classe de 11 KLOC, o código provavelmente é altamente acoplado e quebradiço, mas a criação de classes de comando individuais ajudará muito mais do que qualquer outra estratégia de proxy / fachada.
Não invejo a tarefa, mas, com o passar do tempo, esse problema só piorará se não for resolvido.
Atualizar
Eu sugeriria que o padrão de comando é preferível a uma fachada.
É preferível manter / organizar muitas classes de comando diferentes em uma fachada (relativamente) monolítica. O mapeamento de uma única fachada em um arquivo de 11 KLOC provavelmente precisará ser dividido em alguns grupos diferentes.
Por que se preocupar em tentar descobrir esses grupos de fachada? Com o padrão Comando, você poderá agrupar e organizar essas pequenas classes organicamente, para ter muito mais flexibilidade.
Obviamente, ambas as opções são melhores que o arquivo único de 11 KLOC e crescente.
fonte
Um conselho importante: não misture refatoração e correções. O que você deseja é uma versão do seu programa idêntica à versão anterior, exceto que o código fonte é diferente.
Uma maneira poderia ser começar a dividir a menor função / parte grande em seu próprio arquivo e depois incluir um cabeçalho (transformando main.cpp em uma lista de #includes, que soa como um cheiro de código em si * Eu não sou um Guru de C ++), mas pelo menos agora está dividido em arquivos).
Você pode tentar mudar todas as versões de manutenção para o "novo" main.cpp ou qualquer que seja sua estrutura. Novamente: Não há outras alterações ou correções de erros, porque rastrear essas coisas é confuso como o inferno.
Outra coisa: por mais que você queira fazer um grande passe para refatorar a coisa toda de uma só vez, você pode morder mais do que pode mastigar. Talvez apenas escolha uma ou duas "partes", coloque-as em todos os lançamentos e adicione mais valor ao seu cliente (afinal, a refatoração não agrega valor direto, portanto, é um custo que deve ser justificado) e depois escolha outra uma ou duas partes.
Obviamente, isso requer alguma disciplina na equipe para realmente usar os arquivos divididos e não apenas adicionar coisas novas ao main.cpp o tempo todo, mas, novamente, tentar fazer um refatorio massivo pode não ser o melhor curso de ação.
fonte
Rofl, isso me lembra meu antigo emprego. Parece que, antes de entrar, tudo estava dentro de um arquivo enorme (também em C ++). Em seguida, eles o dividiram (em pontos completamente aleatórios usando inclusões) em cerca de três (arquivos ainda enormes). A qualidade deste software foi, como você poderia esperar, horrível. O projeto totalizou cerca de 40k LOC. (contendo quase nenhum comentário, mas MUITO código duplicado)
No final, fiz uma reescrita completa do projeto. Comecei refazendo a pior parte do projeto do zero. É claro que eu tinha em mente uma possível (pequena) interface entre essa nova parte e o resto. Então eu inseri essa parte no projeto antigo. Não refatorei o código antigo para criar a interface necessária, apenas o substituí. Depois dei pequenos passos a partir daí, reescrevendo o código antigo.
Devo dizer que isso levou cerca de meio ano e não houve desenvolvimento da antiga base de código além das correções durante esse período.
editar:
O tamanho ficou em cerca de 40k de LOC, mas o novo aplicativo continha muito mais recursos e presumivelmente menos bugs em sua versão inicial do que o software de 8 anos. Um dos motivos da reescrita foi também que precisávamos dos novos recursos e a introdução deles no código antigo era quase impossível.
O software era para um sistema incorporado, uma impressora de etiquetas.
Outro ponto que devo acrescentar é que, em teoria, o projeto era C ++. Mas não era OO, poderia ter sido C. A nova versão era orientada a objetos.
fonte
OK, então, na maior parte das vezes, reescrever a API do código de produção é uma má ideia para começar. Duas coisas precisam acontecer.
Primeiro, você precisa que sua equipe decida congelar o código na versão atual de produção desse arquivo.
Segundo, você precisa pegar esta versão de produção e criar uma ramificação que gerencia as construções usando diretivas de pré-processamento para dividir o arquivo grande. Dividir a compilação usando as diretivas do pré-processador JUST (#ifdefs, #includes, #endifs) é mais fácil do que recodificar a API. É definitivamente mais fácil para seus SLAs e suporte contínuo.
Aqui você pode simplesmente cortar as funções relacionadas a um subsistema específico da classe e colocá-las em um arquivo, como mainloop_foostuff.cpp, e incluí-lo no mainloop.cpp no local correto.
OU
Uma maneira mais demorada, porém robusta, seria criar uma estrutura de dependências internas com duplo indireção na maneira como as coisas são incluídas. Isso permitirá que você divida as coisas e ainda cuide das co-dependências. Observe que essa abordagem requer codificação posicional e, portanto, deve ser associada aos comentários apropriados.
Essa abordagem incluiria componentes que são usados com base em qual variante você está compilando.
A estrutura básica é que seu mainclass.cpp incluirá um novo arquivo chamado MainClassComponents.cpp após um bloco de instruções como o seguinte:
A estrutura principal do arquivo MainClassComponents.cpp estaria lá para calcular dependências nos subcomponentes como este:
E agora, para cada componente, você cria um arquivo component_xx.cpp.
Claro que estou usando números, mas você deve usar algo mais lógico com base no seu código.
O uso do pré-processador permite que você divida as coisas sem ter que se preocupar com alterações na API, que é um pesadelo na produção.
Depois que a produção é liquidada, você pode realmente trabalhar no reprojeto.
fonte
Bem, eu entendo sua dor :) Eu já participei de alguns desses projetos e não é bonito. Não há uma resposta fácil para isso.
Uma abordagem que pode funcionar para você é começar a adicionar proteções seguras em todas as funções, ou seja, verificar argumentos, condições pré / pós-métodos nos métodos e, eventualmente, adicionar testes de unidade para capturar a funcionalidade atual das fontes. Depois de ter isso, você estará melhor equipado para re-fatorar o código, pois haverá declarações e erros aparecendo alertando você se você esqueceu alguma coisa.
Às vezes, embora haja momentos em que a refatoração pode trazer mais dor do que benefício. Talvez seja melhor deixar o projeto original e em um estado de pseudo manutenção e começar do zero e, em seguida, adicionar gradualmente a funcionalidade da besta.
fonte
Você não deve se preocupar em reduzir o tamanho do arquivo, mas em reduzir o tamanho da classe. Tudo se resume a quase o mesmo, mas faz com que você olhe para o problema de um ângulo diferente (como sugere @Brian Rasmussen , sua classe parece ter muitas responsabilidades).
fonte
O que você tem é um exemplo clássico de um antipadrão de design conhecido chamado blob . Reserve um tempo para ler o artigo que aponto aqui e talvez você encontre algo útil. Além disso, se esse projeto for tão grande quanto parece, considere algum design para impedir o crescimento em código que você não pode controlar.
fonte
Esta não é uma resposta para o grande problema, mas uma solução teórica para uma parte específica:
Descubra onde você deseja dividir o arquivo grande em subarquivos. Coloque comentários em algum formato especial em cada um desses pontos.
Escreva um script bastante trivial que divida o arquivo em subarquivos nesses pontos. (Talvez os comentários especiais tenham incorporado nomes de arquivos que o script possa usar como instruções para dividi-lo.) Ele deve preservar os comentários como parte da divisão.
Execute o script. Exclua o arquivo original.
Quando você precisar mesclar a partir de uma ramificação, primeiro recrie o arquivo grande concatenando as peças novamente, faça a mesclagem e depois divida novamente.
Além disso, se você deseja preservar o histórico do arquivo SCC, espero que a melhor maneira de fazer isso seja informar ao sistema de controle de origem que os arquivos individuais das peças são cópias do original. Em seguida, ele preservará o histórico das seções que foram mantidas nesse arquivo, embora, é claro, também registre que grandes partes foram "excluídas".
fonte
Uma maneira de dividi-lo sem muito perigo seria dar uma olhada histórica em todas as mudanças de linha. Existem certas funções que são mais estáveis que outras? Pontos quentes de mudança, se quiser.
Se uma linha não for alterada em alguns anos, você provavelmente poderá movê-la para outro arquivo sem muita preocupação. Eu daria uma olhada na fonte anotada com a última revisão que tocava uma determinada linha e veria se há alguma função que você possa executar.
fonte
Uau, parece ótimo. Acho que explicar ao seu chefe que você precisa de muito tempo para refatorar a fera vale a pena tentar. Se ele não concorda, desistir é uma opção.
Enfim, o que eu sugiro é basicamente jogar toda a implementação e reagrupá-la em novos módulos, vamos chamar de "serviços globais". O "módulo principal" somente encaminharia para esses serviços e QUALQUER novo código que você escrever os usará em vez do "módulo principal". Isso deve ser possível em um período de tempo razoável (porque é principalmente copiar e colar), você não quebra o código existente e pode fazer uma versão de manutenção por vez. E se você ainda tiver tempo, poderá gastá-lo refatorando todos os módulos antigos dependentes para também usar os serviços globais.
fonte
Minhas simpatias - no meu trabalho anterior, encontrei uma situação semelhante com um arquivo que era várias vezes maior do que aquele com o qual você tem que lidar. A solução foi:
As classes que você cria na etapa 3. provavelmente irão crescer para absorver mais código apropriado à sua função recém-limpa.
Eu também poderia adicionar:
0: compre o livro de Michael Feathers sobre como trabalhar com código legado
Infelizmente, esse tipo de trabalho é muito comum, mas minha experiência é que existe um grande valor em tornar o código de trabalho, mas horrível, incrementalmente menos horrível, mantendo-o funcionando.
fonte
Considere maneiras de reescrever o aplicativo inteiro de uma maneira mais sensata. Talvez reescreva uma pequena seção como um protótipo para ver se sua ideia é viável.
Se você identificou uma solução viável, refatorar o aplicativo adequadamente.
Se todas as tentativas de produzir uma arquitetura mais racional falharem, pelo menos você sabe que a solução provavelmente está redefinindo a funcionalidade do programa.
fonte
Meus 0,05 eurocents:
Redesenhe toda a bagunça, divida-a em subsistemas, levando em consideração os requisitos técnicos e de negócios (= muitas trilhas de manutenção paralelas com base de código potencialmente diferente para cada uma; obviamente há uma necessidade de alta modificabilidade, etc.).
Ao dividir em subsistemas, analise os locais que mais mudaram e separe-os das partes imutáveis. Isso deve mostrar os pontos problemáticos. Separe as partes que mais mudam para seus próprios módulos (por exemplo, dll) de forma que a API do módulo possa ser mantida intacta e você não precise interromper o BC o tempo todo. Dessa forma, você pode implantar versões diferentes do módulo para diferentes ramificações de manutenção, se necessário, mantendo o núcleo inalterado.
O redesenho provavelmente precisará ser um projeto separado, tentando fazê-lo em um alvo em movimento não funcionará.
Quanto ao histórico do código fonte, minha opinião: esqueça o novo código. Mas mantenha a história em algum lugar para poder verificá-la, se necessário. Aposto que você não precisará muito disso desde o início.
Você provavelmente precisará obter a adesão da gerência para este projeto. Talvez você possa argumentar com tempo de desenvolvimento mais rápido, menos erros, manutenção mais fácil e menos caos geral. Algo parecido com "Habilite proativamente a viabilidade de manutenção e futuro de nossos ativos críticos de software" :)
É assim que eu começaria a enfrentar o problema pelo menos.
fonte
Comece adicionando comentários a ele. Com referência a onde as funções são chamadas e se você pode mover as coisas. Isso pode colocar as coisas em movimento. Você realmente precisa avaliar o quão frágil o código o baseia. Em seguida, junte bits comuns de funcionalidade. Pequenas mudanças de cada vez.
fonte
Outro livro que você pode achar interessante / útil é a refatoração .
fonte
Algo que eu acho útil fazer (e estou fazendo agora, embora não na escala que você enfrenta), é extrair métodos como classes (refatoração de objeto de método). Os métodos que diferem nas diferentes versões se tornarão classes diferentes que podem ser injetadas em uma base comum para fornecer o comportamento diferente que você precisa.
fonte
Achei esta frase a parte mais interessante do seu post:
> O arquivo é usado e alterado ativamente em várias (> 10) versões de manutenção do nosso produto e, portanto, é realmente difícil refatorá-lo
Primeiro, eu recomendaria que você usasse um sistema de controle de origem para desenvolver essas versões de manutenção com mais de 10 anos que suportam ramificação.
Segundo, eu criaria dez ramificações (uma para cada uma das suas versões de manutenção).
Já posso sentir você se encolhendo! Mas o controle de origem não está funcionando para a sua situação devido à falta de recursos ou não está sendo usado corretamente.
Agora, na filial em que você trabalha - refatore-o como achar melhor, seguro com o conhecimento de que você não perturbará os outros nove ramos do seu produto.
Eu ficaria um pouco preocupado que você tenha muito em sua função main ().
Em qualquer projeto que eu escreva, eu usaria main () apenas para executar a inicialização de objetos principais - como um objeto de simulação ou aplicativo - nessas classes é onde o trabalho real deve continuar.
Eu também inicializaria um objeto de log de aplicativo principal para uso global em todo o programa.
Finalmente, também adiciono o código de detecção de vazamento nos blocos de pré-processador, para garantir que ele seja ativado apenas nas compilações DEBUG. Isso é tudo que eu acrescentaria ao main (). Main () deve ser curto!
Você diz que
> O arquivo contém basicamente a "classe principal" (expedição e coordenação principal do trabalho interno) do nosso programa
Parece que essas duas tarefas podem ser divididas em dois objetos separados - um coordenador e um despachante.
Quando você os divide, você pode atrapalhar o seu "fluxo de trabalho do SCC", mas parece que aderir estritamente ao seu fluxo de trabalho do SCC está causando problemas de manutenção do software. Abandone-o agora e não olhe para trás, porque assim que você o consertar, você começará a dormir tranquilamente.
Se você não for capaz de tomar a decisão, lute com unhas e dentes com seu gerente - a sua aplicação precisa ser refatorada - e muito pelo que parece! Não aceite não como resposta!
fonte
Como você descreveu, o principal problema é diferenciar pré-divisão versus pós-divisão, mesclando correções de bugs etc. Ferramenta para contorná-la. Não demorará muito tempo para codificar um script em Perl, Ruby etc. para eliminar a maior parte do ruído da pré-divisão diferente contra uma concatenação da pós-divisão. Faça o que for mais fácil em termos de manipulação de ruído:
Você pode fazer isso sempre que houver um check-in, a concatenação é executada e você tem algo preparado para diferir das versões de arquivo único.
fonte
fonte
"O arquivo contém basicamente a" classe principal "(expedição e coordenação principal do trabalho interno) do nosso programa, portanto, toda vez que um recurso é adicionado, ele também afeta esse arquivo e toda vez que cresce."
Se esse grande SWITCH (que eu acho que existe) se tornar o principal problema de manutenção, você poderá refatorá-lo para usar o dicionário e o padrão de comando e remover toda a lógica do switch do código existente para o carregador, que preenche esse mapa, ou seja:
fonte
Eu acho que a maneira mais fácil de acompanhar o histórico da fonte ao dividir um arquivo seria algo como isto:
fonte
Eu acho que o que eu faria nessa situação é um pouco complicado e:
O rastreamento de alterações antigas no arquivo é simplesmente resolvido pelo seu primeiro comentário no check-in, dizendo algo como "split from mainmodule.cpp". Se você precisar voltar a algo recente, a maioria das pessoas lembrará da mudança; se daqui a dois anos, o comentário dirá a eles onde procurar. Obviamente, qual será o valor de voltar mais de dois anos para ver quem mudou o código e por quê?
fonte