Estándares de codificación de QGIS

Todos los desarrolladores de QGIS deberían seguir estos estándares.

Clases

Nombres

Las clases en QGIS comienzan con Qgs y están formadas usando la notación Camel Case

Ejemplos:

  • QgsPoint
  • QgsMapCanvas
  • QgsRasterLayer

Miembros

Los nombres de los miembros de las clases comienzan con una m minúscula y se forman con mayúsculas y minúsculas.

  • mMapCanvas
  • mCurrentExtent

Todos los miembros de la clase deben ser privados. Se recomienda encarecidamente no usar miembros públicos en las clases. Los miembros protegidos deben evitarse cuando pueda ser necesario acceder al miembro desde las subclases de Python, ya que los miembros protegidos no se pueden usar desde los enlaces de Python.

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

Funciones del accesor

Los valores de los miembros de la Clase deben obtenerse a través de las funciones del accesor. La función debe ser nombrada sin un prefijo get. Las funciones de acceso para los dos miembros privados anteriores serían:

  • mapCanvas()
  • currentExtent()

Asegúrese de que los accesores estén correctamente marcados con const. Cuando sea apropiado, esto puede requerir que el valor en caché de las variables del tipo miembro estén marcadas con mutable.

Funciones

Los nombres de las funciones comienzan con una letra minúscula y se forman mezclando mayúsculas y minúsculas. El nombre de la función debe indicar algo acerca de su propósito

  • updateMapExtent()
  • setUserOptions()

