Os 10 erros de programação mais comuns Iniciante

Como programador de um começo C ++, você nunca pode reconhecer os erros que você faz. Tudo o que você percebe é que leva muito mais tempo para escrever e depurar seus programas. Mesmo assim, uma vez que os programas são implantados eles ainda parecem ter erros traquinas que deveriam ter sido encontrados durante o teste.

Para poupar tempo e problemas, procure os dez erros mais comuns que os programadores iniciantes fazem.

Não seguir um estilo de escrita consistente

Os seres humanos têm uma quantidade muito limitada de poder de computação para trabalhar com (o poder de computação entre os ouvidos). Eles precisam maximizar a sua eficácia quando se toma em uma tarefa reconhecidamente difícil, como programação.

Os programadores não estão usando seus computadores de carbono para o efeito máximo quando eles têm que percorrer os programas que

  • Não tem recuo consistente

  • Não use uma convenção claro para nomear as coisas

  • Não fornecer nomes significativos para as coisas

  • Não tem comentários significativos, mas concisas

Uma vez que você adotou um estilo de programação clara, ele começa a sentir-se tão natural como os jeans de trabalho você puxa quando você está lutando contra o trabalho de fim de semana em torno da casa. Você não tem que pensar sobre isso - você sabe onde as coisas estão. Você sabe, por exemplo, que se um nome é capitalizada, então provavelmente é o nome de uma classe. Se é todos os tampões, então é uma constante de algum tipo. Se ele está recuado, então é dentro de um loop ou um E se declaração. Tais convenções permitem que você gaste mais do seu pensamento o poder do cérebro preciosas sobre o problema que você está tentando resolver - e menos sobre os detalhes de codificação.

Criando funções que são demasiado grandes

As pessoas não começar com a intenção de escrever funções enormes. Eles só começar a escrever. Esta função tem de fazer isso, e depois disso, e, oh, sim, essa outra coisa aqui. Brevemente você é até 500 linhas de código ou mais - e é difícil descobrir exatamente o que-tudo a função faz.

Grandes funções são difíceis de depurar e manter por várias razões:

  • É difícil entender exatamente o que eles estão tentando fazer.

  • Há muitas interações.

  • Há também muitos caminhos através do código.

Uma função é muito grande se violar qualquer uma das seguintes regras:

  • Ele deve ser não mais do que 50 linhas de comprimento.

  • Deve ser explicada em uma frase que não contém E ou OU.

  • Ele deve conter, no máximo, oito no total E se declarações, interruptor declarações, ou construções de loop.

Claro, a regra dos 50-line é arbitrary- tornou-se popular porque é isso que se encaixam em uma única página de papel de computador impressão. Mas ainda é sobre o tamanho certo para um limite superior. No momento em que você exceder esse número, você está se metendo "Quando é que esta função vai acabar?" território.

Então, o que você faria se você encontrar-se superior a esses limites? Você fator a função existente em um número de subfunções se perguntando: "O que esta função faz?" Toda vez que você vê um E ou um OR, é hora de pensar função. Considere o seguinte exemplo:

"Minha função recebe o nome de um arquivo a partir do teclado, em seguida, abre o arquivo e lê objetos do estudante até chegar até o fim e, em seguida, médias suas GPAs e exibe os resultados."

Essa descrição sugere as seguintes funções:

  • fstream getFileObject ()retorna o identificador de um ficheiro indicado pelo utilizador.

  • readStudents Student * (fstream) lê objetos do estudante a partir de um arquivo.

  • averageStudentGPAs (Student *) calcula a média dos GPAS para um conjunto de alunos.

  • displayGPA (ostream para fora, dupla GPA) exibe o GPA aluno para o fluxo de saída.

Cada uma dessas funções é fácil de compreender e pode ser escrita em muito menos do que 50 linhas. A função original faz pouco mais do que chamar essas subfunções para fazer todo o trabalho.

Escrever código sem um plano

Dado um problema, programadores iniciantes são demasiado rápido para iniciar a codificação sem um plano. UMA planoinclui toda uma série de coisas que o programador experiente trata de tomar para concedido:

  • Especificar os requisitos: O programador precisa entender o que o programa precisa fazer.

    Isto pode parecer óbvio, mas no calor da batalha, é fácil pensar em apenas um aspecto do problema, sem considerar o problema completa. Você precisa documentar seu programa para dar alguma compreensão para o usuário do que o programa é suposto fazer. Não se esqueça de incluir os casos de ponta. Esta é a sua oportunidade de determinar a escopo do programa - muitas vezes o programador está focado em resolver um problema particular, enquanto os usuários assumem que o programa vai resolver todos os problemas.

  • Projetar o programa: O programador, então, precisa sentar e considerar, em um nível muito alto, como o programa deve funcionar.

    Isto é difícil para iniciantes, pois eles não têm experiência para voltar a cair. O programador deve decidir como o programa irá funcionar internamente - incluindo a forma como as tabelas de banco de dados (se houver) será colocado para fora.

  • Projetar a interface: O programador tem de decidir o que a interface do usuário será semelhante e como ele vai funcionar.

  • # 42-Será que o programa tem sua própria interface ou vai ser acessado através de um navegador?

  • # 42-Qual será a interface do usuário parece?

  • # 42-Como é que o usuário navegar de uma janela para outra?

  • Projetar o teste: Iniciantes ficam surpresos ao saber que o início do projeto é o melhor momento para pensar sobre o teste. Determinar como você testar seu programa irá afetar a forma como você colocá-lo fora.

  • Aprender uma linguagem de programação é apenas o primeiro passo para aprender a programar.

    As variáveis ​​globais

    programadores iniciantes tendem a declarar todas as variáveis ​​globais. "Por que se preocupar com tudo isso um absurdo escopo? Porque não basta declarar a variável global para que eu possa usá-lo quando eu quiser?" Bem, os problemas ocorrem quando a variável tem um valor que você não espera.

    Será que a variável não inicializada se - seja porque você se esqueceu ou porque o fluxo lógico não passar o código de inicialização? Ou será que a variável se inicializada incorretamente? Ou será que a variável obter inicializado corretamente, mas, em seguida, redefinir por alguma outra função para um valor inesperado? Não há realmente nenhuma maneira de dizer - a menos que você execute a uma seção programa ao mesmo tempo mantendo um olho de águia sobre a variável.

    Não há nada mais frustrante do que encontrar que o problema que você está perseguindo o dia todo remonta a uma variável global, mudando os valores de forma inesperada, após uma chamada para alguma função que não tem nada a ver com essa variável.

    Não validar entrada do usuário

    Um programa deve ter muito cuidado sempre que aceita a entrada externa. Primeiro, o programa deve certificar-se de que a entrada do usuário não transborde alguns buffer interno. Segundo, se o programa usa a entrada do usuário para criar consultas, deve-se certificar de que a referida entrada não contém controles que podem vazar para a consulta. A falha fazer essas verificações básicas pode fazer seu programa hackable e um perigo para a sociedade.

    Além desse risco, no entanto, você precisa ter certeza de que o que você está lendo é realmente o que você espera. Isto é normalmente feito com marcadores. Por exemplo, o seguinte formato lê na pontuação em um teste de estudante:

    1234 35 2345 37 3456 29 5678 31

    O primeiro número é o ID do aluno. O segundo valor é a pontuação correspondente.

    O problema é que há muito pouca informação posicional desde que podem ser usados ​​para detectar, pelo menos, quando o programa está fora de sincronia - e, talvez, para obtê-lo de volta em sincronia. Considere o que acontece se o arquivo de entrada tem mesmo o menor erro:

    1234 3 5 2345 37 3456 29 5678 31

    Aqui foi inserido um espaço extra entre o '3' e o '5'. Então agora 1234 será atribuído o valor 3, em vez de 35. Mas o que dizer pobre estudante 0005? Ele agora recebe um valor 2.345 e assim por diante para baixo da linha.

    A situação é melhorada se cada entrada é colocado em uma linha separada:

    1234 3 52345 373456 295678 31

    Agora é possível detectar um erro na primeira linha. Mesmo que o erro foi detectado, um programa bem escrito usaria as novas linhas para sincronizar novamente para que apenas o valor para 1234 seria armazenado incorretamente.

    Usando um objeto de fluxo sem verificar falhar

    Este é apenas tão fácil de estragar - e tão difícil de perceber até que ele faz.

    É muito fácil escrever algo como o seguinte:

    int valor-while (! input.eof ()) {entrada >> valor processValue (valor)}

    Este ciclo é suposto para ler os valores a partir de um fluxo de entrada e processa-los até encontrar o arquivo endoF. O problema com este circuito é que funciona bem na maior parte do tempo. Se o programa encontrar um número não inteiro no ficheiro, no entanto, o programa se transforma em um ciclo infinito. Isto é porque uma vez que o extrator se depara com algo que não compreende - digamos, um personagem onde um número deve ser - que define o sinalizador falhar no objeto de entrada. Daquele ponto em diante, o extrator teimosamente se recusa a executar qualquer entrada.

    Pior do que a recusa de executar E / S quando o sinalizador falha está definido é o fato de que as funções de transmissão não se queixam sobre isso. O programa pressupõe que o que quer que acontece a estar em valor foi apenas ler a partir do arquivo - quando, na verdade, é só sobraram de uma leitura anterior.

    O ciclo seguinte é de longe preferível:

    int valor-while (! input.eof ()) {entrada >> value-if (input.fail ()) {} break-processValue (valor)}

    Agora o loop sai se o programa quer atinge fim de arquivo ou encontra um valor que não entende.

    O manuseio incorreto uma exceção

    O mecanismo de exceção é uma grande ferramenta para o tratamento de erros. Como qualquer ferramenta, no entanto, exceções podem ser mal aplicado. O erro mais comum é para capturar exceções que você nunca pretendeu. O seguinte trecho de código demonstra o princípio:

    // Excluir o filetry {deleteFile (filename) -} // ignorar o erro se o arquivo não está presentcatch (...) {}

    O programador sabe que o deleteFile () função gera um FileNotFoundException se o arquivo a ser excluído não está presente. Ao invés de pegar essa exceção, no entanto, ela pega tudo. Na maioria das vezes, a exceção, provavelmente é porque o arquivo não está lá, mas a exceção poderia muito bem ser completamente alheios. Pela captura e ignorar a exceção, o usuário não tem conhecimento de que o arquivo não foi excluído.

    O código adequado apareceria da seguinte maneira:

    // Excluir o filetry {deleteFile (filename) -} // ignorar o erro se o arquivo não está presentcatch (FileNotFoundException e) {}

    Nota: As sementes desse erro foram estabelecidas na decisão de lançar uma exceção se o arquivo a ser excluído não é encontrado. Pode-se argumentar que esta não é uma situação excepcional, mas uma parte do processamento normal - e poderia ter resultado em um retorno de erro simples.

    Deixar de manter um log de programa

    Um sistema de produção precisa para gravar o que está fazendo. Isto é especialmente verdadeiro para os sistemas acessíveis pela Internet. Às vezes, "não funcionou" é sobre todas as informações de depuração que um programador ganha. Como no mundo pode um programador dizer o que aconteceu? Ao se referir aos logs.

    sistemas de produção de manter um registro constante de que eles estão fazendo e que pediu para que possa ser feito. Ao receber ID da pessoa e o tempo aproximado que o pedido não foi feito, um programador pode voltar para os logs e encontrar o pedido. Idealmente, o log irá dizer o programador o pedido, se ele trabalhou ou não, e se não, por que não.

    Na maioria das vezes um programador começa a divulgar aos outros o que eles desarrumada nos seus pedidos - mas se eles realmente fez tropeçar em um problema com o programa, o registro deve ser capaz de dar o programador informação suficiente para, pelo menos, re-criar o erro no laboratório onde eu possa estudá-la off-line, encontrar o problema, e empurre uma correção de volta à produção.

    Não usando um depurador

    Um depurador dá ao programador a oportunidade de pisar lentamente através de seu código para melhor entender exatamente o que está fazendo. Esta etapa é fundamental para um programa que não está funcionando - mas é tão importante para um programa que parece estar funcionando bem.

    Eu não sei o número de vezes que eu já atravessou uma função que está gerando os resultados adequados apenas para perceber que a função não está funcionando da maneira que eu quero. Ou ele não controla todos os possíveis valores de entrada legal ou - mais provavelmente - ele não detecta os possíveis valores de entrada inválidos.

    O depurador fornece mais informações para trabalhar com quando você precisa de uma compreensão mais detalhada do que o programa está fazendo.

    Não fazer o backup de seu trabalho

    "Meu rígido caiu e eu perdi duas semanas de trabalho!" Não há realmente nenhuma desculpa para este desastre à moda antiga, embora possa levar um longo tempo para se recuperar de uma falha de disco. Você pode ter que reformatar um disco, reconstruir o sistema operacional, e quem sabe mais o quê -, mas recuperar o código-fonte que você escreveu não deve ser mais difícil do que copiar arquivos de um sistema para outro.

    Existem sistemas de baixo custo que automaticamente backup de todo o disco em todas as noites. Outros sistemas de backup de seus arquivos através da Internet, quase continuamente. Estes sistemas não são caros - especialmente em comparação com o programador de tempo.

    Uma outra coisa: backups noturnos podem ser mantidos no mesmo quarto que o disco original - mas pelo menos uma vez por semana, os backups devem ser movidos para um local físico diferente para se proteger contra perda devido a fogo ou água danos.

    Se você é facilidade de desenvolvimento como acesso à Internet, você pode manter uma cópia de seu código-fonte e toda a documentação na nuvem através de um serviço comercial como o DropBox.

    menu