Difference between revisions of "CodingStandard"
(Add C++ section.) |
(→C++ Format: Combine with coding recommendations from C++ page, removing them from there; do the reverse for design guidance.) |
||
Line 39: | Line 39: | ||
= C++ Format = | = C++ Format = | ||
C++ follows the C format guidelines above, with the following modifications: | C++ follows the C format guidelines above, with the following modifications: | ||
− | * Namespaces shall be all lower case, and the outermost one shall be named ''' | + | * Namespaces shall be all lower case, and the outermost one shall be named '''gnc'''. |
− | * | + | * Identifier formats: |
− | ** '''Typenames''' (i.e. class, struct, enum, and POD type-aliases) shall | + | ** '''Typenames''' (i.e. class, struct, enum, and POD type-aliases) shall be camel-cased. |
− | ** '''Function''' and '''object''' | + | ** '''Function''' and '''object''' names shall be lower-case and shall have words separated by underscores. |
+ | ** '''Preprocessor Macros''' and '''enumeration names''' shall be upper-case with words separated by underscores. | ||
In addition, certain types of variables shall have prefixes denoting their roles: | In addition, certain types of variables shall have prefixes denoting their roles: | ||
Line 50: | Line 51: | ||
* '''Free static variables''': '''s_'''. Free static variables means statics which are not local and not members of a class or struct, regardless of scope. | * '''Free static variables''': '''s_'''. Free static variables means statics which are not local and not members of a class or struct, regardless of scope. | ||
− | Headers and implementation files should be named for the class they declare or implement. In general any file should declare or implement only one class. | + | Other Formatting: |
+ | * Use C-style comments for multi-line comments and C++-style for end-of-line comments; either is OK for single-line standalone comments. | ||
+ | * Headers and implementation files should be named for the class they declare or implement. In general any file should declare or implement only one class. | ||
== Coding Guidance == | == Coding Guidance == | ||
− | * Write modern, idiomatic C++ using the new features of C++11 | + | * Write modern, idiomatic C++ using the new features of C++11; use the -std= CXXFLAGS value in configure.ac to see if you can use features introduced in C++14 or C++17 (as of this writing you may not). In particular: |
− | + | ** Prefer curly braces for initializers and <tt>auto</tt> for variable declarations. | |
− | * | + | ** Declare and initialize variables in one statement at the point that they're first used. |
− | * | + | ** Use templates instead of copying code and especially instead of preprocessor macros. |
+ | ** Prefer passing references to pointers. | ||
+ | ** '''Do not ''ever''''' pass void* (aka gpointer) in C++ code. Use templates or class hierarchies to enforce type safety. | ||
= Framework = | = Framework = |
Revision as of 18:28, 8 March 2016
C Format
Gnucash is fairly relaxed about code format, but we will periodically run a reformatter called Artistic Style (astyle) over the code to clean it up. To reduce the need for this (it messes up VCS history, particularly "blame"), please format your code as follows.
In general, follow the GNU format except use four spaces instead of two for the indents, and don't indent the braces. To summarize, a properly formatted function will look like this:
guint gnc_account_foo (Account *account, gpointer bar) { Split *baz; guint salt; if (gnc_split_waldo (baz) > 0) { salt = gnc_split_pepper (baz); } return salt; }
Please keep lines under 80 characters. If you need to wrap, line up the function arguments like this:
gnc_account_function_with_a_lot_of_paramters (LongTypeName foo, LongerTypeName *bar, TypeName baz) { }
We don't do the wide separation of names and aligned parameters, so don't do this:
void gnc_account_foo (Account *bar, Split *baz, gpointer waldo); Split *gnc_account_pepper (Account *salt, Transaction *sausage);
Instead, do it this way:
void gnc_account_foo (Account *bar, Split *baz, gpointer waldo); Split *gnc_account_pepper (Account *salt, Transaction *sausage);
For the record, the astyle commandline we use (with astyle version 1.24; other versions might result in slightly different formatting) is
astyle --indent=spaces=4 --brackets=break --pad-oper *.[hc]
The rationale for the arguments is contained in this email.
C++ Format
C++ follows the C format guidelines above, with the following modifications:
- Namespaces shall be all lower case, and the outermost one shall be named gnc.
- Identifier formats:
- Typenames (i.e. class, struct, enum, and POD type-aliases) shall be camel-cased.
- Function and object names shall be lower-case and shall have words separated by underscores.
- Preprocessor Macros and enumeration names shall be upper-case with words separated by underscores.
In addition, certain types of variables shall have prefixes denoting their roles:
- Member variables: m_.
- Static member variables (a.k.a class variables): c_.
- Static constants: k_.
- Free static variables: s_. Free static variables means statics which are not local and not members of a class or struct, regardless of scope.
Other Formatting:
- Use C-style comments for multi-line comments and C++-style for end-of-line comments; either is OK for single-line standalone comments.
- Headers and implementation files should be named for the class they declare or implement. In general any file should declare or implement only one class.
Coding Guidance
- Write modern, idiomatic C++ using the new features of C++11; use the -std= CXXFLAGS value in configure.ac to see if you can use features introduced in C++14 or C++17 (as of this writing you may not). In particular:
- Prefer curly braces for initializers and auto for variable declarations.
- Declare and initialize variables in one statement at the point that they're first used.
- Use templates instead of copying code and especially instead of preprocessor macros.
- Prefer passing references to pointers.
- Do not ever pass void* (aka gpointer) in C++ code. Use templates or class hierarchies to enforce type safety.
Framework
Gnucash is a Gtk+ project. It's design is object-oriented. The current object orientation is implemented mostly with Gnome's GObject C-language framework and makes heavy use of GLib. While this is a rich eco-system, it brings with it a huge number of dependencies which makes GnuCash difficult to port to other operating systems. Consequently the developers have decided to migrate all of GnuCash except the GUI to C++. No new GObject or GLib-dependent code should be written; instead use C++, the C++ standard library, and Boost libraries.
Guile and Scheme
Gnucash is partly implemented in a Scheme dialect called Guile. (It was originally written mostly in Guile, but that implementation was largely replaced with C several years ago.) In particular, the reports system and part of the business system are written in Guile. To support that, most of the core "engine" API is wrapped and accessible from Guile.