Como você define o código elegante? [duplicado]

70

Em uma discussão sobre codificação de qualidade e como você a identifica, me deparei com uma discussão sobre o teste da capacidade de codificação das pessoas fazendo com que elas mostrassem como trocariam dois valores usando um pedaço de código para atingir o objetivo. Duas soluções principais foram produzidas:

  1. Introduza uma variável de reposição para passar a parcela dos valores ou:
  2. Use alguns operadores bit a bit.

Seguiu-se então um argumento sobre o qual era de fato a melhor solução (eu estaria inclinado para a primeira opção enquanto estivesse ciente de que o segundo existe, mas nem sempre pode ser avaliado como esperado dependendo dos valores em questão).

Tendo em mente a história do Mel, o Real Programador , estou interessado em conhecer como você avalia o código como sendo elegante ou não, e é sucinto uma característica chave do código elegante.

    
por temptar 12.04.2017 / 09:31
fonte

22 respostas

76

O bom código deve ser limpo, simples e fácil de entender antes de mais nada. Quanto mais simples e mais limpa ela é, menor a chance de insetos entrarem. Como Saint-Exupéry cunhou, "Perfeição é alcançada, não quando não há mais nada a acrescentar, mas quando não há mais nada para tirar."

Além disso, o código elegante geralmente é o resultado de uma análise cuidadosa do problema e da localização de um algoritmo e design que simplifica muito o código (e geralmente acelera também). Por exemplo. Pérolas de Programação mostra vários exemplos em que uma percepção obtida durante a análise deu um ângulo totalmente diferente de ataque, resultando em uma solução muito simples, elegante e curta.

Mostrar quão inteligente o autor é, só vem depois destes ;-) Micro-otimização de performance (como usar as operações bitwise que você menciona) deve ser usada somente quando é possível provar (com medições concretas) que o pedaço de código em questão é o gargalo, e que a mudança realmente melhora o desempenho (eu vi exemplos em contrário).

    
por 03.08.2011 / 16:03
fonte
47

O código elegante é uma combinação de:

  • Exatidão. IMHO nenhum código errado pode realmente ser elegante.
  • Succinctness. Menos código significa menos para dar errado, menos para entender *.
  • Legibilidade. Quanto mais fácil for entender o código, mais fácil será mantê-lo.
  • Desempenho. Até certo ponto. O código prematuramente pessimizado não pode ser verdadeiramente elegante.
  • Seguindo os padrões estabelecidos da plataforma ou projeto. Quando são dadas duas opções igualmente elegantes, a que está mais próxima do padrão estabelecido é a melhor.
  • Exatamente da maneira que eu faria. Ok, estou brincando, mas é fácil rotular o código que NÃO é como você faria como "deselegante". Por favor, não faça isso - mantenha a mente aberta para código diferente.

Claro, há também o ditado verdadeiro: "Para cada problema existe uma solução simples, elegante e errada".

* Como os comentários abaixo mostram, há alguma contenção no código mais curto. "Sucinto" não significa "no menor número de caracteres possível", significa "expresso de forma breve e clara".

    
por 03.08.2011 / 16:31
fonte
28

Código simples é um código que é tão legível que mesmo programadores novatos podem trabalhar (pelo menos em geral) o que o código está fazendo. (Veja: sintaxe da expressão Ruby )

Código incrivelmente complexo é um código que faz o máximo possível no menor número possível de linhas, sem ter uma preocupação real com a legibilidade (veja: Perl )

Código elegante é um código que faz com que outros desenvolvedores digam "Ah cara, por que eu não pensei nisso ?!" É uma espécie de entre os dois primeiros, com código que pode não ser tão prontamente aparente que seus pais possam lê-lo, mas não algum rabisco arcano que exija um códice para interpretar. Ele faz o trabalho, faz bem , e não deixa as pessoas mantendo o código coçando suas cabeças.

    
por 02.08.2011 / 16:46
fonte
13

Fred Brooks quebra a complexidade de uma solução nas categorias de "complexidade essencial" e "complexidade acidental" . O código perfeitamente elegante, para mim, é o que é todo "complexidade essencial", e não "complexidade acidental". O truque é que diferentes programadores terão idéias diferentes sobre o que é "complexo", então é provável que discordemos sobre se um código é elegante.

Por exemplo, acho que a estrutura do código Lisp é significativamente mais elegante do que a estrutura do código em linguagens semelhantes a C. Por outro lado, a notação de prefixo de Lisp e a construção de árvore de análise explícita violam nossa intuição sobre como as expressões matemáticas devem parecer, o que pode dificultar a leitura do código para as pessoas. Como resultado, muitos programadores consideram que todos os parênteses em Lisp não são "elegantes", mas na verdade são bastante feios. Para alguém que está realmente preocupado sobre como o compilador irá interpretar o código, Lisp pode parecer elegante. Para alguém que está mais preocupado sobre como as pessoas interpretarão o código, Lisp pode parecer feio.

    
por 02.08.2011 / 18:04
fonte
11
A sucessão é um componente importante, mas para mim, para ser chamado de elegante, o código também deve ser facilmente compreensível a ponto de você dizer: "É claro que essa é a maneira óbvia de fazê-lo!" Mesmo se paradoxalmente não é a primeira maneira que você pensou. Se não passar no teste, pode ser chamado de "inteligente" ou "eficiente", mas não elegante.

    
por 02.08.2011 / 15:42
fonte
10

É semelhante à poesia, que é uma linguagem elegante.

Os poetas podem dizer em poucas palavras o que seria necessário para outras páginas e páginas dizerem e não também. Codificadores elegantes podem fazer o mesmo com o código.

Um exemplo típico é comparar uma implementação típica de quicksort em C com quicksort em Haskell:

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) 

(menor e maior pode ser embutido para uma solução de três linhas).

    
por 03.08.2011 / 15:54
fonte
7

A troca XOR é bem conhecida. E todo mundo, que tem pelo menos um pouco da humildade que Dijkstra pediu, dirá a você, é a maneira errada de fazer as coisas. Não só é mais difícil de ler para humanos, mas também para compiladores. Compiladores são relativamente bons em análise de fluxo e alocação de registros e todo tipo de coisas. Tendo um bom compilador, você não pode esperar que toda variável que você criar existirá na pilha / em um registrador a qualquer momento. O que você precisa fazer é expressar as coisas claramente. Em uma linguagem que suporta chamada por referência, este é o o caminho : swap(x, y); .
Esta é a melhor solução (ouso dizer isso, pelo menos dadas as alternativas que você forneceu). É uma declaração one e é autoexplicativa. Não usa voodoo como o swap XOR faz. Não introduz o ruído de uma variável temporária e 3 instruções de atribuição. Isso é algo que acontece dentro do swap. Supondo que seja uma função, um compilador decente in-line esta chamada. Você também pode fazer uma macro. Seja o que for.

O que torna o código verdadeiramente elegante é a falta de redundâncias, é ortogonalidade, é simplicidade. Isso garante sistemas robustos que crescem em cima uns dos outros. Ter grupos de instruções recorrentes em todo o lugar sempre que você quiser que uma troca introduza redundância, não tenha ortogonalidade e falhe simplicidade.

    
por 03.08.2011 / 16:00
fonte
4

É fácil identificar o que o código elegante faz. Você pega o "Por que não pensei nisso?" vibe. Isso é relativo à complexidade do problema e da linguagem usada.

Isso não significa que a melhor ou a solução mais simples seja automaticamente elegante. Simples é muitas vezes uma das suas qualidades. Modificações, embora geralmente mais fáceis, nem sempre mantêm o elagance.

    
por 02.08.2011 / 16:57
fonte
2

Bom é a ausência de Bad. Aplica-se a tudo na vida e o código não é exceção. Assim,

Good code is one that doesn't have a smell! So, it is important for you to see and understand what a code smell is. No joke intended.

Pense nisso. Você diz que você é feliz apenas porque você não está triste ou se foi de sua tristeza. Da mesma forma, você chama algo de bom código, quando não vê nada de ruim no código. Todo aspecto de qualidade do código (capacidade de manutenção, legibilidade, etc.) pode ser alcançado eliminando-se o cheiro do código. E acredite ou não, isso não acontece na primeira vez - acontece iterativamente:)

    
por 02.08.2011 / 19:52
fonte
2

Eu gosto de comparar o código com a mídia impressa aqui.

Você sabe que odeia quando lê artigos simplificados demais. Dumbed down. Poucos fatos, frases simples. Isso se traduz em código que eu ligo para iniciantes: Trivial, ingênuo mesmo, implementação, nada é muito complicado, mas é demorado e cheio de passos desnecessários.

Por outro lado, você conhece esse estilo de torre de marfim. Você lê um livro de filósofos conhecidos. Você lê um artigo científico sobre um assunto complicado: o estilo muitas vezes parece ser muito demorado. Palavras não são reutilizadas, você tem que mostrar que você pode conhecer uma dúzia de sinônimos. Enquanto o conteúdo real pode ser puro, bom, interessante - o estilo de escrita torna difícil de seguir. Esse estilo obscurece a linha original de pensamentos. Este é o código inteligente .

O código elegante está em algum lugar no meio e tão subjetivo quanto as preferências podem ser. Você pode identificar e descrever casos ruins com facilidade, mas a perfeição é diferente para a maioria de nós.

    
por 03.08.2011 / 16:13
fonte
2

Elegância é a minimização da complexidade. Se você puder entregar rapidamente o código para outro programador com habilidades razoáveis e eles puderem continuar o trabalho (e esperamos que atenda ao seu padrão inicial), o código provavelmente será elegante.

O software bem escrito deve permanecer por pelo menos dez anos. A elegância inicial pode ficar assustada com hacks posteriores, mas a duração do código de tempo sobrevive é uma métrica razoável de quão bem foi inicialmente escrita. Código mal escrito ou vai estagnado (e as pessoas hackear em torno dele), ou é re-trabalhado (embora na prática eu vi as pessoas substituem o código elegante com soluções menores porque eles não conseguiram olhar para ele com cuidado).

    
por 03.08.2011 / 18:34
fonte
1

Minha definição é simples, infelizmente você não pode determinar (todas) você mesmo.

O Elegant Code tem os seguintes recursos:

  • Resolve o problema.
  • Posso confiar nos testes de modo que, se eu modificar algum comportamento, um teste será interrompido.
  • Quando eu ou + qualquer outro desenvolvedor + abre o código, é imediatamente fácil de seguir. Quaisquer blocos lógicos não triviais são descritos por um comentário.
  • As coisas simples são simples, as coisas difíceis são possíveis.
  • Alguém mais está disposto a assumir o desenvolvimento do código, embora eu ainda esteja lá. Sem ser forçado.
por 03.08.2011 / 18:21
fonte
0

Com que facilidade a maioria dos desenvolvedores pode lê-lo? Quão fácil é mudar?

Como resultado, eu definitivamente concordo com você que o opton 1 é significativamente mais elegante.

A opção 2 é inteligente e demonstra um bom conhecimento dos operadores. Também economiza um pequeno pedaço de memória. Útil, talvez, em casos excepcionais, e vale a pena um desenvolvedor ser capaz de fazer. Mas não no seu caso médio de 99%.

    
por 02.08.2011 / 15:43
fonte
0

Tinha que ser consistente . Tinha que haver algum tipo de padrão nele. E quando você precisar quebrar esse padrão, divida-o de maneira consistente, de modo que, em geral, ainda haja algum tipo de padrão.

Se alguém aponta para o seu código e pergunta por que você está fazendo dessa maneira, e sua resposta é "Eu não sei, estou apenas fazendo dessa forma porque é assim que eu aprendi / porque é assim que todo mundo está fazendo " então esse código pode ser elegante ou não elegante . No entanto, se você pode explicar por que o código é assim, por que você escolheu codificar dessa forma, por que as outras alternativas não são tão atraentes, então você pode ter certeza de que o código é elegante . / p>     

por 02.08.2011 / 16:01
fonte
0

Eu fui blasé no meu comentário no topo, mas para mim o código elegante é aquele que afeta meus sentidos muito mais do que a maioria.

Produz uma reação positiva ao alcançar os objetivos, sendo ao mesmo tempo curta e direta, simplicidade, mas com propósito e poder, elegante, simétrica e um pouco "fora da caixa" na abordagem. Incorre em um elemento de surpresa. O método e o algoritmo não são tão complexos (pelo menos superficialmente) que atrapalhem sua compreensão.

O código elegante é mais do que a soma de suas partes. Às vezes, o código elegante parece quase funcionar com os dados, em vez de usar a força bruta ou mapear os dados em outra forma. Para mim, a elegância geralmente vem em um pacote independente - uma única função, poucas ou nenhuma chamada externa, nem muito longa nem muito curta.

Por exemplo, eu vi métodos de classificação que eu chamaria de elegantes. E códigos / algoritmos elegantes para desenhar fractais de maneiras incomuns, mas altamente eficientes - combinando beleza visual e codificando elegância!

    
por 02.08.2011 / 16:45
fonte
0

O código elegante usa a inteligência para realizar algo com muito menos código do que a maioria das pessoas acharia possível, mas de uma maneira que seja legível e óbvia em retrospectiva e não se pareça com o code-golf.

    
por 02.08.2011 / 17:01
fonte
0

Pessoalmente, acho que o código elegante é superestimado. Mas eu trabalho no mundo dos bancos de dados, onde o código de desempenho é de importância crítica e o código "elegante" no contexto do código SQL mais frequentemente do que não (pelo menos na minha experiência) tem um desempenho ruim. Eu me encolho toda vez que ouço alguém que quer escrever um código SQL elegante.

No geral, eu ainda acho que lutar pela elegância é ridículo. Em primeiro lugar, ninguém pode defini-lo adequadamente. O que você quer é um código que funcione corretamente, tenha bom desempenho, seja de fácil manutenção e, em seguida, elegante seja um quarto distante se ele chegar à lista.

    
por 02.08.2011 / 20:22
fonte
0

O código elegante não é o mesmo que o design elegante, embora haja um cruzamento entre os dois.

Como você define uma pintura elegante? É lindo de se ver, perfeitamente legível, faz todo o sentido é fácil de manter e só faz o trabalho.

O design elegante ajuda no código elegante. Você não pode ter código elegante sem um bom design, mas você pode ter um código feio com um bom design. Muito melhor escrever se can_can_add_apples_to_my_basket (20) então   add_apples_to_basket (20) outro  render_not_enough_room_to_add_apples (20) fim em seguida, escreva as duas condições se potencialmente poderiam ser reutilizáveis onde quer que você as precisasse para o que você precisava delas (esse é o bit de design)

código que sais se b.count + 20 < = b.max então   b + = 20 outro   raise ("muitas maçãs") fim

Você ainda tem os 2 métodos (count e max), então você ainda tem um bom design, mas o código é feio e sem sentido, difícil de manter sem o conhecimento do sistema e totalmente ambíguo

    
por 03.08.2011 / 06:00
fonte
0

Para ser honesto, raramente há uma boa razão para trocar o valor de duas variáveis, e não é realmente uma coisa "elegante" de se fazer, não importa como você faça isso.

O código elegante não é sobre o código em si, é realmente sobre o que o código faz e como ele faz isso. Pessoalmente, penso que este é um mau exemplo para determinar o que é "código elegante", uma vez que a coisa que está a ser feita não é em si mesma elegante. Eu acho que o código Haskell é tipicamente elegante, porque ele (na maioria das vezes) lida com valores imutáveis . No entanto, os algoritmos que utilizam o estado mutável podem, de fato, ser escritos elegantemente também (e geralmente não parecem tão quentes em Haskell).

    
por 03.08.2011 / 09:56
fonte
0

Depende realmente de quem você pergunta. Alguém vindo de um background matemático muitas vezes prefere um código que um programador experiente possa achar problemático. Isso faz com que pareça muito subjetivo.

Além disso, você descobrirá que idiomas diferentes têm maneiras diferentes de resolver o mesmo problema. Em Python, por exemplo, trocar duas variáveis é trivial: x, y = y, x

Na prática, a maioria dos programadores concorda que existem alguns critérios comuns:

  • o código elegante deve ser o mais curto possível
  • mas tão detalhado quanto necessário
  • deve ser fácil acompanhar
  • cada declaração deve ser fácil de entender
  • nenhuma declaração deve parecer redundante ou supérflua
  • o código deve seguir os idiomas da linguagem
  • não deve fazer uso de abstrações gotejantes

Esta é uma visão muito pragmática da elegância. O código não deve ser "inteligente" ou falha nesses critérios. Mas será sustentável e mais fácil de ajustar e ampliar.

Dito isto, existe um código que pode ser uma obra de arte, apesar de falhar na maioria das regras desta lista. O código "inteligente" geralmente se enquadra nessa categoria. É muito denso, muitas vezes depende de uma compreensão completa das implementações subjacentes (digamos, gerenciamento de memória, ou a implementação exata do compilador), mas, no entanto, evoca um fascínio sublime.

Existe uma diferença entre a elegância que você encontraria em Outros scripts do Perl Hacker versus o código que você gostaria de usar na produção. Esta é a razão pela qual você nunca iria querer que Mel estivesse em seu time, mesmo que você pudesse chamar a sua grande obra elegante.

    
por 03.08.2011 / 15:33
fonte
0

Entender código elegante deve ser como resolver um quebra-cabeça. Deve ser difícil de entender no começo, então é muito fácil de entender depois de ter "entendido".

Há um trade-off - as pessoas que não entendem o assunto ficam coçando as cabeças, enquanto as pessoas que o entendem acham isso óbvio, em retrospecto.

Quanto à troca de variáveis, nenhuma será particularmente elegante. Não há complexidade para domar aqui, então não há espaço para uma solução "elegante".

    
por 03.08.2011 / 17:39
fonte
-2
isElegant(code)
{
  return isSimple(code) && isReadable(code) && code.reducesComplexity();
}
    
por 02.08.2011 / 20:37
fonte