Para guardar la consistencia con la API disponible de QGIS y con la API de Qt se deben evitar las abreviaciones, por ejemplo, setDestinationSize` en lugar de ``setDestSize o setMaximumValue en lugar de setMaxVal.

Los acrónimos también deben ser usados con CamelCase por consistencia. Por ejemplo, setXml en lugar de setXML.

Argumentos de la función

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

Preste atención especial a cuándo se deben pasar los argumentos por referencia. A menos que los objetos de argumento sean pequeños y se copien trivialmente (como los objetos QPoint), se deben pasar por referencia const. Para mantener coherencia con la API Qt, incluso los objetos compartidos implícitamente pasan por referencia const (por ejemplo, `` setTitle (const QString & title) `` en lugar de `` setTitle (QString title) ``.

Función que regresa valores

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)

Diseñador Qt

Clases Generadas

Las clases QGIS que se se generan desde archivos Qt Designer (ui) deberían tener un sufijo de Base. Esto identifica la clase como una clase base generada.

Ejemplos:

  • QgsPluginManagerBase
  • QgsUserOptionsBase

Diálogos

Todos los cuadros de diálogo deben implementar ayuda con información sobre herramientas para todos los iconos de la barra de herramientas y otros widgets relevantes. La información sobre herramientas agrega mucho a la detección de características para usuarios nuevos y experimentados.

Asegúrese de que el orden de tabulación para widgets se actualice cada vez que cambie el diseño de un diálogo.

Archivos C++

Nombres

La implementación de C++ y los archivos del título deben tener una extensión .cpp y .h respectivamente. Los nombres de los archivos deberán estar todos en minúsculas y, en el respecto a las clases, deberán coincidir con el nombre de la clase.

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

Nota

En caso de que no esté claro en la declaración anterior, para que un nombre de archivo coincida con un nombre de clase, implícitamente significa que cada clase debe declararse e implementarse en su propio archivo. Esto hace que sea mucho más fácil para los usuarios nuevos identificar dónde se relaciona el código con una clase específica.

Encabezado y Licencia Estándar

Cada archivo de origen debería contener una sección de encabezado que siga el siguiente patrón de ejemplo:

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

Nota

Hay una plantilla para Qt Creator en git. doc/qt_creator_license_template uselo, copielo de la ubicación local, ajuste la dirección de correo electrónico y -si es necesario- el nombre y configure QtCreator para usarlo: Herramientas‣ Opciones ‣ C++ ‣ Nombre de Archivo.

Nombres de variables

Los nombres de las variables locales inician con minúscula y se forman utilizando mayúsculas y minúsculas. No utilice prefijos como mi o el.

Ejemplos:

  • mapCanvas
  • currentExtent

Tipos Enumerados

Los tipos enumerados deben nombrarse en CamelCase con una mayúscula al inicio, p. ej:

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

No utilice nombres de tipos genéricos que entren en conflicto con otros tipos. p.ej. use UnidadDesconocidaUnit en lugar de Desconocido

Constantes & Macros Globales

Constantes y macros globales deberían escribirse en mayúscula separada por guión bajo e.g.:

const long GEOCRS_ID = 3344;

Qt Signals y Slots

Todos los espacios/señales conectados deben hacerse utilizando el conector “nuevo estilo” disponible en Qt5. Más información sobre este requisito está disponible en QEP #77.

Evite utilizar de Qt Ranuras de conexión automática (p. ej. los nombrados void on_mSpinBox_valueChanged). Ranuras de conexión automática son frágiles y propensos a romperse sin previo aviso si los diálogos se refactan.

Editando

Cualquier editor de texto/IDE puede ser usado para editar código QGIS, siempre que los siguientes requerimientos sean atendidos.

Tabulaciones

Defina su editor para emular tabulaciones con espacios. El espaciado de tabulación debería establecerse en 2 espacios.

Nota

En vim esto se hace con set expandtab ts=2

Indentación

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).

Llaves

Llaves deberían iniciar la línea que sigue a la expresión:

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

Compatibilidad API

There is API documentation for C++.

Tratamos de mantener la API estable y compatible con versiones anteriores. Los ajustes en la API deben hacerse de modo similar al codigo fuente de Qt, por ejemplo

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

Estilo de Codificación

Aquí se describen algunas pistas y consejos de programación que podrán reducir errores, el tiempo de desarrollo y el mantenimiento.

Siempre que sea Posible Generalizar Código

Si usted está cortando y pegando código, o escribiendo la misma cosa más de una vez, considere consolidar el código en una sola función.

Esto hará:

  • permite hacer cambios en una ubicacion en lugar de en multiples ubicaciones

  • ayuda a prevenir codigo innnecesariamente largo o lento

  • dificulta para multiples copias la evolucion de diferencias en el tiempo, lo cual dificulta a otros entender y mantener

Preffiere tener primero las constantes en los predicados

Es preferible poner constantes primero en predicados.

0 == valor en vez de valor == 0

Esto ayudara a los programadores a prevenir el uso accidental de “=” cuando intentaban usar “==”, lo cual podria introducir sutiles bugs logicos. El compilador generara un error si accidentalmente usas “=” en lugar de “==” para comparaciones dado que las constantes inherentemente no pueden ser asignadas

espacio en blanco puede ser tu amigo

Agregar espacios entre operadores, sentencias y funciones facilita a los humanos analizar el codigo por partes.

lo cual es facil de leer, esto:

if (!a&&b)

o este:

if ( ! a && b )

Nota

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

Ponga los comandos en líneas separadas

Cuando se lee codigo, es facil omitir comandos si estos no estan al comienzo de la linea. Cuando se lee rapidamente a lo largo del código, es comun saltarse lineas si estas no lucen como lo que se esta buscando en los primeros caracteres. Es tambien commun esperar un comando despues de una sentencia condicional como “if”

Considere:

if (foo) bar();

baz(); bar();

Es muy facil perder parte de lo que es el flujo de control. En lugar use

if (foo)
  bar();

baz();
bar();

Idente modificadores de acceso

Los modificadores de acceso estructuran una clase en secciones de API pública, API protegida y API privada. Los modificadores de acceso a ellos mismos agrupan el código en esta estructura. Sangrar el modificador de acceso y las declaraciones.

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

Recomendaciones de libros

Debería también leer este artículo de Qt Quarterly sobre designing Qt style (APIs)

Créditos para contribuciones

Se anima a los que contribuyen nuevas funciones a hacer conocer a la gente acerca de sus contribuciones mediante: