Outdated version of the documentation. Find the latest one here.

QGIS standaarden voor coderen

Deze standaarden zouden door alle ontwikkelaars van QGIS moeten worden gevolgd.

Klassen

Naamgeving

Een klasse in QGIS begint met Qgs en wordt gevormd met behulp van camel case.

Voorbeelden:

  • QgsPoint
  • QgsMapCanvas
  • QgsRasterLayer

Leden

Namen van leden van klassen beginnen met een kleine letter m en worden gevormd met behulp van mixed case.

  • mMapCanvas
  • mCurrentExtent

Alle leden van klassen zouden private moeten zijn. Leden van Public-klassen worden STERK ontraden. beveiligde leden zouden moeten worden vermeden als toegang tot het lid moet worden verkregen via subklassen van Python, omdat beveiligde leden niet kunnen worden gebruikt vanuit de Python bindings.

Mutable static class member names should begin with a lower case s, but constant static class member names should be all caps:

  • sRefCounter
  • DEFAULT_QUEUE_SIZE

Functies Accessor

Waarden voor leden van klassen zouden moeten worden verkregen door middel van functies accesssor. De functie zou moeten worden benoemd zonder een voorvoegsel get. Functies Accessor voor de twee bovenstaande private leden zouden zijn:

  • mapCanvas()
  • currentExtent()

Zorg er voor dat accessors juist zijn gemarkeerd met const. Waar van toepassing zou dit er toe kunnen leiden dat gecachte waardentypen van variabele leden zijn gemarkeerd met mutable.

Functies

Namen van functies beginnen met een kleine letter en worden gevormd met behulp van mixed case. De functienaam zou iets over het doel van de functie moeten zeggen.

  • updateMapExtent()
  • setUserOptions()

Voor consistentie met de bestaande API van QGIS en met de API van Qt zouden afkortingen moeten worden vermeden. Bijv. setDestinationSize in plaats van setDestSize, setMaximumValue in plaats van setMaxVal.

Acroniemen zouden ook camel case moeten zijn om redenen van consistentie. Bijv. setXml in plaats van setXML.

Argumenten voor functies

Function arguments should use descriptive names. Do not use single letter argments (e.g. setColor( const QColor& color ) instead of setColor( const QColor& c )).

Wees uitermate zorgvuldig als argumenten zouden moeten worden doorgegeven door middel van verwijzingen. Tenzij de objecten voor de argumenten klein zijn en eenvoudig zijn te kopiëren (zoals objecten QPoint), zouden zij moeten worden doorgegeven door middel van een verwijzing const. Voor consistentie met de API van Qt dienen zelfs impliciet gedeelde objecten te worden doorgegeven door een verwijzing const (bijv. setTitle( const QString& title ) in plaats van setTitle( QString title ).

Teruggegeven waarden van functies

Return small and trivially copied objects as values. Larger objects should be returned by const reference. The one exception to this is implicitly shared objects, which are always returned by value.

  • int maximumValue() const
  • const LayerSet& layers() const
  • QString title() const (QString is implicitly shared)
  • QList< QgsMapLayer* > layers() const (QList is implicitly shared)

Qt Designer

Gegenereerde klassen

Klassen voor QGIS die worden gegenereerd uit Qt Designer (ui)-bestanden zouden een achtervoegsel Base moeten hebben. Dat identificeert de klasse als een gegenereerde basisklasse.

Voorbeelden:

  • QgsPluginManagerBase
  • QgsUserOptionsBase

Dialoogvensters

Alle dialoogvensters zouden helptips moeten implementeren voor alle pictogrammen van de werkbalk en andere relevante widgets. Helptips voegen een grote mate van ontdekkingsdrang toe voor zowel nieuwe als ervaren gebruikers.

Zorg er voor dat de tabvolgorde voor widgets wordt bijgewerkt, iedere keer als de lay-out van het dialoogvenster wijzigt.

C++-bestanden

Naamgeving

C++ implementatie en headerbestanden zouden respectievelijk de extensie .cpp en .h moeten hebben. De bestandsnaam zou geheel in kleine letters moeten zijn en, in het geval van klassen, moeten overeenkomen met de naam van de klasse.

Example: Class QgsFeatureAttribute source files are qgsfeatureattribute.cpp and qgsfeatureattribute.h

Notitie

In het geval het niet duidelijk is uit het argument hierboven: om een bestandsnaam overeen te laten komen met een naam voor de klasse betekent het impliciet dat elke klasse zou moeten zijn gedeclareerd en geïmplementeerd in zijn eigen bestand. Dit maakt het voor nieuwkomers veel gemakkelijker om te identificeren waar de code gerelateerd is aan een specifieke klasse.

Standaard header en licentie

Elk bronbestand zou een gedeelte header moeten hebben met een patroon als in het volgende voorbeeld:

/***************************************************************************
  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.
 *
 ***************************************************************************/

Notitie

Er staat een sjabloon voor Qt Creator in GIT. Kopieer het, om het te gebruiken, vanuit doc/qt_creator_license_template naar een lokale locatie, pas het mailadres aan en - indien vereist - de naam en configureer QtCreator om het te gebruiken: Tools -> Options -> C++ -> File Naming.

Namen van variabelen

Namen van variabelen beginnen met een kleine letter en worden gevormd met behulp van mixed case. Gebruik geen voorvoegsels zoals my of the.

Voorbeelden:

  • mapCanvas
  • currentExtent

Geënumereerde typen

Geënumereerde typen zouden moeten worden benoemd in CamelCase met een hoofdletter aan het begin, bijv.:

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

Gebruik geen algemene namen voor typen die kunnen conflicteren met andere typen. Gebruik bijvoorbeeld UnkownUnit in plaats van alleen Unknown

Globale constanten & macro’s

Globale constanten en macro’s zouden moeten worden geschreven in hoofdletters, gescheiden door een underscore, bijv.:

const long GEOCRS_ID = 3344;

Qt signalen en slots

Alle verbindingen naar signal/slot zouden moeten worden gemaakt met behulp van de verbindingen “new style” die beschikbaar zijn in Qt5. Meer informatie over dit vereiste is beschikbaar in QEP #77.

Vermijd het gebruiken van Qt auto connect slots (d.i. die welke zijn genaamd void on_mSpinBox_valueChanged). Auto connect slots zijn fragiel en gevoelig voor beschadigingen zonder waarschuwing als dialoogvensters opnieuw worden opgebouwd.

Bewerken

Elke tekstbewerker/IDE kan worden gebruikt om de code van QGIS te bewerken, vooropgesteld dat aan de volgende eisen wordt voldaan.

Tabs

Stel uw bewerker in om tabs te laten zien als spaties. De afstand voor de tab zou moeten zijn ingesteld op 2 spaties.

Notitie

In VIM wordt dit gedaan met set expandtab ts=2

Inspringen

Source code should be indented to improve readability. There is a scripts/prepare-commit.sh that looks up the changed files and reindents them using astyle. This should be run before committing. You can also use scripts/astyle.sh to indent individual files.

As newer versions of astyle indent differently than the version used to do a complete reindentation of the source, the script uses an old astyle version, that we include in our repository (enable WITH_ASTYLE in cmake to include it in the build).

Haakjes

Haakjes zouden op de regel moeten beginnen volgens de volgende expressie:

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

Compatibiliteit met de API

There is API documentation for C++.

We proberen de API stabiel en achterwaarts compatibel te houden. Opschonen van de API zou op een manier moeten worden gedaan die soortgelijk is aan de broncode voor Qt bijv.

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();
}

