Les 10 erreurs de programmation les plus courantes débutants

Comme programmeur d'un début C, vous pouvez ne jamais reconnaître les erreurs que vous faites. Tout ce que vous remarquerez est que cela prend beaucoup plus de temps pour écrire et déboguer vos programmes. Même alors, une fois que les programmes sont déployés, ils semblent encore avoir des erreurs embêtants qui auraient été trouvés au cours des essais.

Sommaire

Pour gagner du temps et de peine, chercher les dix erreurs les plus courantes que les programmeurs débutants font.

Ne pas suivre un style d'écriture cohérente

Les humains ont une quantité très limitée de puissance de calcul pour travailler avec (la puissance de calcul entre leurs oreilles). Ils ont besoin pour maximiser son efficacité lors de la prise sur une tâche certes difficile comme la programmation.

Les programmeurs ne sont pas utilisent leurs ordinateurs de carbone pour un effet maximum quand ils ont à parcourir programmes

  • Ne pas disposer d'indentation cohérente

  • Ne pas utiliser une convention claire pour nommer les choses

  • Ne pas fournir des noms significatifs pour les choses

  • Ne pas avoir des commentaires significatifs mais concises

Une fois que vous avez adopté un style de programmation claire, il commence à se sentir aussi naturel que ces jeans de travail vous tirez sur lorsque vous êtes lutte contre le travail de week-end autour de la maison. Vous ne devez pas penser à ce sujet - vous savez où sont les choses. Vous savez, par exemple, que si un nom est en majuscule, alors il est probablement le nom d'une classe. Si elle est tous les bouchons, alors il est une constante d'un certain type. Si elle est en retrait, alors il est dans une boucle ou un si déclaration. Ces conventions permettent de passer plus de puissance de votre cerveau précieuse réflexion sur le problème que vous essayez de résoudre - et moins sur les détails de codage.

Fonctions qui sont trop gros Rédaction

Les gens ne commencent pas avec l'intention d'écrire d'énormes fonctions. Ils commencent juste à écrire. Cette fonction a besoin pour ce faire, et ensuite que, et, oh oui, cette autre chose ici. Bientôt, vous êtes jusqu'à 500 lignes de code ou plus - et il est difficile de comprendre exactement ce que-tous fait la fonction.

Big fonctions sont difficiles à déboguer et maintenir pour plusieurs raisons:

  • Il est difficile de comprendre exactement ce qu'ils essaient de faire.

  • Il ya trop d'interactions.

  • Il ya trop de chemins à travers le code.

Une fonction est trop grand si elle viole l'une des règles suivantes:

  • Il ne faut pas plus de 50 lignes de longueur.

  • Il devrait être explicable en une phrase qui ne contient pas AND ou OR.

  • Il ne doit pas contenir plus de huit au total si déclarations, interrupteur déclarations, ou des constructions en boucle.

Bien sûr, la règle 50-ligne est arbitrary- il est devenu populaire parce que ce serait tenir sur une seule feuille de papier d'impression ordinateur. Mais il est encore à propos de la bonne taille pour une limite supérieure. Au moment où vous dépassez ce nombre, que vous obtenez en "Quand cette fonction va finir?" territoire.

Alors, que faites-vous si vous vous trouvez à dépasser ces limites? Vous prenez en compte la fonction existante dans un certain nombre de sous-fonctions en vous demandant: "Qu'est-ce que cette fonction fait?" Chaque fois que vous voyez un ET ou un OU, il est temps de penser fonction. Prenons l'exemple suivant:

"Ma fonction obtient le nom d'un fichier à partir du clavier, puis ouvre le fichier et lit objets d'étudiants jusqu'à ce qu'il arrive à la fin et puis leurs moyennes MPC et affiche les résultats."

