Classificando um algoritmo: legibilidade vs. compactação [fechado]

4

Considere a seguinte pergunta de exame / entrevista:

Implemente a função strcpy () em C: void strcpy(char *destination, char *source);

A função strcpy copia a cadeia C apontada por source na matriz apontada por destination , incluindo o caractere nulo de terminação. Suponha que o tamanho da matriz apontada por destination seja longo o suficiente para conter a mesma cadeia C que source e não se sobreponha na memória com source .

Digamos que você fosse o entrevistador \ examinador, como você classificaria as seguintes respostas para essa pergunta?

1)

void strcpy(char *destination, char *source)
{
  while (*source != '
void strcpy(char *destination, char *source)
    {
       while (*(destination++) = *(source++)) ;
    }
') { *destination = *source; source++; destination++; } *destination = *source; }

2)

void strcpy(char *destination, char *source)
{
  while (*source != '
void strcpy(char *destination, char *source)
    {
       while (*(destination++) = *(source++)) ;
    }
') { *destination = *source; source++; destination++; } *destination = *source; }

A primeira implementação é direta - é legível e amigável ao programador.

A segunda implementação é mais curta (uma linha de código), mas menos compatível com o programador; Não é tão fácil entender como esse código está funcionando e, se você não estiver familiarizado com as prioridades desse código, será um problema.

Eu estou querendo saber se a primeira resposta mostraria mais complexidade e pensamento mais avançado, aos olhos do entrevistador, embora ambos os algoritmos se comportem da mesma forma, e embora a legibilidade do código seja considerada mais importante do que a compactação do código. Parece-me que, desde a criação de um algoritmo, esse compacto é mais difícil de ser implementado, ele mostrará um nível de pensamento mais alto como resposta em um exame. No entanto, também é possível que um entrevistador / examinador considere a segunda resposta não boa, porque não é legível.

Eu também gostaria de mencionar que isso não é específico para este exemplo, mas geral para legibilidade de código versus compacidade ao implementar um algoritmo, especificamente em entrevistas de exames.

    
por amiregelz 02.09.2012 / 17:11
fonte

8 respostas

8

A segunda resposta mostra que o desenvolvedor entende melhor os casos de borda C. No entanto, a primeira versão é mais fácil de ler e entender porque não requer compreensão desses casos de borda.

Se você for perguntado, pergunte ao entrevistador ou ao examinador o que eles estão procurando. Em caso de dúvida, vá para o código legível mais de compacidade de cada vez. Entrevistadores e examinadores podem chegar rapidamente à tomada de decisões, facilitando a ajuda deles.

Se o entrevistador ou o examinador quiser mais, faça a versão legível primeiro, depois dê a segunda versão e explique por que ela funciona. Isso também ajudará você, porque você pode fazer saltos conceituais mais curtos.

    
por 02.09.2012 / 17:26
fonte
7

Tudo depende dos requisitos para esse pedaço de código.

  • É para ser rápido?
  • É para usar memória mínima?
  • É para ser confiável?
  • Era para ser sustentável?

A outra coisa que você precisa considerar é a diretriz:

Make it right, then make it fast

O primeiro exemplo seria a primeira implementação ideal da função que satisfaria os requisitos 3 rd e 4 th na minha lista acima. Também seria suficiente para um aplicativo que não fosse crítico no tempo ou com memória limitada, etc. O segundo exemplo poderia ser o que você codificaria se precisasse satisfazer o 1 st e 2 nd requisitos ou você mais tarde descobriu problemas com o seu código inicial (improvável neste caso específico).

No que diz respeito ao testador, a complementação real não deve ser um fator para determinar se o código passa nos testes ou não. Tudo o que importa é que:

  1. Produz o resultado correto
  2. Faz isso em um tempo "razoável" (que varia de aplicativo para aplicativo)
  3. Usa uma quantidade "razoável" de recursos do computador (idem)

No entanto, ao reler sua pergunta, vejo que você está usando a palavra "testador" para a pessoa que conduz a entrevista. Neste caso, como você está olhando para o código para julgar o nível de habilidade ou competência do programador, o segundo exemplo seria "melhor", pois mostra que o programador entende como funciona o ponteiro e a incrementação do ponteiro.

A ressalva é que, a menos que o código seja realmente "escreva uma vez" (ou seja, ele nunca será examinado novamente), você deseja o código no primeiro exemplo.

    
por 02.09.2012 / 17:27
fonte
6

Em C, a expressão x ++ = y ++ é extremamente comum e, portanto, de fácil compreensão, e a IMO deve ser preferida ao longo da maior distância x = y; x ++; y ++; sempre que possível, pois expressa a INTENÇÃO melhor. Isso deixa a verificação para encerrar o loop.

while(*source != '
while(*source)
')

vs

while(*destination++ = *source++){}

vs

while(*source != '
while(*source)
')

Compreender o 2º e o 3º depende da compreensão de duas coisas, que C considera zero como falso e tudo diferente de zero para ser verdade e que os operadores de atribuição retornam um resultado.

Ambos devem estar enraizados até mesmo em um programador C júnior e serem facilmente escolhidos por aqueles que vêm de outro idioma.

Resumindo, eu não considero o segundo mais difícil de ler, e de fato acho o primeiro mais difícil de ler no contexto de um programa em C - em uma linguagem sem o ++ primeiro seria necessário, claro, mas programar em linguagem como se fosse linguagem b é confuso. A pergunta "por que esse código está fazendo isso" é muito mais difícil do que "o que esse código está fazendo", e o uso não padrão me faz perguntar por que ...

Agora, se você quiser marcá-las por algum motivo, não procure mais do que a falta de comentários. Ao lidar com indicadores, essas restrições não declaradas estão apenas implorando por erros.

    
por 02.09.2012 / 20:40
fonte
3

Em geral, se eu estou pedindo para as pessoas escreverem código em uma entrevista, eu estou olhando para ver se eles escrevem código que eu gostaria de depurar e manter. Isso me levaria a preferir respostas como o primeiro exemplo.

No entanto, qualquer pessoa que faça essa pergunta específica provavelmente está testando para ver se o entrevistado conhece o muito comum strcpy idiom no segundo exemplo. Este é um teste do seu conhecimento de ponteiros e C, não da legibilidade ou compactação de seu código.

    
por 02.09.2012 / 17:28
fonte
1

Existem algumas coisas que vêm à mente.

Se funcionar, deve ser bom o suficiente. Concentrar-se obsessivamente na formatação de código não é mais produtivo como focar obsessivamente na otimização prematura. Na maioria dos casos, não agrega nenhum valor.

Você mencionou " não é tão fácil entender como esse código está funcionando, e se você não está familiarizado com as prioridades deste código, então é um problema. ". Isso é então um problema porque o programador não é competente o suficiente com tais estruturas . Essas estruturas compactas são, na verdade, bastante comuns em códigos simples como esse, e qualquer programador experiente imediatamente entende e realmente as prefere porque são simples .

Isto é altamente uma questão de estilo, que varia entre as pessoas. Eu não acho que há uma resposta correta para questionar assim.

    
por 02.09.2012 / 17:28
fonte
1

Contexto do testador

Primeiro, vamos definir os testadores. A distinção entre funções de desenvolvimento de software e testes de software envolve o acesso ao código-fonte. Os desenvolvedores estão constantemente em contato com detalhes do código, concentrando-se no teste de unidade. Os membros da equipe chamados testadores são quase sempre intencionalmente alheios aos níveis mais baixos de implementação, concentrando-se em testes de integração, testes de estresse, testes de carga, testes de compatibilidade. Portanto, é mais provável que um testador observe a estrutura do código-fonte quando um erro de digitação quebra uma construção ou quando um rastreamento de pilha chega aos registros.

Usar qualquer estilo que os outros membros da sua equipe considerem fácil de manter normalmente significa que os testadores terão menos quebras de compilação e deficiências de comportamento a longo prazo. Em caso de dúvida, pergunte ao seu time ou vá atrás da simplicidade.

Contexto de revisão de código

Quando o código está sendo revisado por um colega desenvolvedor antes do commit, é claro que as diferenças no estilo do código são importantes. Aquele que é padrão dentro da organização / produto / projeto, ou familiar aos outros membros da equipe, é o correto. Os outros estão incorretos - menos pontos e retrabalho.

Se um desenvolvedor puder explicar por que uma determinada prática está melhor do que o padrão atual, e por que o padrão deve ser atualizado (essa questão já fornece muitos argumentos disponíveis de qualquer forma), isto é, mais pontos, mas há não é motivo para se desviar intencionalmente primeiro e explicar apenas o segundo.

Contexto da entrevista

Durante uma entrevista, erros de digitação, diferenças de recuo, etc., não importam realmente. Suas duas implementações compilam exatamente o mesmo código binário. Comparado com as implementações padrão da mesma tarefa, qualquer uma das nossas amostras equivalentes é muito mais fácil de ler, muito mais lenta e também muito mais. 09/21 / strcpy-data-corruption-on-core-i7-com-linux-64bit / "> mais seguro de usar para pessoas que não estão profundamente familiarizadas com a biblioteca C padrão. Isso ocorre em parte porque a parte "não se sobrepõe" da tarefa pode ter sido traduzida para a palavra-chave restrict , mas não foi.

A diferença no estilo de codificação diz coisas sobre a alma do desenvolvedor. Ambos os estilos de codificação mostrados são completamente padrão da indústria, por isso seria tolo julgar a experiência ou as habilidades do candidato com base apenas no estilo de codificação. No entanto, é possível que os dois programadores acabem sendo oferecidos a cargos de orientação diferente, ou que uma organização específica encontre um ajuste com apenas um desses dois estilos de personalidade.

    
por 02.09.2012 / 19:42
fonte
1

Por que você não pode dar as duas respostas?

Uma vez eu tive alguém me dizendo que eu tinha a resposta errada em uma entrevista e me negou o trabalho por causa disso, mesmo que o meu procedimento funcionasse. Ele queria o caminho rápido em vez do caminho legível (era uma empresa de jogos). Ele explicou seu atalho inteligente, mas ainda era uma grande decepção para mim. Eu fiquei emburrada por ter me enganado por algumas semanas antes de procurar e testar sua solução. Acabou tendo um bug sério que teria impedido que funcionasse!

Em retrospecto, eu deveria ter continuado a trabalhar no problema imediatamente depois de deixar a entrevista (ou pelo menos no dia seguinte, quando eu me refresquei). Dessa forma, eu poderia tê-lo contatado e continuado a discussão sobre o problema, talvez enviado um caso de teste por e-mail para demonstrar onde sua solução preferida falhou e sugeriu uma correção que resolvesse o problema mais próximo do seu caminho, mas sem o bug.

A maioria dos candidatos que eu fiz perguntas em entrevistas errou. Eu finalmente desisti e pedi aos candidatos que descrevessem um projeto recente pelo qual se sentiam entusiasmados. Essa é provavelmente uma questão de entrevista melhor de qualquer maneira. Porque é aberto, você tem uma idéia do estilo e da perspectiva de alguém, bem como de seu conhecimento e habilidade. Se alguém já tivesse me dado duas respostas corretas para uma pergunta e discutido os pontos strongs e fracos relativos, acho que teria desmaiado. Alguém assim teria que ser um serial killer condenado e um criminoso sexual para não conseguir o emprego! Talvez eu não estivesse contratando da melhor equipe de talentos, mas você tem isso.

    
por 03.09.2012 / 20:10
fonte
1

The first implementation is straightforward - it is readable and programmer-friendly.

The second implementation is shorter (one line of code) but less programmer-friendly; it's not so easy to understand the way this code is working, and if you're not familiar with the priorities in this code then it's a problem.

Você tem sua resposta lá.

Quando os entrevistadores analisam seu código, eles também verão seu estilo de codificação. A legibilidade é importante para o código de produção, portanto, tente mostrar a eles que você pode escrever esse código.
Para um exame, você também deve buscar a compreensão, para que seu código não seja erroneamente determinado como defeituoso.

    
por 03.09.2012 / 18:39
fonte