Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QEP 314: Code style and practice guidelines #314

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
af239dd
wip
nyalldawson Dec 18, 2024
a2a1ba4
Formatting
nyalldawson Dec 18, 2024
da35953
Formatting
nyalldawson Dec 18, 2024
02f95ed
Formatting
nyalldawson Dec 18, 2024
0de6a2d
Formatting
nyalldawson Dec 18, 2024
8e58c5a
Update qep-xx-coding-guidelines.rst
nyalldawson Dec 25, 2024
55b98ba
Update qep-xx-coding-guidelines.rst
nyalldawson Dec 25, 2024
39efea7
Update qep-xx-coding-guidelines.rst
nyalldawson Dec 27, 2024
3489598
Update qep-xx-coding-guidelines.rst
nyalldawson Dec 27, 2024
049d270
Update qep-xx-coding-guidelines.rst
nyalldawson Dec 27, 2024
245226a
rename
nyalldawson Dec 27, 2024
2006b98
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
d85c1b6
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
882576b
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
3554a24
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
1994396
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
c5dbb86
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
40fb388
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
abbe4c4
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
14968fb
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
c412546
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
3eabc6a
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
09ced2e
Update qep-xx-coding-guidelines.md
nyalldawson Dec 27, 2024
5279698
Update qep-xx-coding-guidelines.md
nyalldawson Dec 31, 2024
90e7230
Update qep-xx-coding-guidelines.md
nyalldawson Dec 31, 2024
3be2de6
Update qep-xx-coding-guidelines.md
nyalldawson Dec 31, 2024
261e819
Update qep-xx-coding-guidelines.md
nyalldawson Dec 31, 2024
9670481
add number
nyalldawson Dec 31, 2024
785c7fe
Update qep-400-coding-practice.md
nyalldawson Dec 31, 2024
f4f93b0
Update qep-400-coding-practice.md
nyalldawson Dec 31, 2024
6aa201d
Rename to 314
nyalldawson Jan 8, 2025
c6990af
Add as_const requirement
nyalldawson Jan 8, 2025
d5fb85f
Document include guidelines
nyalldawson Jan 8, 2025
8844450
Add QString guides
nyalldawson Jan 8, 2025
4aef2c4
Document debug output
nyalldawson Jan 8, 2025
a9c6e70
Formatting
nyalldawson Jan 8, 2025
53fa712
Add private member note
nyalldawson Jan 8, 2025
2a60b31
Add no auto connect slot guideline
nyalldawson Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions qep-314-coding-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# QGIS Enhancement 314: Code style and practice guidelines

## Summary

This QEP documents coding standards and conventions used throughout the QGIS code base. Developers are required to follow these standards when submitting code to QGIS.

Notes:

- Spacing and indentation rules are automatically applied by the QGIS pre-commit hooks, and accordingly are not covered here
- These guidelines describe QGIS specific coding practices only. Following "best practice" for modern c++ coding is assumed, and only referred to here when QGIS coding requires certain variances from this.

## Coding Guidelines

### 1. Naming

- 1.1. Variable and function naming should be camel case. Generally Qt's approach to capitalising only the first letter in acronyms is used (eg ``QgsGpsDetector``, not ``QgsGPSDetector``), with the exception of ``3D`` (eg ``Qgs3DMapCanvas``).