Cette description suggère des fonctions suivantes:

  • fstream getFileObject ()retourne la poignée d'un fichier indiqué par l'utilisateur.

  • Étudiant (* readStudents fstream) lit objets d'étudiants à partir d'un fichier.

  • averageStudentGPAs (étudiants *) Les moyennes MPC pour une collection d'étudiants.

  • displayGPA (ostream sur, double AMP) affiche la GPA étudiant pour le flux de sortie.

Chacune de ces fonctions est facile à comprendre et pourrait être écrit en beaucoup moins de 50 lignes. La fonction d'origine ne fait guère plus que d'appeler ces sous-fonctions pour faire tout le travail.

Ecriture de code sans un plan

Face à un problème, les programmeurs débutants sont beaucoup trop rapide pour commencer à coder sans avoir un plan. UN plan comprend toute une série de choses que le programmeur expérimenté vient de prendre pour acquis:

  • Préciser les exigences: Le programmeur a besoin de comprendre ce que le programme a besoin de faire.

    Cela peut sembler évident, mais dans la chaleur de la bataille, il est facile de penser qu'un aspect du problème sans considérer le problème dans son ensemble. Vous avez besoin de documenter votre programme pour conférer une certaine compréhension à votre utilisateur de ce que le programme est censé faire. Ne pas oublier d'inclure les cas de pointe. Ceci est votre chance pour déterminer la portée du programme - souvent le programmeur se concentre sur la résolution d'un problème particulier alors que les utilisateurs supposent que le programme va résoudre tous les problèmes.

  • Concevoir le programme: Le programmeur doit ensuite asseoir et d'envisager, à un niveau très élevé, comment le programme doit travailler.

    Il est difficile pour les débutants car ils ont pas d'expérience à se replier sur. Le programmeur doit décider comment le programme fonctionnera en interne - y compris la façon dont les tables de base de données (le cas échéant) seront disposés.

  • Concevoir l'interface: Le programmeur doit décider ce l'interface utilisateur va ressembler et comment cela va fonctionner.

  • # 42 le programme aura sa propre interface ou qu'il sera accessible via un navigateur?

  • # 42-Qu'est-ce que l'interface utilisateur ressembler?

  • # 42-Comment l'utilisateur naviguer d'une fenêtre à l'autre?

  • Concevoir le test: Les débutants sont surpris d'apprendre que le début du projet est le meilleur temps de penser à l'essai. Déterminer comment vous testez votre programme aura une incidence sur la façon dont vous étalez.

  • Apprendre une langue de programmation est juste la première étape vers l'apprentissage de programme.

    Les variables globales

    Programmeurs débutants ont tendance à déclarer toutes les variables à l'échelle mondiale. "Pourquoi se soucier de tous les non-sens de cette envergure? Pourquoi ne pas déclarer la variable à l'échelle mondiale afin que je puisse l'utiliser quand je veux?" Eh bien, les problèmes se produire lorsque la variable a une valeur que vous ne vous attendez pas.

    La variable ne soit pas initialisé - soit parce que vous avez oublié ou parce que le flux logique ne passe pas par le code d'initialisation? Ou bien la variable se initialisé de façon incorrecte? Ou bien la variable se initialisé correctement, mais ensuite remis à zéro par une autre fonction d'une valeur inattendue? Il n'y a vraiment aucun moyen de dire - à moins que vous exécutez une section de programme à la fois tout en gardant un œil d'aigle sur la variable.

    Il n'y a rien de plus frustrant que de trouver que le problème que vous avez fait la chasse toute la journée remonte à une variable globale, l'évolution des valeurs de façon inattendue, après un appel à une fonction qui n'a rien à voir avec cette variable.

    Non valider une entrée utilisateur

    Un programme doit être très prudent quand il accepte l'entrée externe. Premièrement, le programme doit vérifier que l'entrée de l'utilisateur ne déborde pas une mémoire tampon interne. Deuxièmement, si le programme utilise une entrée d'utilisateur pour créer des requêtes, il doit veiller à ce que ladite entrée ne contient pas de contrôles qui peuvent fuir dans la requête. Ne pas le faire ces vérifications de base peuvent rendre votre programme piraté et un danger pour la société.

    Au-delà de ce risque, cependant, vous devez vous assurer que ce que vous lisez est en fait ce que vous attendez. Cela se fait normalement avec des marqueurs. Par exemple, le format suivant lit dans les scores sur un test de l'étudiant:

    1234 35 2345 37 3456 29 5678 31

    Le premier nombre est la carte d'étudiant. La deuxième valeur est la partition correspondante.

    Le problème est qu'il ya très peu d'informations de position fournie qui peut être utilisé pour détecter au moins lorsque le programme est hors de synchronisation - et peut-être le récupérer en synchronisation. Pensez à ce qui se passe si le fichier d'entrée a même la plus petite erreur:

    3 5 2345 1234 37 3456 29 5678 31

    Voici un espace supplémentaire a été inséré entre le '3' et le '5'. Alors maintenant, 1 234 seront affectés à la valeur 3 plutôt que 35. Mais qu'en est-il pauvre étudiant 0005? Il reçoit maintenant une valeur 2 345 et ainsi de suite jusqu'à la ligne.

    La situation est améliorée si chaque entrée est placé sur une ligne distincte:

    1234 3 52345 373456 295678 31

    Maintenant, il est possible de détecter une erreur dans la première rangée. Même si cette erreur est passée inaperçue, un programme bien écrite serait utiliser les sauts de ligne pour resynchroniser de sorte que seule la valeur pour 1234 serait stocké de manière incorrecte.

    L'utilisation d'un objet de flux sans vérifier l'échec

    Celui-ci est tellement facile de bousiller - et si difficile à remarquer jusqu'à ce qu'elle fait.

    Il est très facile d'écrire quelque chose comme ce qui suit:

    int valeur-temps (! input.eof ()) {entrée >> valeur processValue (valeur)}

    Cette boucle est censé lire les valeurs à partir d'un flux d'entrée et les processus entre eux jusqu'à ce qu'il rencontre le Fichier Finde. Le problème avec cette boucle est que cela fonctionne très bien la plupart du temps. Si le programme rencontre un nombre non entier dans le fichier, toutefois, le programme tourne dans une boucle infinie. Ceci est parce qu'une fois que l'extracteur rencontre quelque chose qu'il ne comprend pas - dire, un caractère où un certain nombre devrait être - on positionne le drapeau échouer dans l'objet d'entrée. A partir de là, l'extracteur refuse obstinément à le taper.

    Pire que le refus d'effectuer des E / S lorsque le drapeau est réglé échec est le fait que les fonctions de flux ne se plaignent pas. Le programme suppose que tout ce qui se trouve être en valeur a été viens de lire à partir du fichier - quand, en fait, il est juste à gauche au-dessus de la lecture précédente.

    La boucle suivante est de loin préférable:

    int valeur-temps (! input.eof ()) {entrée >> valeur si (input.fail ()) {} percée processValue (valeur)}

    Maintenant, la boucle sort si le programme soit atteint la fin du fichier ou rencontre une valeur qu'il ne comprend pas.

    Une mauvaise manipulation d'une exception

    Le mécanisme d'exception est un excellent outil pour la gestion des erreurs. Comme tout outil, cependant, des exceptions peuvent être détournés. L'erreur la plus commune est d'intercepter les exceptions que vous jamais voulu. L'extrait de code suivant illustre le principe:

    // Supprimer le filetry {deleteFile (nom de fichier) -} // ignorer l'erreur si le fichier est pas presentcatch (...) {}

    Le programmeur sait que le supprimer le fichier() fonction lance un FileNotFoundException si le fichier à supprimer est pas présent. Plutôt que d'attraper cette exception, cependant, elle attrape tout. La plupart du temps, l'exception est probablement parce que le fichier est pas là, mais l'exception pourrait tout aussi bien être complètement indépendants. En capturant et en ignorant l'exception, l'utilisateur ne sait pas que le fichier n'a pas été supprimé.

    Le code approprié apparaîtra comme suit:

    // Supprimer le filetry {deleteFile (nom de fichier) -} // ignorer l'erreur si le fichier est pas presentcatch (FileNotFoundException e) {}

    Note: Les graines de cette erreur ont été portées dans la décision de lancer une exception si le fichier à supprimer est introuvable. On pourrait faire valoir que cette situation n'a rien d'exceptionnel, mais une partie du traitement normal - et aurait abouti à un retour d'erreur simple.

    Ne pas garder un journal du programme

    Un système de production doit enregistrer ce qu'il fait. Cela est particulièrement vrai pour les systèmes accessibles par Internet. Parfois, "cela n'a pas fonctionné" est sur toutes les informations de débogage qui obtient un programmeur. Comment dans le monde un programmeur peut dire ce qui est arrivé? En se référant aux journaux.

    Les systèmes de production de conserver un enregistrement constant de ce qu'ils font et qui a demandé que cela se fasse. En obtenant l'ID de la personne et le temps approximatif que la demande a été faite échoué, un programmeur peut retourner dans les journaux et à trouver la demande. Idéalement, le journal va dire le programmeur la demande, si elle a travaillé ou non, et si non, pourquoi pas.

    La plupart du temps un programmeur arrive à dire aux gens ce qu'ils foiré dans leurs demandes - mais si vraiment ils ne trébuchent dans un problème avec le programme, le journal devrait être en mesure de donner le programmeur suffisamment d'informations pour au moins recréer l'erreur dans le laboratoire où je peux étudier en ligne, trouver le problème, et pousser un correctif de retour sur la production.

    Ne pas utiliser un débogueur

    Un débogueur donne au programmeur la possibilité à l'étape lentement à travers votre code afin de mieux comprendre exactement ce qu'il fait. Cette étape est essentielle pour un programme qui ne fonctionne pas - mais il est tout aussi important pour un programme qui semble bien fonctionner.

    Je ne sais pas le nombre de fois que je l'ai entrés dans une fonction qui génère les résultats appropriés pour réaliser que la fonction ne fonctionne pas de la manière que je veux. Soit il ne gère pas toutes les valeurs d'entrée légale possibles ou probables - plus - il ne détecte pas les possibles valeurs d'entrée valides.

    Le débogueur vous donne plus d'informations pour travailler avec quand vous avez besoin d'une compréhension plus détaillée de ce que fait votre programme.

    Ne pas sauvegarder votre travail

    "Mon disque est écrasé et je l'ai perdu deux semaines de travail!" Il n'y a vraiment aucune excuse pour cette ancienne catastrophe, même si elle peut prendre un certain temps pour récupérer d'une panne de disque. Vous pourriez avoir à reformater un disque, reconstruire le système d'exploitation, et qui sait quoi d'autre - mais récupérer le code source que vous avez écrit ne devrait pas être plus difficile que de copier des fichiers d'un système à un autre.

    Systèmes peu coûteux existent qui sauvegarder automatiquement l'intégralité du disque sur une base quotidienne. D'autres systèmes de sauvegarder vos fichiers sur Internet, presque sans interruption. Ces systèmes ne sont pas chers - surtout en comparaison avec programmeur temps.

    Une autre chose: Les sauvegardes de nuit peuvent être conservés dans la même pièce que le disque d'origine - mais au moins une fois par semaine, les sauvegardes devraient être déplacés vers un autre emplacement physique pour se prémunir contre la perte due à un incendie ou de dégâts des eaux.

    Si vous êtes centre de développement en tant que l'accès à Internet, vous pouvez conserver une copie de votre code source et toute la documentation dans le nuage grâce à un service commercial comme Dropbox.


    » » » » Les 10 erreurs de programmation les plus courantes débutants