Stijl van coderen

Hier worden enkele hints en tips beschreven voor het programmeren die hopelijk het aantal fouten, ontwikkeltijd en onderhoud reduceren.

Waar mogelijk: generaliseer code

Indien u code knipt-en-plakt, of op een andere manier hetzelfde meer dan eens schrijft, overweeg dan om de code te consolideren in één enkele functie.

Dat zal:

  • het mogelijk maken wijzigingen op één plaats door te voeren in plaats van op meerdere plaatsen

  • helpen bij het tegengaan van overbodige code

  • het moeilijker maken voor meerdere kopieën om in de tijd verschillen te ontwikkelen, wat het moeilijker maakt voor anderen om het te begrijpen en te onderhouden

Voorkeur voor het hebben van constanten als eerste in predicaten

Heb een voorkeur voor het als eerste plaatsen van constanten in predicaten.

0 == value in plaats van value == 0

Dit zal programmeurs helpen om te voorkomen dat zij per ongeluk = gebruiken wanneer zij bedoelen == te gebruiken, wat zeer subtiele logische bugs kan introduceren. De compiler zal een fout genereren als u per ongeluk = gebruikt in plaats van == voor vergelijkingen omdat inherent aan constanten geen waarden kunnen worden toegewezen.

Witruimte kan uw vriend zijn

Toevoegen van spaties tussen operatoren, statements en functies maken het voor mensen gemakkelijker code te parsen.

Wat is gemakkelijker te lezen, dit:

if (!a&&b)

of dit:

if ( ! a && b )

Notitie

scripts/prepare-commit.sh will take care of this.

Plaats opdrachten op afzonderlijke regels

Het is bij het lezen van code eenvoudig om opdrachten te missen als zij niet aan het begin van de regel staan. Bij het snel doorlezen van code worden vaak regels, die er niet uitzien als zoals u verwacht in de eerste tekens, over te slaan. Het is ook algemeen gebruik om een opdracht te verwachten na een voorwaarde, zoals if.

Overweeg:

if (foo) bar();

baz(); bar();

Het is heel eenvoudig om delen van de beheersstroom te missen. Gebruik in plaats daarvan

if (foo)
  bar();

baz();
bar();

Laat access modifiers inspringen

Acess modifiers structureren een klasse die is opgedeeld in public API, protected API en private API. Access modifiers zelf groeperen de code binnen deze structuur. Laat de access modifier en declaraties inspringen.

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

Aanbevolen boeken

U zou ook echt dit artikel moeten lezen uit Qt Quarterly ove designing Qt style (APIs)

Vermelding van bijdragen

Zij die nieuwe functies bijdragen worden aangemoedigd om mensen kennis te laten nemen van hun bijdrage door: