Reformatação e controle de versão


23

A formatação de código é importante. Mesmo o recuo é importante . E a consistência é mais importante que pequenas melhorias. Mas os projetos geralmente não têm um guia de estilo claro, completo, verificável e aplicado desde o primeiro dia, e grandes melhorias podem chegar a qualquer dia. Talvez você ache isso

SELECT id, name, address
FROM persons JOIN addresses ON persons.id = addresses.person_id;

poderia ser melhor escrito como / é melhor escrito do que

SELECT persons.id,
       persons.name,
       addresses.address
  FROM persons
  JOIN addresses ON persons.id = addresses.person_id;

enquanto trabalhava na adição de mais colunas à consulta. Talvez essa seja a mais complexa das quatro consultas em seu código ou uma consulta trivial entre milhares. Não importa quão difícil seja a transição, você decide que vale a pena. Mas como você controla as alterações de código nas principais alterações de formatação? Você pode simplesmente desistir e dizer "este é o ponto em que começamos novamente" ou pode reformatar todas as consultas em todo o histórico do repositório.

Se você estiver usando um sistema de controle de versão distribuído como o Git, poderá reverter para o primeiro commit de todos os tempos e reformatar o caminho para o estado atual. Mas é muito trabalho, e todo mundo teria que interromper o trabalho (ou estar preparado para a mãe de todas as fusões) enquanto isso acontecia. Existe uma maneira melhor de alterar o histórico que oferece o melhor de todos os resultados:

  • Mesmo estilo em todas as confirmações
  • Trabalho de mesclagem mínima

?

Para esclarecer, não se trata de práticas recomendadas ao iniciar o projeto, mas o que deve ser feito quando uma grande refatoração for considerada uma Boa Coisa ™, mas você ainda deseja um histórico rastreável? Nunca reescrever o histórico é ótimo se for a única maneira de garantir que suas versões sempre funcionem da mesma forma, mas e os benefícios do desenvolvedor de uma reescrita limpa? Especialmente se você tiver maneiras (testes, definições de sintaxe ou um binário idêntico após a compilação) para garantir que a versão reescrita funcione exatamente da mesma maneira que a original?


24
Por que você gostaria de reescrever a história? Isso anula o objetivo do controle de versão. Você deseja garantir que o aplicativo enviado há 3 meses corresponda à revisão xxxxxx sem a menor dúvida. Mesmo reformatação trivial é inaceitável.
— Simon Bergot

5
Eu gostaria de comentar que eu faço isso com a tag "Reformatar. Nenhuma mudança funcional"
— Rig

3
Em um tópico não relacionado, parece que você estava sugerindo reescrever o histórico do Git reformatando todo o código. Não dê idéia às pessoas, reescrever o histórico do Git é ruim para 99,9% dos casos. A reformatação não é o caso da borda de 0,1%.
— Andrew T Finnell

4
Em algumas línguas (estou olhando para você, Python), a reformatação pode alterar o funcionamento lógico do código. Você precisaria analisar todos os idiomas armazenados no seu VCS para rastrear e ignorar as reformatações com segurança.
— Joris Timmermans

3
Reformas são alterações de código e devem ser confirmadas como tal.
— precisa

Respostas:


26

Faça a reformatação como confirmações separadas. Isso interferirá minimamente no histórico, e você poderá ver rapidamente quais confirmações estão apenas reformatando e que realmente alteram o código. Poderia distorcer git blamee semelhante, mas se apontar para um commit somente de reformatação, é bastante simples procurar a alteração anterior antes disso.


Vi projetos descarrilados há semanas, porque um dos desenvolvedores achou que era uma boa ideia. Se você fizer isso, entenda os riscos com antecedência e decida exatamente até onde irá a formatação. Eu acho que o mjfgates tem a resposta certa.
— Johntron 18/01/16

1
Parece que a equipe em questão tem problemas maiores que a formatação de código. Mas sim, eu não recomendo fazer isso, a menos que você precise. Se você quiser reformatar as alterações, ainda assim, seria melhor fazê-las como confirmações separadas do que misturadas com alterações funcionais.
— harald

Sim, muitos problemas: o PI só quer alertar os novos desenvolvedores de que não é tão simples quanto parece. As ferramentas de reformatação em massa são arriscadas (especialmente se você construí-lo com regex - pelo menos usa o AST), e se você se preocupa com a revisão de código e o rastreamento de erros, ele pode realmente atrapalhar seu processo. Pessoalmente, escrevo meu código para ser consistente com o estilo de cada arquivo, embora não me importe em revisar códigos quando algumas funções são reformatadas. Muitos desenvolvedores ficam presos no estilo do código e negligenciam os problemas maiores como arquitetura, processo, ferramentas etc.
— Johntron

Na programação, nada é tão simples como parece :)
— harald

13

Não reescreva a história do VCS: é contra os princípios do VCS.

Não tente automatizar a correção da formatação: está tratando os sintomas, não o problema real (= desenvolvedores que não seguem os padrões de codificação).

Defina o padrão de codificação e as melhores práticas de formatação em um documento comum e peça a todos os desenvolvedores que concordem.

Você menciona o Git, o que é ótimo, porque é distribuído. Com um DVCS, é muito fácil aplicar as melhores práticas por meio do fluxo de trabalho do gatekeeper . Os gatekeepers rejeitam propostas de mesclagem (= solicitações de recebimento no Git) que não estão em conformidade com as diretrizes comuns. E quero dizer rejeitar , em negrito, caso contrário, o codificador violado não se preocupará em seguir as regras e continuar repetindo os mesmos erros.

Essa técnica funciona bem para mim. Os programadores desejam que seu trabalho seja mesclado; portanto, após alguns erros no começo, eles começam a seguir as regras.

De acordo com a correção da base de código existente ... eu recomendo fazer isso gradualmente, talvez módulo por módulo, ou como faz sentido para o seu projeto. Teste com cuidado em cada etapa. Pode parecer estúpido, mas erros acontecem mesmo com mudanças triviais, como apenas a formatação, portanto, esteja preparado para alguns pequenos inchaços na estrada.


1
Voto negativo, porque o autor afirma claramente que isso ocorre no contexto de projetos que não começaram com "... um guia de estilo claro, completo, verificável e aplicado desde o primeiro dia". Ele não pode tratar o problema real, porque já aconteceu. Eu concordo com você embora :)
— Johntron

2
rejeitar significa que haverá uma luta entre os humanos e o robô. Esteve lá. Mais cedo ou mais tarde, o robô exigirá que um código realmente complexo seja formatado de maneira ilegível. Exemplos: uma string Java é de fato uma instrução SQL, mas o robô não sabe disso; o espaço em branco antes do fechamento de parênteses pode conter informações sobre a estrutura do código para humanos, mas não para o robô; parâmetros da função obter dividido em várias linhas da forma mais sem sentido ...
— 18446744073709551615

9

A resposta para sua pergunta real é: "Você não". Não conheço nenhuma ferramenta SCM atual que possa rastrear alterações na lógica do código formatado de uma maneira, através de uma grande alteração de formatação e de outras alterações após o código ser formatado da nova maneira. E, você sabe disso, perder o histórico de um pedaço de código não é bom.

Consequentemente, vou contradizer um pouco sua primeira frase. Código formatação não importa que muito. Pretty é legal, mas não é para isso que estamos aqui. Eu entendo, assim como qualquer pessoa, que ser despejado no antigo código variante K&R de alguém com os dois espaços recuados é uma porcaria (1), mas ... a formatação não é realmente um obstáculo para entender o que está acontecendo, a menos que seja algo excepcionalmente patológico. E, nesse caso, você terá problemas para alterar o código de qualquer maneira e não deve incomodá-lo.

Portanto, não vale a pena fazer alterações no código estabelecido estritamente para reformatá-lo. Mudando os nomes das variáveis, dividindo funções longas, todas as coisas boas de refatoração que alteram o conteúdo, sim, mas não APENAS reformatando.

