Standards de développement QGIS

Ces standards doivent être suivis par tous les développeurs QGIS.

Classes

Noms

Une classe dans QGIS commence avec Qgs et est nommé en utilisant la casse camel.

Exemples:

  • QgsPoint
  • QgsMapCanvas
  • QgsRasterLayer

Attributs

Les noms des attributs (membres) de la classe commence avec un caractère minuscule m et sont formés en utilisant une casse mixte.

  • mMapCanvas
  • mCurrentExtent

Tous les attributs de la classe doivent être privés. Les attributs publics d’une classe sont FORTEMENT déconseillés.

Accesseurs

Les valeurs des attributs doivent toujours être obtenues à travers des accesseurs (fonctions d’accès). La fonction doit être nommée sans le préfixe get. Les accesseurs pour les deux attributs privés de dessus doivent être:

  • mapCanvas()
  • currentExtent()

Fonctions

Les noms de fonction commencent avec une lettre minuscule et sont formés en utilisant une casse mixte. La nom de la fonction devrait indiquer l’objectif de la fonction.

  • updateMapExtent()
  • setUserOptions()

Qt Designer

Classes générées

Les classes QGIS qui sont générées depuis les fichiers Qt Designer (.ui) doivent avoir Base pour suffixe. Cela permet d’identifier la classe comme étant une classe générée.

Exemples:

  • QgsPluginManagerBase
  • QgsUserOptionsBase

Boîtes de dialogue

Toutes les boîtes de dialogue doivent implémenter ce qui suit:

  • Un tooltip pour toutes les icônes de barre d’outils et tous les contrôles concernés.
  • Une aide de type « Qu’est-ce ? » pour tous les contrôles de la boîte de dialogue.
  • Un bouton optionnel (mais fortement recommandé) d’aide contextuelle
    qui dirige l’utilisateur vers la page d’aide appropriée en lançant leur navigateur web.

Fichiers C++

Noms

Les fichiers d’implémentation et d’en-tête C++ doivent respectivement avoir une extension en .cpp et en .h. Les fichiers doivent être nommés en minuscule et, dans le cas des classes, doivent suivre le nom de classe.

