NASPRO - The 'NASPRO Architecture for Sound PROcessing'

User login

Who's online

There are currently 0 users and 0 guests online.

Syndicate

Syndicate content

Valid XHTML 1.0 Strict
Valid CSS
Viewable with Any Browser

Naming conventions

camelCase vs wide_names

The wide_names style is used throughout the whole library code. There is no particular reason for this, it's just that I like it more ;-)

Prefixes and suffixes

Namespace

In order to avoid possible name clashes with other code, all exported symbols (to be more precise: the ones which are always exported, see below) of this library have to start with the nacore_ prefix, while all the #define directives declared in the public headers (and meant to be directly used by host and module developers) should begin with the NACORE_ prefix.

Visibility

This is a potentially tricky issue: the only way to be (almost) sure that a symbol is never exported, whatever OS/build system/machine used, is to declare it as static (and so use it only in that source file). In practice, though, it's not that simple, since it often happens that you want to access a "private" library function declared in another source file.

While on many build systems/OSes it is possible to use some specific keywords to export/hide symbols, this is not generally true.

To face such issue properly, the NASPRO core library follows a simple and portable approach, consisting of:

  • a collection of macros to be used when declaring non-static global symbols, wrapping system-specific visibility keywords (NACORE_PUBLIC_*() and NACORE_PRIVATE_*() macros defined in include/NASPRO/core/cpp.h);
  • using the _nacore_ prefix (notice the extra underscore at the beginning) for non-static global symbols (the ones declared with NACORE_PRIVATE_*()) which are not meant to be exported (this is because it's not guaranteed that they don't actually get exported) - the same goes for #defines which have to be included in public headers but are not meant to be used by hosts (the prefix becomes _NACORE_).

#defines

As you have certainly noticed, all #defined macro/constant names are written in uppercase. This is a widely used (and good) convention among C programmers.

typedefs, structs and enums

Again, the names of types which are not meant to be used by the host should begin with _nacore_, while in the other case they should start with nacore_.

There are only two more rules: all typedef names should end with the _t suffix and all typedefed function pointer types should end with the _func_t suffix.

Module symbols

All symbols to be retrieved in modules directly by the NASPRO core library should begin with the nacore_ prefix as well.

Prefixes should be avoided for…

  • static symbols and types in source files;
  • local (inside a function's body) symbols;
  • function and macro parameters.

Choosing names

Apart from the prefixing/suffixing rules described above, there are some other (more relaxed) conventions for choosing names properly.

First of all, it's important to point out what is considered to be important when naming something. Here's a priority ordered list:

  1. No ambiguity: names should be chosen so that their meaning is clear enough not to be confused in any way;
  2. Consistence: when a name for a given resource is chosen, everything else referring to that resource has to use that same name unmodified (for example if an array type named nacore_array_t is defined, every name of function handling such arrays should contain array and not Array, arr, etc.);
  3. Predictability: make so that host developers can realistically guess names without directly knowing about them;
  4. Brevity: short names (when fully understandable and not ambiguous) are not only an improvement in readability, but also in performance (take a look at the "How To Write Shared Libraries" paper by Ulrich Drepper).

Let's get more in depth.

Types

Type names should be no longer than two words, since they're very likely to be used in functions as well.

Short, but well established and understandable, acronyms are allowed. For example nacore_rbtree_t is fine, while nacore_red_black_tree_t is not.

Variables

When naming variables is important to be informative and concise.

Following conventions used nearly everywhere (like single letters for counters or abbreviations like max and min) and reusing variables is ok.

As a general rule of thumb: there should be no need to comment on what a variable is used for (only exception being reuse).

Functions and macros

From a naming point of view, there are two kinds of functions: the ones which are strongly related to a type or a part of the library and the ones which are not.

In the latter case naming should simply follow the conventions already mentioned (examples: nacore_init(), nacore_exit()), while in the former case the first part of the name should recall the type/part involved and the rest is chosen as before (examples: nacore_modsys_load_module(), nacore_text_msg_report()).

Then, in order to have a good consistency and predictability, it is important to follow some naming patterns in some partciular cases. Precisely:

  • instantiation function (with or without initialization) names should be in the form: nacore_<optional_part>_<object>_new;
  • freeing function (with or without finalization) names should be in the form: nacore_<optional_part>_<object>_free;
  • initialization function (without instantiation) names should be in the form: nacore_<optional_part>_<object>_init;
  • finalization function (without freeing) names should be in the form: nacore_<optional_part>_<object>_fini;
  • names of functions getting a certain value should be in the form: nacore_<optional_part>_<optional_object>_get_<some_value>;
  • names of functions setting a certain value should be in the form: nacore_<optional_part>_<optional_object>_set_<some_value>;
  • ...

The same rules apply to macros as well (obviously using uppercase names).

Copyright © 2007, 2008 Stefano D'Angelo