- 1.1.1. Local variables should have no name prefix (eg do not prefix variable names with ``my``)
- 1.1.2. [Hungarian notation](https://en.m.wikipedia.org/wiki/Hungarian_notation) is NOT used, except in some exceptional circumstances (eg variable names used with the gdal c API)
- 1.1.3. Member variables should have a ``m`` prefix (eg ``mLineWidth``)
- 1.1.4. Static variables should have a ``s`` prefix (eg ``sMutex``)
- 1.1.5. constexpr or static constants should be named in all uppercase, with underscore separators (eg ``DEFAULT_LINE_WIDTH``)
- 1.2. Classes should be named with a ``Qgs`` prefix, eg ``QgsGeometry``
- 1.3. Avoid abbreviations in naming (eg use ``maximum`` instead of ``max``, ``width`` instead of ``w``). While
this can increase the lengths of names it ensures that naming is consistent across the API and
is clearer for those of a non-native English speaking background. This applies to function names,
variable names, and argument names.
- 1.4. Getters and setters should use Qt naming conventions, eg ``setLineWidth()`` for a setter and
``lineWidth()`` for the getter.

### 2. Code Documentation

- 2.1. All public and protected fields must include Doxygen documentation.
- 2.2. Avoid repetitive documentation. Eg:


```
/**
* Sets the line width in centimeters.
* \param width line width in centimeters
*/
```

instead:

```
/**
* Sets the line \a width in centimeters.
*/
```

or:

```
/**
* Sets the line width.
*
* \param width line width, specified in centimeters.
*/
```

- 2.3. Qt style grammar and wording should be used. eg "Returns the line width" instead of "getter for line width", "Sets the line width" instead of "setter for line width", etc.
- 2.3.1. Use full sentences with correct punctuation (capitalisation and full stops) to ensure the documentation conveys professionality.
- 2.4. Ensure that the first line in the documentation is a concise sentence describing the method or class. This first line is interpreted as a brief summary of the object, and is used in table of contents in the c++ and PyQGIS documentation. The first line must be followed by a blank line, before any detailed explanations are described.
- 2.5. All methods and classes must have a ``\since QGIS 3.xx`` annotation added, describing the QGIS version when
that method was added. If the method is to be backported to a stable branch, ensure that the ``\since``
version correctly describes version at which that method is guaranteed to be accessible. (eg ``\since QGIS 3.34.8``
instead of ``\since QGIS 3.34``). Methods introduced in the same version as their class do not require an explicit since annotation.
- 2.6. Avoid re-documenting overridden methods, unless there is **specific** behavior differences in the override
which added extra useful information over the base virtual method documentation.
- 2.7. Use ``\see otherMethod()`` to link getters and setters (and other related methods)
- 2.8. The literal values ``true``, ``false`` and ``nullptr`` should be written in documentation as ``TRUE``, ``FALSE`` and ``NULLPTR`` respectively. (Preprocessing macros correctly replace these with ``true``, ``false`` and ``nullptr`` for the c++ documentation, and ``True``, ``False`` and ``None`` for the PyQGIS documentation)
- 2.9. Include explicit details of memory ownership in the documentation. Eg "ownership of the symbol is transferred to the renderer", "caller takes ownership of the returned object".


### 3. Language features

- 3.1. For readability and ease of code review, avoid use of ``auto``. The following exceptions are permitted:

- 3.1.1. ``auto`` should be used for complex types, such as iterators. Eg ``for ( auto it = object.begin(); ...)``

- 3.2. If ``enums`` are to be used outside of a single .h/.cpp file (or there is a reasonable chance that they will be in future!), they should be placed inside the ``Qgis`` namespace.

- 3.3. Checking if a pointer is null should be done with ``if ( !ptr )`` or ``if (ptr )`` alone, omitting explicit comparison with the ``nullptr`` constant.

- 3.4. Always use ``std::as_const`` to wrap the iterated container when iterating over non-const Qt containers (ie QList, QVector, QHash, ...). E.g.

```
QList< int > someList;
for ( int value : std::as_const( someList ))
{
...
}
```

- 3.5. Use ``QStringLiteral`` for untranslated literals, and ``QLatin1String`` for string comparisons. E.g.

```
const QString s = QStringLiteral( "my string" );
if ( s == QLatin1String( "another string" ) )
...
```

- 3.6. Don't use ``qDebug()``, ``qWarn()`` or other Qt debug print functions. Instead use ``QgsDebugError`` for unexcepted error logging only, or ``QgsDebugMsgLevel`` (with a level of 2 or higher, depending on how "noisy" the logging will be) for debug outputs which occur in normal operations.
- 3.7. Member variables should normally be in the private section and made available via getters and setters. This ensures full compatibility with the PyQGIS bindings and allows refactoring in future without API breakage.
- 3.8. Avoid use of Qt "auto connect slots" (i.e. those named ``void on_mSpinBox_valueChanged``). Auto connect slots are fragile and prone to breakage without warning if UI files are refactored.

### 4. Memory safety

- 4.1. "Factory" methods should return a std::unique_ptr (not a raw pointer), unless Qt parent/child
ownership is in place
- 4.2. Methods which take ownership of an object should default to taking a unique_ptr argument, **UNLESS**
these methods are to be exposed to Python, in which case a raw pointer with the ``SIP_TRANSFER`` annotation
is required.

### 5. File structure

- 5.1. Includes should be at the top of the .h or .cpp files. Group QGIS includes together, and where possible, include QGIS headers before Qt or other external library headers.
- 5.2. When including Qt headers, use ``#include <QString>`` instead of ``#include qstring.h``.
- 5.3. Avoid module wide Qt imports, i.e. don't ``#include <QtGui>``.