Exemple: Pour la classe QgsFeatureAttribute, les fichiers sources sont qgsfeatureattribute.cpp` et qgsfeatureattribute.h

Note

Dans le cas où l’assertion précédente ne serait pas assez claire, pour qu’un nom de fichier corresponde au nom d’une classe, il est implicite que chaque classe soit déclarée et implémentée par son propre fichier. Cela permet aux nouveaux développeurs d’identifier plus rapidement le code lié à une classe donnée.

En-tête standard et licence

Chaque fichier source doit contenir une en-tête suivant le motif de l’exemple qui suit:

/***************************************************************************
  qgsfield.cpp - Describes a field in a layer or table
  --------------------------------------
  Date : 01-Jan-2004
  Copyright: (C) 2004 by Gary E.Sherman
  Email: sherman at mrcc.com
/***************************************************************************
 *
 * 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.
 *
 ***************************************************************************/

Note

Il existe un gabarit pour Qt Creator dans le dépôt Git. Pour l’utiliser, copiez-le depuis doc/qt_creator_license_template vers un emplacement local, adaptez l’adresse de courrier électronique et, si requis, le nom du développeur et configurez Qt Creator pour utiliser ce gabarit: Outils -> Options -> C++ -> Nommage de fichier.

Noms de variable

Les noms des variables locales commencent par une minuscule et sont formés en utilisant des minuscules et majuscules.

Exemples:

  • mapCanvas
  • currentExtent

Énumérations

Les énumérations doivent être nommés selon la casse Camel avec une première lettre en majuscule, ex:

enum UnitType
{
  Meters,
  Feet,
  Degrees,
  UnknownUnit
};

N’utilisez pas de noms génériques qui peuvent entrer en conflit avec d’autres types. ex: utilisez UnkownUnit plutôt que Unknown

Constantes globales et Macros

Les constantes globales et les macros doivent être écrites en majuscules avec des séparateurs en tirets bas, ex:

const long GEOCRS_ID = 3344;

Commentaires

Les commentaires portant sur les méthodes et classes doivent être écrits à la troisième personne de l’indicatif et non à l’impératif:

/**
 * Creates a new QgsFeatureFilterModel, optionally specifying a \a parent.
 */
explicit QgsFeatureFilterModel( QObject *parent = nullptr );
~QgsFeatureFilterModel() override;

Édition

N’importe quel éditeur ou EDI peut être utilisé pour éditer le code de QGIS, sous réserve qu’il respecte les pré-requis suivants:

Tabulations

Paramétrez votre éditeur pour remplacer les tabulations par des espaces. L’espacement d’une tabulation doit être paramétrée pour occuper deux espaces.

Note

Sous Vim, vous pouvez utiliser set expandtab ts=2

Indentation

Le code source doit être indenté pour améliorer sa lecture. Il existe un script nommé scripts/prepare-commit.sh qui vérifie les fichiers modifiés et corrige leur indentation en utilisant astyle. Il doit être lancé avant chaque commit. Vous pouvez également utiliser scripts/astyle.sh pour indenter des fichiers individuellement.

Etant donné que les nouvelles versions de astyle indentent différemment les fichiers par rapport à la version utilisée pour faire une ré-indentation complète du source, le script utilise une ancienne version d’astyle que nous avons incluse dans le dépôt (activée lors de la compilation avec la variable WITH_ASTYLE dans CMake).

Accolades

Les accolades doivent commencer sur la ligne suivant l’expression:

if(foo == 1)
{
  // do stuff
  ...
}
else
{
  // do something else
  ...
}

Compatibilité API

Il existe une documentation d’API pour C++.

Nous essayons de garder l’API stable et rétrocompatible. Les nettoyages de l’API devraient se faire de manière similaire au code source de Qt, par ex.

class Foo
{
  public:
    /** This method will be deprecated, you are encouraged to use
     *  doSomethingBetter() rather.
     *  @deprecated doSomethingBetter()
     */
    Q_DECL_DEPRECATED bool doSomething();

    /** Does something a better way.
     *  @note added in 1.1
     */
    bool doSomethingBetter();

  signals:
    /** This signal will be deprecated, you are encouraged to
     *  connect to somethingHappenedBetter() rather.
     * @deprecated use somethingHappenedBetter()
     */
#ifndef Q_MOC_RUN
    Q_DECL_DEPRECATED
#endif
    bool somethingHappened();

    /** Something happened
     *  @note added in 1.1
     */
    bool somethingHappenedBetter();
}

Style de code

Voici quelques trucs et astuces de programmation qui, nous l’espérons, vous aideront à réduire les erreurs, le temps de développement et la maintenance.

Lorsque c’est possible, utiliser du code générique

Si vous utilisez du code copier-coller ou que vous écrivez plusieurs fois la même chose, demandez-vous comment consolider le code dans une seule fonction.

Cela permettra:

  • de gérer les changements à un seul endroit plutôt qu’en de multiples fichiers.
  • de prévenir le code pourri
  • de rendre plus difficile l’évolution différenciée de plusieurs copies au fil du temps, phénomène qui rend plus difficile la compréhension et la maintenance pour les autres développeurs

Placez d’abord les constantes en premier dans les expressions

Placez d’abord les constantes en premier dans les expressions.

0 == value à la place de value == 0

Cela permettra d’empêcher les développeurs d’utiliser accidentellement = à la place de ==, ce qui peut introduire des bogues logiques subtils. Le compilateur générera une erreur si vous utilisez accidentellement = à la place de == pour les comparaisons puisque les constantes ne peuvent pas se voir assigner des valeurs.

Le caractère espace est votre ami

Ajouter des espaces entre les opérateurs, les assertions et les fonctions rendent le code plus lisible pour les êtres humains.

Qu’est-ce qui est plus facile à lire ? Ceci:

if (!a&&b)

ou ceci:

if ( ! a && b )

Note

scripts/prepare-commit.sh gère également les espaces.

Placer les commandes sur des lignes séparées

Lors de la lecture du code il est facile de rater des commandes, si elles ne sont pas en début de ligne. Lors d’une lecture rapide du code, il est courant de sauter des lignes si elles ne semblent pas correspondre avec ce que l’on cherche dans les premiers caractères. Il est aussi commun de s’attendre à une commande après un conditionnel comme if.

Considérez ceci:

if (foo) bar();

baz(); bar();

C’est très facile de rater des morceaux dans le flux de contrôle. Au lieu de cela, utiliser

if (foo)
  bar();

baz();
bar();

Indenter les modificateurs d’accès

Les modificateurs d’accès structurent une classe en sections publique, protégée et privée de l’API. Les modificateurs d’accès eux-mêmes groupent le code dans cette structure. Indenter les modificateurs d’accès et les déclarations.

class QgsStructure
{
  public:
    /**
     * Constructor
     */
     explicit QgsStructure();
}

Recommandation de lecture

Vous devriez également lire cet article de Qt Quarterly sur designing Qt style (APIs)

Crédits pour les contributions

Les contributeurs des nouvelles fonctions sont encouragés à indiquer aux autres leur contribution en: