hginit - #ifdefs ridículo

8

Eu estava lendo a introdução mercurial de Joel Spolsky quando me ocorreu:

"E agora o que eles fazem é o seguinte: cada novo recurso está em um grande bloco #ifdef. Assim, eles podem trabalhar em um único tronco, enquanto os clientes nunca veem o novo código até que seja depurado e, francamente, isso é ridículo".

Por que isso é tão ridículo de qualquer maneira, não é isso, se nada mais, simplesmente mais simples de lidar? Não é nada chique, mas faz o truque - pelo menos se você já é "casado" com subversão.

Qual é a desvantagem? Eu meio que não entendo a discussão.

panny
fonte
não é ridículo quando você tem apenas uma ou duas opções, mas eu tive que lidar com enormes cadeias de grupos bizarramente inter-aninhados de ifdefs e é uma abominação tentar entender, e se você tivesse que lidar com isso, você achar isso ridículo também. Você acha código impulso modelo complicado é difícil de ler ......
Whatsisname

Respostas:

20

Penso que a resposta é dada na frase subsequente:

Manter o código estável e de desenvolvimento separado é precisamente o que o controle do código-fonte deve permitir.

Usando #ifdefblocos, você está emulando a funcionalidade de um sistema de controle de origem com um pré-processador C. É a ferramenta errada para o trabalho.

A desvantagem é que você provavelmente acaba duplicando muito código (pense em definições de funções inteiras uma vez dentro, uma vez fora do #ifdef) ou tenha um código ilegível (pense nas #ifdeflinhas únicas incluídas em uma função - possivelmente repetidamente).

Na primeira variante, você acaba corrigindo bugs duas vezes (o que não seria necessário se você pudesse mesclar as correções do ramo estável ao ramo dev), enquanto no segundo o objetivo original de separar ramos estável e dev não era realmente alcançado .

blubb
fonte
2
+1: Nos anos 80, eu tinha um depurador que rodava em praticamente qualquer sistema UNIX que você possa imaginar. Antes da versão 4, o código estava cheio #ifdefs. Juro que fez meus olhos sangrarem só de olhar. Para a versão 4, fui para uma arquitetura conectável usando arquivos separados e também comecei a usar o RCS (ou era o SCCS?). A vida ficou muito melhor e os novos recursos foram muito mais fáceis de desenvolver. (Mas o menino que eu nunca gostaria que tivéssemos git ou hg naqueles dias.)
Peter Rowell
Conheço o inferno #ifdef por experiência própria! Concordo que deve ser evitado como uma substituição do controle de versão.
Giorgio
3

Tendo mantido o código que era o ninho de #ifdefs de um rato (embora por razões diferentes), é ridículo; torna o código muito mais difícil de ler e muito mais difícil de manter, especialmente ao testar em várias condições.

John Bode
fonte
Sim, eu fiz isso também e foi horrível.
detly
1

Ele assume que todo o novo código pode ser gravado sem tocar no código existente. Muitas vezes, a única maneira de fazer isso é repetir-se muito. (um novo método para um similar, mas não exatamente o mesmo, por exemplo).

Uma das principais vantagens do VCS distribuído é que incentiva a equipe a trabalhar em seu próprio ramo de recursos e a não se preocupar com o trabalho em conflito com outras pessoas. Essa estratégia nega essa vantagem.

Para mim, isso parece ridículo, pois eles parecem estar deliberadamente abusando das ferramentas. Se você vai fazer a troca, certamente vale a pena aprender a usá-las.

Tom Squires
fonte
3
esta não se limita a DVCS
James
Não, não assume isso. Mesmo com lugares estratégicos #ifdef, você pode tocar no código existente, mas deixar a versão antiga intacta em um #else.
tdammers
1

#ifdefcódigo não é ridículo, mas - triste e terrível. E é (hoje) o diagnóstico para o desenvolvedor

Bem, Joel selecionou em "Reeducação do Subversion" The Bad Way (tm) da argumentação - ele criou uma situação especial e degenerada com usuários especialmente selecionados e usa esse caso de uso como justificativa para a tese "Subversion suxx"

O código spaghetti suxx mais, código incontrolável e ilegível é mais perigoso do que gastar algum tempo na reeducação de "Right Merge" no Subversion - "Merge frequentemente, idiotas !!!" Ramificação e mesclagem bidirecional eram possíveis e utilizáveis ​​no Subversion <1.5, agora (após a introdução do mergeinfo) a mesclagem se tornou ainda mais fácil e confortável . Uma pequena sobrecarga de monitoramento de árvores "interessantes" e fusões sincronizadas (geralmente !!!) é um preço justo para o desenvolvedor, que recebe em troca um código compacto, limpo e depurável.

Lazy Badger
fonte
1

O que ele está descrevendo é na verdade um FeatureToggle , e pode haver boas razões para usá-lo em vez de ramificações de recurso. O problema é com o uso #ifdef. Sem um gerenciamento muito bom, eles podem facilmente se tornar uma grande bagunça espalhados por toda a base de código.

Considere o seguinte:

  1. Quando você remove um #ifdef? - Tem certeza de que não há builds que ainda excluam esse recurso? Também não é para aquele cliente (bem pago) para quem você faz algumas construções especiais?
  2. Quem é responsável por remover o #ifdef? - O desenvolvedor que criou o recurso? Você tem certeza de que ele se lembrará quatro semanas depois da linha, para verificar se o switch não está excluído em nenhuma compilação e pode ser removido com segurança? Ele estará confiante de que é seguro remover o #ifdef? E a outra tarefa extremamente urgente, que não tem prioridade sobre remover um mísero #ifdef?

Minha experiência diz que essas coisas #ifdefficarão para sempre, espalhadas.

Bjarke Freund-Hansen
fonte
1

Por experiência (em um grande projeto em uma base de código de mais de 600.000 linhas, que foi mantida fora dos lançamentos por três anos usando #ifdefs), meus argumentos contra seu uso seriam:

  • Eles reduzem a legibilidade do código - particularmente porque alguns IDEs insistem em colocá-los no início da linha ignorando o nível de indentação.
  • Eles adicionam complexidade, tanto aos desenvolvedores que trabalham no recurso segregado quanto aos desenvolvedores que tentam contorná-los.
  • Essa complexidade adicional diminui a produtividade - no nosso caso, estou convencido de que isso adicionou vários meses ao projeto.
  • Removê-los assim que o recurso for lançado não é uma tarefa de custo zero - no nosso caso, foi uma tarefa de uma semana para alguém passar e remover todos os se #ifdefresolver os conflitos com o código que foi adicionado em #elseifs.

Em suma, foi um dia glorioso em que migramos para o Mercurial - ainda temos uma base de código enorme e muito complexa, mas pelo menos podemos ramificar-se com eficiência agora.

Gato feliz
fonte