*Title: Coding standards Efrei Robotique *Author: Ni *TOC * Intro Afin d'assurer un code source homogène, ce document défini les standards de codage pour tout programme développé pour Efrei Robotique. Le but n'est pas de définir un standard parfait, aucun ne peu prétendre l'être, mais un standard homogène. Un interrêt de coller au même standard est que l'on peut éditer n'importe quel fichier sans changer la configuration de son éditeur. Il est basé sur les [GNU Coding Standards (http://www.gnu.org/prep/standards.html)]. Ce document n'est pas figée, si vous n'êtes pas d'accord avec un point, on peut en discuter. * Code C ** Formatage L'indentation est de 4 caractères, tout en gardant une tabulation de 8 caractères. Éviter de faire des lignes de plus de 78 caractères. Pour les fonctions mettre le nom de la fonction et les accolades en première colonne. Aligner les lignes cassées avec les parenthèses ou les opérateurs. Les accolades de blocs sont mis sur leur propre ligne et décalées 2 caractères. Mettre un espace autour des opérateurs sauf : * les operateurs unaires ; * |.|, |[]| et |->| ; * avant une virgule ; * après une parenthèse ouvrante ou avant une parenthèse fermante. Les identifiant sont écrits en minuscule, les mots séparés par un caractère de soulignement (|_|). La seule exception est les noms de macros écrits en majuscules. Un identifiant de type se termine par |_t| (c'est éventuellement discutable... mais bon, je trouve que c'est pas mal). Un exemple pour faire plus clair : ^<< static char * concat (char *s1, char *s2) { int i; if (!s1 || !s2) return 0; for (i = 0; i < 5; i++) { faire_un_truc_complexe (avec_un_long_argument, et_un_autre[4] + 1, toto ()); } do { z--; } while (truc ()); return 0; } ^>> Lorsque l'on coupe une expression sur plusieurs lignes essayer de couper avant l'opérateur. Éviter d'utiliser NULL, c'est pour les vieux. Utiliser 0 à la place. Il n'y a jamais plus de deux espaces à la suite, sauf pour l'indentation. Il n'y a pas d'espace en fin de ligne. On saute une ligne après chaque fonction même la dernière, mais jamais à l'intérieur d'une fonction. Si l'envie vous prend de mettre une ligne vide dans une fonction, c'est qu'on pourrait certainement la remplacer par un commentaire. Il n'y a jamais deux ligne vides à la suite. ** Commentaires. Une phrase commence par une majuscule et se termine par un point. En français, il y a un espace avant chaque ponctuation composé de deux signes, mais pas d'un ou trois signes. En anglais il n'y a pas d'espace devant un caractère de ponctuation, mais deux espaces après un point s'il signifie une fin de phrase. Placez les commentaires sur leur propre ligne rarement en fin de ligne sauf éventuellement pour la description d'une structure ou d'une palanquée de variables globales (mais si, pour un microcontrôleur, c'est bien). Les seuls commentaires autorisés en C sont les : /* Commentaires. */ On peut utiliser toutefois les commentaires C++ pour commenter temporairement du code. Si le commentaire prend plusieurs lignes le formater de cette manière : /* Ceci * est * un long * commentaire. */ Merci de mettre plein de commentaires, mais uniquement s'il apporte quelquechose. Par exemple : ^<< /* Initialise i (mauvais commentaire). */ i = 0; /* Recherche la fin de la liste (bon commentaire). */ for (l = debut; l != fin; l = l->next) ; ^>> Mettre un commentaire au début de chaque fonction afin d'expliquer à quoi elle sert. Ne pas répéter dans le commentaire ce qui est déjà dit dans la déclaration de la fonction. Chaque fichier a une structure normalisée. Pour un en-tête |robert.h| : ^<< #ifndef robert_h #define robert_h /* robert.h - Fonctions de robertisation des paramètres. */ /* Programme de simulation de merguez. {{{ * * Copyright (C) 2004 Nicolas Schodet * * Robot APB Team/Efrei 2005. * Web: http://assos.efrei.fr/robot/ * Email: robot AT efrei DOT fr * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * }}} */ #include "entete_non_systeme.h" #include {Ici les définitions de types et de structures.} /* +AutoDec */ {Ici, les définitions de fonctions insérées automatiquement.} /* -AutoDec */ #endif /* robert_h */ ^>> Pour un code source |robert.c| : ^<< /* robert.c - Fonctions de robertisation des paramètres. */ /* Programme de simulation de merguez. {{{ * * Copyright (C) 2004 Nicolas Schodet * * Robot APB Team/Efrei 2005. * Web: http://assos.efrei.fr/robot/ * Email: robot AT efrei DOT fr * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * }}} */ #include "robert.h" #include "entete_non_systeme.h" #include {Ici les définitions de types et de structures locales au fichier.} /* +AutoDec */ {Ici, les définitions de fonctions statiques insérées automatiquement.} /* -AutoDec */ {Ici, les définitions de variables statiques ou globales.} {Ici, les définitions des fonctions.} ^>> Cette documentation est fournie avec les fichiers de template et le script qui va avec pour Vim. ** Extractdoc Pour les petits programmes en C, |extractdoc| permet d'extraire la doc des codes sources. Il utilise le même style de commentaires que doxygen, c'est à dire : /** Ceci est un commentaire extractdoc. */ Il n'utilise par contre pas les balises doxygen, je trouve qu'elles nuisent à la lecture du commentaire. Il reconnaît par contre la syntaxe [aft (http://www.maplefish.com/todd/aft-refman.html)], si aft est utilisé pour transformer le texte. En pratique, il remplace un espace en début de commentaire par une tabulation et fait aussi le remplacement de liste de description. Par exemple : ^<< /** * Met à jour les informations de cuisson. * * - t : température (°C). * - mode : type de cuisson. */ ^>> donne : ^<< Met à jour les informations de cuisson. [t] température (°C). [mode] type de cuisson. ^>> et dans aft : Met à jour les informations de cuisson. [t] température (°C). [mode] type de cuisson. ** Trucs et astuces Évitez d'utiliser des unsigned long ou des short, on ne devrais utiliser que : [des int] pour les entiers, même s'il sont toujours positifs ; [des double] pour les flottants ; [des char] pour des caractères ; [des unsigned char] pour des données binaires. * Code C++ ** Formatage Les règles du formatage du code C s'appliquent. Vim ne gère pas encore correctement l'indentation de certain aspects du C++, notamment : * les namespaces ; * les listes d'initialisations. Pour les namespaces, n'indentez pas le contenu, c'est inutile d'indenter un fichier complet. Fermez toujours un namespace avec un commentaire rapellant le nom du namespace. Pour les listes d'initialisation, on les formate de cette manière : ^<< /// Constructeur par défaut. Merguez::Merguez (void) : temperatureDeCuisson_ (0), identificateurTresLong_ (42), unAutreEncore_ (51), fermete_ (0.0) { } ^>> Les identificateurs sont écrit en minuscule. Les mots sont séparés par une majuscule. Les noms de types commencent par une majuscule. Les noms de variables membres privées ou protégées se terminent par un caractère de soulignement (|_|). Un petit exemple : ^<< namespace bbq { /// Classe de définition des propriétés d'une merguez. class Merguez { int temperatureDeCuisson_; double fermete_; public: /// Constructeur par défaut. Merguez (void); }; } // bbq ^>> L'ordre des déclarations dans la classe est le suivant (avec variations possibles) : * types ; * variables membres ; * constructeurs ; * constructeur de recopie, destructeur et operateur= ; * fonctions publiques ; * fonctions privées ou protégées. Si les constructeurs ou destructeurs sont privées, ils n'occupent plus la position de tête de classe. Les définitions dans le fichier |.cc| suivent le même ordre que la déclaration. Les classes sont déclarées dans un fichier |.hh| de la forme : ^<< #ifndef merguez_hh #define merguez_hh // merguez.hh - Composant Merguez. // Programme de barbeq. {{{ // // Copyright (C) 2004 Nicolas Schodet // // Robot APB Team/Efrei 2005. // Web: http://assos.efrei.fr/robot/ // Email: robot AT efrei DOT fr // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // }}} #include "entete_non_systeme.hh" #include {Ici la définition de classe.} {Ici la déclaration de fonctions globales.} {Ici la définition de fonctions inlines.} #endif // merguez_hh ^>> Quand il y a plus de une ou deux fonctions inline ou templetées, les mettre dans un fichier séparé |.tcc|, à inclure à la fin du |.hh|. Les classes sont implémentées dans un fichier |.cc| de la forme : ^<< // merguez.cc - Composant Merguez. // Programme de barbeq. {{{ // // Copyright (C) 2004 Nicolas Schodet // // Robot APB Team/Efrei 2005. // Web: http://assos.efrei.fr/robot/ // Email: robot AT efrei DOT fr // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // }}} #include "merguez.h" #include "entete_non_systeme.h" #include {Ici les définitions de types et de structures locales au fichier.} {Ici, les définitions de fonctions statiques.} {Ici, les définitions de variables statiques ou globales.} {Ici, les définitions des fonctions.} ^>> Les noms de fichiers ne prennent jamais de majuscule. ** Commentaires. Le seul type de commentaire à utiliser est le commentaire C++. On peut toutefois utiliser le commentaire C pour désactiver temporairement du code. La documentation du code se fait avec doxygen. On utilise les trois barres obliques pour signifier à doxygen que ce commentaire doit être lu. On essayera toutefois d'éviter les balises doxygen qui réduisent la lisibilité du commentaire. Une exception à la règle des commentaires bidons s'applique aux constructeurs et destructeurs afin que chaque fonction ait son commentaire attitré. ** Trucs et astuces Dans une classe qui ne peut être copiée, on peut déclarer le constructeur de recopie et l'opérateur = comme fonction privées. Ce n'est alors pas la peine de les définir. Une variable de boucle peut être déclarée dans la définition de la boucle. N'oubliez pas les |std::| pour accéder à une classe de la bibliothèque standard. Déclarer comme fonction const toute fonction qui peut l'être si le sens le justifie. De même déclarer les paramètres par pointeur ou référence const si possible. Dans le cas de conteneurs const, utiliser des |const_iterator|, sinon, ça ne compile pas. Réutilisez le code existant et faîtes du code réutilisable. Initialisez toutes les variables membres à un état connu. Usez et abuser des conteneurs standards comme les |std::list|, |std::vector|, |std::map|, mais encore et surtout les |std::string|.