Coding style

From VLE

Jump to: navigation, search

The Coding style we use in the development of VLE comes from classical open source projects like the Linux or BSD. The following paragraphs describe the rules to follow when you want to integrate a patch into VLE.

Contents

Class declaration

In the declaration of a class, we define in a specific order: typedef, attributes and functions in the following protection: public, protected and private. This order allows the user to quickly see the functionality of your class. For example:

#ifndef THENAMESPACE_CLASS_HPP
#define THENAMESPACE_CLASS_HPP 1
 
namespace thenamespace {
 
class Class : virtual, public, protected, private class1, class2 etc.
{
public:
    typedefs ...
    variables ...   // Public attributes are rare.
    functions ...
 
protected:
    typedefs ...
    variables ...
    functions ...
 
private:
    typedefs ...
    variables ...
    functions ...
};
 
} // namespace thenamespace
#endif

All class and function must be attached to a namespace. Do not pollute the global space. In VLE we use a simple rule for the name of the namespaces: a repertory = a namespace.

/*
 * for a new class into the vle/devs directory.
 */
namespace vle { namespace devs {
 
class NewEventTable : boost::noncopyable
{
    ...
};
 
}} // namespace vle devs
 
/*
 * for a new examples into the examples directory.
 */
namespace vle { examples {
 
class GeneratorPlugin : public vle::devs::Dynamics
{
    ...
};
 
}} // namespace vle examples

Règles de nommage

  • dossier : Les noms de répertoires sont en minuscules afin de respecter le nom des namespaces.
mkdir -p examples/generator
  • namespace : Tout en minuscule, comme le noms des dossiers.
namespace examples { namespace generator {
    ...
}}
  • classe : Les premières lettres de chaque nom en majuscule.
class Position
{
    ...
};
  • méthode : la première lettre des noms de méthodes commence par une minuscule.
void position(int& x, int& y);
int x();
void setX(const int x);
const std::string& name() const;
void runLocal();
  • attribut d'une classe : il commence par la lettre minuscule m (pour member) suivie d'une majuscule.
int            mX, mY;
std::string    mName;
double         mDX, mDY;

Règles de mise en page

Tabulations et espaces

Une fonction ne peut dépasser les limites de 50 lignes et 80 colonnes pour permettre une meilleure lecture du code. De même, les indentations se font sur 4 caractères alors que la taille d'une tabulation est de 8 caractères. Enfin, une fonction ne peut contenir plus de six variables locales, et une fonction ou un membre d'une classe ne peut contenir plus de six paramètres locaux.

Dans le même ordre d'idée :

  • sur un ligne se trouve une seule instruction :
if (condition) {
    fait_quelque_chose();
}
  • Pas d'espace entre un nom de fonction et la parenthèse :
func (arg);    /* mauvais */
func(arg);     /* bien */
  • Entrez un espace après if, while, switch, etc. :
if(arg)     /* mauvais */
if (arg)    /* bien */
for(;;)     /* mauvais */
for (;;)    /* bien */
  • Entrez un espace après une virgule et un point-virgule :
func(arg1,arg2);     /* mauvais */
func(arg1, arg2);    /* bien */
for (i = 0;i < 2;++i)     /* mauvais */
for (i = 0; i < 2; ++i)   /* bien */
  • Entrez un espace avant et après =, +, /, etc. :
double var=a*5;     /* mauvais */
double var = a * 5; /* bien */
  • Pas d'espace entre le type de la variables et les cractères références et

pointeurs :

int * a;     /* mauvais */
int* a;      /* bien */
  • Pas d'espace entre les opérateurs d'adresses et les variables :
int b = * a;     /* mauvais */
int b = *a;      /* bon */

Placement des accolades

La politique de placement des accolades est celles définient par Kernighan et Ritchie c'est-à-dire, une accolade se trouve sur l'instruction de la ligne sauf dans le cas d'une définition de fonction. Les exemples suivants montrent les différents cas de placement :

if (x == y) {
    ...
}
int fonction(int x)
{
    ...
}
do {
    ...
} while (condition);
if (x == y) {
    ...
} else if (x > y) {
    ...
} else {
    ...
}
switch (test.getX()) {
case 0:
    ...
    break;
case 1:
    {
        ...
    }
default:
    ...
}

Gérer les erreurs via les exceptions

L'environnment VLE utilise les exceptions pour détecter les erreurs en cours de fonctionnement. Le fichier vle/utils/Exception.hpp définit quelques classes d'exceptions. Si vous souhaitez lever une exception, celle-ci doit hériter de la classe std::exception (défini dans la bibliothèque standard). Vous pouvez utiliser les exceptions standards :

  • std::logic_error : pour reporter les problèmes survenus dans la logique interne du programme.
  • std::domain_error : pour reporter une erreur de domaine dans le sens mathématique du terme.
  • std::invalid_argument : pour reporter les arguments invalides des fonctions.
  • std::length_error : quand un objet est construit avec une taille qui excède la taille maximum permise.
  • std::out_of_range : représente les arguments dont les valeurs dépassent les limites comme l'accès à un élément d'un tableau.
  • std::runtime_error : représente les erreurs ne peuvant être révéler que lors de l'exécution du programme.
  • std::range_error : Pour reporter une erreur de limite sur les types.

Ou les exceptions définies dans VLE (fichier vle/utils/Debug.hpp) :

  • vle::utils::FileError : pour reporter une erreur lors de l'accès à un fichier (détection, ouverture, lecture, écriture).
  • vle::utils::ParseError : pour reporter une erreur lors de la lecture d'un fichier \texttt{XML}.
  • vle::utils::InternalError : pour reporter une erreur interne dans un programme.

Assertions

Une méthode très simple pour détecter les erreurs dans un programme est d'utiliser les fonctions d'assertions définies dans le fichier cassert. Par exemple :

#include <cassert>
 
int getX(const Point* p)
{
    assert(p);  // on s'assure que le pointeur p est différent de NULL.
    return p->x;
}
 
std::auto_ptr < std::ostream > buildFilename(const std::string& name)
{
    std::ofstream* o = new std::ofstream(name);
    assert(o.is_open(); // on s'assure que le fichier est bien ouvert.
 
    return std::auto_ptr < std::ostream >(o);
}

Attention cependant la commande assert fait un appel à abort ce qui a pour effet de fermer l'application sur une erreur. Si vous voulez juste informer l'appelant de votre méthode de l'arrivée d'une erreur, il faut préférer utiliser une levée d'exception classique :

#include <vle/utils/Exception.hpp>
 
int getX(const Point* p)
{
    if (not p) {
        throw vle::utils::InternalError("Invalid point");
    }
 
    return p->x;
}
 
std::auto_ptr < std::ostream > buildFilename(const std::string& name)
{
    std::ofstream* o = new std::ofstream(name);
 
    if (not o.is_open()) {
        throw vle::utils::ArgError("Cannot open file");
    }
 
    return std::auto_ptr < std::ostream >(o);
}

Commentaires

Les commentaires font partis intégrante d'un programme. Dans la plateforme VLE, toutes les fonctions doivent contenir des commentaires décrivant le rôle de la fonction et non son fonctionnement. Aucun commentaire ne doit venir s'insérer dans le code de la fonction.

Le programme doxygen (Une description complète du système doxygen se trouve sur le site : http://www.doxygen.org), à partir des sources commentées et de balises spéciales, réalise une documentation complète.

/**
 * Description du rôle de la fonction ...
 * ...
 * @param n1 description du paramètre 1 très longue description, blabla bla bla
 * blablabla bla bla blabla.
 * @param n2 description du paramètre 2
 * @throw indique les exceptions pouvant être levées par la fonction.
 * @return description du retour de la fonction.
 */
int max(int n1, int n2)
{
    ...
}

Les fichiers du projet d'extension .cpp et .hpp possèdent une entête identique définissant la licence (de type GNU : GPL) et les informations sur les auteurs :

/**
 * @file vle/utils/Path.hpp
 * @author The VLE Development Team
 * See the AUTHORS or Authors.txt file
 */
 
/*
 * VLE - the multimodeling and simulation environment
 * This file is a part of the VLE environment
 * http://www.vle-project.org
 *
 * Copyright (C) 2003-2007 Gauthier Quesnel quesnel@users.sourceforge.net
 * Copyright (C) 2007-2010 INRA http://www.inra.fr
 * Copyright (C) 2003-2010 ULCO http://www.univ-litoral.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 3 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, see <http://www.gnu.org/licenses/>.
 */


This page was last modified on 25 July 2010, at 08:05. This page has been accessed 309 times.