1) - Eu já possuía o Windows Clipboard Viewer por um tempo. A coisa toda era um módulo C de 150k. Encontrei um local em que diferentes pessoas usaram, penso eu, cinco estilos de aparelhos diferentes, a trinta linhas uma da outra. Mas essa seção de coisas funcionou. Eu carreguei uma impressão desse pedaço de código por dez anos, mas não o cutuquei porque esse histórico importava, e esse código estava em pelo menos três árvores de origem (Windows 3.x, NT, futuro 95) que viviam em diferentes edifícios.


No passado, usando hg, descobri que a mesclagem por peças é uma ferramenta inestimável para lidar com mesclas complicadas de re-fatores . Normalmente, o que eu faria é mesclar as confirmações antes do grande re-fator, depois mesclar o grande re-fator e, finalmente, mesclar as confirmações desde o re-fator. Cada uma dessas três fusões por conta própria é muito mais fácil do que tentar desembaraçar a bagunça resultante de todas as fusões de uma só vez.
— Mark Booth

Eu concordo totalmente! Além disso, já vi muitos desenvolvedores exagerarem (uma versão mais nova de mim mesmo) na reformatação e no estilo de código, e eles acabam apresentando defeitos. Uma vírgula / ponto-e-vírgula ausente aqui, declarações de variáveis ​​movidas para o topo das funções, loops de for alterados para for-each's - todos podem introduzir erros sutis. É necessária uma quantidade enganosa de habilidade para fazer essas alterações com segurança.
— Johntron 18/01/16

4

Mas como você controla as alterações de código nas principais alterações de formatação?

Alterações de formatação são alterações de código; trate-os como faria com qualquer outra alteração no seu código. Qualquer um que tenha trabalhado em um projeto significativo provavelmente já viu bugs e outros problemas criados quando alguém decidiu "apenas" reformatar algum código.

Mas é muito trabalho, e todo mundo teria que interromper o trabalho (ou estar preparado para a mãe de todas as fusões) enquanto isso acontecia.

Por que você tem que reformatar tudo ao mesmo tempo? Especialmente se a reformatação não alterar o significado do código, você poderá reformatar os arquivos individualmente e registrá-los à medida que avança. Melhor, peça a todos da equipe que concordem com um estilo (caso contrário, não há sentido em reformatar de qualquer maneira) e peça a todos que cuidem da reformatação no decorrer de seus outros trabalhos. Depois de um tempo, você terá coberto a maior parte do código sem interromper o restante do projeto.


1

Existem duas abordagens viáveis ​​que eu já vi para isso.

1. Reformate o código no commit-hook

Embora inicialmente seja arrepiante alterar o código após o envio , se o procedimento de reformatação (por exemplo, astyle ) não prejudicar o código, será uma operação segura. Com o tempo, toda a equipe perceberá que todo o código parece o mesmo. Claramente, ter testes abrangentes de unidade / automatizados garantirá que nada ocorra.

2. Reformatação única de todo o código

Isso é mais perigoso na minha experiência e dificulta os problemas de rastreamento no big bang, mas é possível. A execução de todos os testes depois é essencial. Para o estilo de codificação, a maioria das diferenças gira em torno do uso de espaço em branco - recuo ou novas linhas. Uma ferramenta de mesclagem decente deve poder ser instruída a ignorar todas as diferenças de espaço em branco, portanto, isso ajudará nas mesclagens.


1
A opção um não ativaria o ripple em grande parte da base de código, resultando rapidamente no mesmo big bang de alterar cada arquivo?
— Sinal

@Sign: Exatamente o que quero dizer - Quando o gancho de confirmação muda, seu histórico pode se deteriorar para algo quase inútil. A formatação que não altera a funcionalidade não deve ser uma confirmação, deve ser transplantada ao longo do histórico do código.
— L0b0

1
Se o IDE o suportar, também haverá 3) o formato automático do IDE salvo. Em seguida, basta usar as mesmas configurações em todos os lugares - isso é mais fácil se você usar o padrão com o IDE.

Eu fiz essas duas abordagens. A primeira abordagem é muito intrusiva, pois haverá várias alterações sempre que um novo arquivo for confirmado pela primeira vez. A segunda abordagem é melhor para a equipe, como arrancar uma bandaid rapidamente.
— Druska 8/04
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.