Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Info

This document was drawn from C++ Naming Conventions on the Trac/Wiki. There have been some significant re-formatting for Confluence. The content on this page should be verified before the Trac/Wiki pages are removed.

...

skip-headingsh4
start-numbering-with3
start-numbering-ath2

Naming Conventions

General Naming Conventions

3-0. Guidance on Selecting Names

  • The fundamental quantity being described should appear first in the name, with modifiers concatenated afterward. A rule of thumb is to ask what the units of the quantity would be, and make sure that quantity appears first in the name.
    • "dateObs," not "obsDate" for a quantity that fundamentally is a date/time of significance;
    • "timeObsEarliest" (or, "timeObsFirst"), not "earliestObsTime"
    • "nGoodPix" not "goodPixN" since this is fundamentally a number
    • There are some historical exceptions (e.g., expTime from the FITS standard) that must be preserved
  • Use care to select the most meaningful name to represent the quantity being described
    • "imageMean" not "pixelMean" if we are talking about the mean value of an image, not repeated measurements of a pixel
  • Names should not explicitly include units
    • "skyBackground" not "skyADU" to indicate the sky background level
    • "expMidpoint" rather than "taiMidPoint"; or "timeRange" not "taiRange"
  • Acronyms should be used sparingly, and limited to very common usages in the relevant community.
    • CCD, FWHM, ID, PSF, and RA would be fine as name fragments
  • Obscure abbreviations should be avoided: clarity is probably more important than brevity.
    • "apertureDiam" would be better than "apDia"
  • The Database Schema document should be reviewed for existing appropriate names
    • Check the authoritative DB Column names for the current Project in order to select consistent names between persisted C++ variables and their corresponding DB Columns. Refer to Section 3.3 Names Exposed to Database. (Note: Sect. 3.3 does not appear to exist!)

3-1. Names of user defined types MUST be in mixed case starting with uppercase.

Code Block
languagecpp
class Line, SavingsAccount

struct {
    float bar;
    int  yoMama;
} Foo;
Foo myFoo;

typedef Vector<Frame> FrameVector;

Common practice in the C++ development community. The capitalization rule for class names should be all words in the name capitalized, e.g., "ClassName".

3-2. Variable names MUST be in mixed case starting with lower case.

Code Block
languagecpp
int lineWidth;

Common practice in the C++ development community. Makes variables easy to distinguish from types, and effectively resolves potential naming collision as in the declaration Line line;. Keep variable names balanced between short and longer, more meaningful. Use 8 to 20 characters as a guideline (excluding integer loop counters which may be as little as 1 character).

...

Common practice in the C++ development community.

Code Block
languagecpp
int const MAX_ITERATIONS = 25;
int const MIN_ITERATIONS(23);
enum { HIGH_SCHOOL, GRAMMAR_SCHOOL, KINDEGARTEN };

In general, the use of such constants should be minimized. In many cases implementing the value as a method is a better choice:

Code Block
languagecpp
int getMaxIterations() {     // NOT: int const MAX_ITERATIONS = 25
  return 25;
}

This form is both easier to read, and it ensures a unified interface towards class values.

Note that this rule applies only to const variables that represent constants (i.e. those that would be set using an enum or #define in C); it does not apply to variables that happen to be determined at their point of definition, e.g.:

Code Block
languagecpp
void foo(string const& filename);
float const r2 = r*r;           // radius^2

3-4. Names representing methods or functions SHOULD naturally describe the action of the method (and so will usually start with a verb) and MUST be written in mixed case starting with lowercase. Private member function names MUST additionally lead with an underscore.

Do not put a space between the function name and the opening parenthesis when declaring or invoking the function.

Code Block
languagecpp
class GoodClass {
public:
    void const getPublic() {}           // OK
protected:
    void const getProtected() {}        // OK
private:
    void const _getPrivate() {}         // OK
};

void getName() {...}                    // OK
void computeTotalWidth() {...}          // OK

Refer to Rule 3-10 for a discussion on the leading underscore requirement for private member functions.

Common practice in the C++ development community. This is identical to variable names, but functions in C++ are already distinguishable from variables by their specific form.

3-4a. Names for methods that return new objects MAY start with past-tense verbs.

It is sometimes useful to pair a mutator with a const method that returns a mutated copy of the callee. When it is, the imperative verb in the name of the mutator MAY be changed to the past tense to make the distinction clear. For example:

Code Block
languagecpp
Box b;
b.dilateBy(a); // b is modified
Box c = b.dilatedBy(a); // a modified copy of b is assigned to c

3-5 A name representing a typedef MUST be initial letter capitalized, camel-case with no prefix of the enclosing class.

Code Block
languagecpp
typedef unsigned char Byte;
typedef unsigned long BitMask;
Byte smallMask;

This syntax is consistent with template type names and classes which are also similar in usage.

3-5a. A name representing a typedef SHOULD have a 'T' suffix if and only if necessary to disambiguate the typedef from a template bare name

If the typedef is a template specialization of a concrete type, the typedef name should typically include some indication of the parameter type (e.g. "typedef Image<float> ImageF;"). If the specialization uses an incoming template parameter, the suffix 'T' is preferred to using the specialized template's bare name, as the latter is very difficult to use correctly in C++.

...

The original package developer will specify in the .cc file the preferred abbreviation to use and, optionally, also use it throughout his code. The original developer may consider using the following guideline to fabricate the name

  • remove the preliminary 'lsst';
  • concatenante the remaining fields;
  • if desired to make shorter, abbreviate each field while still maintaining a relevant word.

    Code Block
    languagecpp
    namespace pexLog = lsst:pwx:logging;
    namespace afwMath = lsst::afw::math;

Three options are available for using a namespace when defining symbols

  • Specify the namespace explicitly in the definition

    Code Block
    languagecpp
    lsst::foo::bar::myFunction(...) {...};
  • Use an abbreviation for the namespace

    Code Block
    languagecpp
    namespace fooBar = lsst::foo::bar;
    fooBar::myFunction(...) {...};
  • Put the definitions into a namespace block

    Code Block
    languagecpp
    namespace lsst{
    namespace foo{
    namespace bar{    
       myFunction(...) {...};
    }}}  // lsst::foo::bar

3-7. Names representing template parameters MAY be a single uppercase letter or a mixed case phrase, first letter capitalized in each word, indicating the desired type.

Code Block
languagecpp
template<typename T> ...             // acceptable
template<typename T> ...                // acceptable
template<typename C, typename D> ... // acceptable
template<class PixelType> ...  // acceptable, user-defined class only

Common practices in the C++ development community. Regarding the use of typename versus class, we will adopt the convention of using typename in all cases except where the intent is ONLY a user-defined class and not primitives.

It is recommended that template parameter names that are not a single character be suffixed with 'T' or 'Type' to distinguish them from other, concrete types.

3-8. Abbreviations and acronyms MUST not be uppercase when used as name.

Code Block
languagecpp
exportHtmlSource();    // NOT: exportHTMLSource();
openDvdPlayer();       // NOT: openDVDPlayer();

Using all uppercase for the base name will give conflicts with the naming conventions given above. A variable of this type would have to be named dVD, hTML etc. which obviously is not very readable. Another problem is illustrated in the examples above; When the name is connected to another, the readability is seriously reduced; the word following the abbreviation does not stand out as it should.

...

Code Block
languagecpp
::mainWindow.open(), ::applicationContext.getName(), ::erf(1.0)

In general, the use of global variables should be avoided. Consider using singleton objects instead. Only use where required (i.e. reusing a framework that requires it.) See Rule 5-7.

Global functions in the root namespace that are defined by standard libraries can often be avoided by using the C++ versions of the include files (e.g. "#include <cmath>" instead of "#include <math.h>"). Since the C++ include files place functions in the std namespace, "using namespace std;", which is permitted by Rule 5-41, will allow these functions to be called without using the '::' operator. In cases where functions are only available in the C include files, the '::' operator must be used to call them. This requirement is intended to highlight that these functions are in the root namespace and are different from class methods or other namespaced free functions.

...

(TBD In the future, commentary will be added on restrictions regarding single letter private functions)

 

...

Code Block
languagecpp
class SomeClass
{
private:
    int  _length;
    int  _computeBlob();
}

Apart from its name and its type, the scope of a variable or method is its most important feature.

Indicating class scope by using underscore makes it easy to distinguish class variables from local scratch variables. This is important because class variables are considered to have higher significance than method variables, and should be treated with special care by the programmer. A side effect of the underscore naming convention is that it nicely resolves the problem of finding reasonable variable names for setter methods and constructors:

 

Code Block
languagecpp
void setDepth(int depth){
    _depth = depth;
}

An issue is whether the underscore should be added as a prefix or as a suffix. Both practices are commonly used. Since LSST Data Management uses both C++ and Python as implementation languages, prefixing the underscore is recommended in order to maintain conformity with Python's naming convention where variables and functions with leading underscore are treated specially. Care must be given to avoid using a reserved name.

It should be noted that scope identification has been a controversial issue for quite some time. It seems, though, that this practice now is gaining acceptance and that it is becoming more and more common as a convention in the professional development community.

3-11. Generic variables MAY have the same name as their type.

Code Block
languagecpp
void setTopic(Topic *topic)      // NOT: void setTopic (Topic *value)
                                 // NOT: void setTopic (Topic *aTopic)
                                 // NOT: void setTopic (Topic *x)

void connect(Database *database) // NOT: void connect (Database *db)
                                 // NOT: void connect (Database *oracleDB)

Reduce complexity by reducing the number of terms and names used. Also makes it easy to deduce the type given a variable name only.

If for some reason this convention doesn't seem to fit it is a strong indication that the type name is badly chosen.

Non-generic variables have a role. These variables can often be named by combining role and type:

Code Block
languagecpp
Point startingPoint, centerPoint;
Name  loginName;

3-12. All names MUST be written in English and use American English spelling.

Code Block
languagecpp
int fileName;    // NOT:   int filNavn;
int color;       // NOT:   int colour;

English is the preferred language for international development.

3-13. Variables with a large scope SHOULD have long names, variables with a small scope MAY have short names.

Scratch variables used for temporary storage or indices are best kept short. A programmer reading such variables should be able to assume that its value is not used outside a few lines of code. Common scratch variables for integers are i, j, k, m, n and for characters c and d.

3-14. The name of the object is implicit, and SHOULD be avoided in a method name.

Code Block
languagecpp
line.getLength();    // NOT:  line.getLineLength();

The latter seems natural in the class declaration, but proves superfluous in use, as shown in the example.

3-37 Names representing containers of numeric STL built-ins MUST be of the form: " [capitalized STL name][element type suffix used in afw::image] ".

 

Code Block
languagecpp
std::vector<double> => VectorD
std::list<int> => ListI

3-37a Names representing containers of DM objects SHOULD be of the form: " [element class name, ignoring ptrs][capitalized STL name] ".

Code Block
languagecpp
std::vector<PTR(Span)> => SpanVector
std::list<Box2I> => Box2IList
    • However, containers which have a clear meaning in a particular context, (e.g. MaskPlaneDict), MAY use a name that describes that meaning (like MaskPlaneDict).
    • Or if, for example, a container is logically a list (i.e. doesn't need random access) but is actually a std::vector for simplicity/performance reasons, it may be called a 'List', especially to preserve backwards compatibility.

3-38 Names representing static factory methods SHOULD indicate the special properties of the objects created by that factory method.

Code Block
languagecpp
Vector3d v = Vector3d::orthogonalTo(vector1, vector2);
Vector3d n = Vector3d::northFrom(vector);
Circle c = Circle::empty();

Sometimes, there can be more than one factory method with the same argument signature, all of which create objects with similar characteristics. In this case, the factory method name SHOULD begin with 'from' and indicate the distinguishing properties of the arguments. For example:

Code Block
languagecpp
Angle::fromDegrees(1.0);
Angle::fromRadians(1.0);

Specific Naming Conventions

3-15. The terms 'get/set' MUST be used where an attribute is accessed directly and in the imperative form. The variable name portion should be the same as the actual variable name but now with the first letter capitalized.

 

Code Block
languagecpp
employee.getName();       matrix.getElement (2, 4);
employee.setName(name);   matrix.setElement (2, 4, value);

Common practice in the C++ development community. In Java this convention has become more or less standard. Methods that return a reference to an object for which "set" has no meaning, should not follow this convention. For instance, use:

 

Code Block
languagecpp
Antenna().Drive().getFoo()

rather than:

Code Block
languagecpp
getAntenna().getDrive().getFoo()

3-16. (Deleted)

3-17. The term 'find' SHOULD be used in methods where something is looked up.

 

Code Block
languagecpp
vertex.findNearestVertex();   matrix.findMinElement();

Give the reader the immediate clue that this is a simple look up method with a minimum of computations involved. Consistent use of the term enhances readability.

3-18. The term 'initialize' SHOULD be used where an object or a concept is established.

 

Code Block
languagecpp
printer.initializeFontSet();

The American 'initialize' should be preferred over the English 'initialise'. Abbreviation 'init' should be avoided.

3-19. Variables representing GUI components SHOULD be suffixed by the component type name.

mainWindow, propertiesDialog, widthScale, loginText, leftScrollbar, mainForm, fileMenu, minLabel, exitButton, yesToggle, etc.

Enhances readability since the name gives the user an immediate clue of the type of the variable and thereby the object's resources.

3-20. The suffix 'List' MAY be used on names representing a list of objects.

Code Block
languagecpp
Vertex (one vertex),   vertexList (a list of vertices)

Enhances readability since the name gives the user an immediate clue of the type of the variable and the operations that can be performed on the object.

Simply using the plural form of the base class name for a list (matrixElement (one matrix element), matrixElements (list of matrix elements)) should be avoided since the two only differ in a single character and are thereby difficult to distinguish.

A list in this context is the compound data type that can be traversed backwards, forwards, etc. (typically an STL vector ). A plain array is simpler. The suffix 'Array' can be used to denote an array of objects.

3-21. The prefix 'n' SHOULD be used for variables representing a number of objects.

 

Code Block
languagecpp
nPoints, nLines

The notation is taken from mathematics where it is an established convention for indicating a number of objects.

3-22. The filter name prefix (ugrizy) MUST be used if and only if the name is specific to a filter.

For example:

 

Code Block
languagecpp
float iAmplitude, iPeriod;   // OK
float gAmplitude, gPeriod;   // OK
int iLoopCtr;                // BAD

This recommendation fosters consistent naming of C++ and DB shared persistent objects which use a filter-initial prefix.

Naming DB persistent objects by incorporating their filter band fosters the efficiency of a simple sort rule. If the C++ data is maintained in an array indexed by filter, this rule doesn't apply. See also Rule 3-36. (Note: Rule 3-36 was deleted.)

3-23. Iterator variables SHOULD be declared within the loop scope.

 

Code Block
languagecpp
for (vector<MyClass>::iterator listIter = list.begin(); listIter != list.end(); listIter++){
    Element element = *listIter;
    ...
}

It is not always possible to declare iterator variables in scope (for example if you have several iterators of different type), but do it when you can. Declare additional iterator variables just before the loop, so it's clear that they are associated with the loop.

3-24. Names for boolean variables and methods SHOULD be obviously boolean.

Examples of good names include:

Code Block
languagecpp
bool isSet, isVisible, isFinished, isFound, isOpen;
bool exists();
bool hasLicense(), canEvaluate(), shouldSort()

Common practice in the C++ development community and partially enforced in Java.

Using the 'is' prefix can highlight a common problem of choosing bad boolean names like 'status' or 'flag' . 'isStatus' or 'isFlag' simply doesn't fit, and the programmer is forced to choose more meaningful names.

3-25. Complement names MUST be used for complement operations.

get/set, add/remove, create/destroy, start/stop, insert/delete, increment/decrement, old/new, begin/end, first/last, up/down, min/max, next/previous, old/new, open/close, show/hide, suspend/resume, etc.

Reduce complexity by symmetry.

3-26. Abbreviations in names SHOULD be avoided.

Code Block
languagecpp
computeAverage();     // NOT:  compAvg();

There are two types of words to consider. First are the common words listed in a language dictionary. These must never be abbreviated. Write:

  • command instead of cmd
  • copy instead of cp
  • point instead of pt
  • compute instead of comp
  • initialize instead of init

etc.

Then there are domain specific phrases that are more naturally known through their abbreviations/acronym. These phrases should be kept abbreviated. Write:

  • html instead of HypertextMarkupLanguage
  • cpu instead of CentralProcessingUnit
  • ccd instead of ChargeCoupledDevice

etc.

3-27. Deleted

3-28. Negated boolean variable names MUST be avoided.

Code Block
languagecpp
bool isError;    // NOT:   isNoError
bool isFound;    // NOT:   isNotFound

The problem arises when such a name is used in conjunction with the logical negation operator as this results in a double negative. It is not immediately apparent what isNotFound means.

3-29. Enumeration constants MAY be prefixed by a common type name if at global (or namespace) scope.

 

Code Block
languagecpp
enum { GRADE_HIGH, GRADE_MIDDLE, GRADE_LOW };

Where possible, put enums in appropriate classes, in which case the GRADE_ isn't needed:

Code Block
languagecpp
class Grade {
      enum { HIGH, MIDDLE, LOW };

      Grade() {} Etc. ...
};

This gives additional information of where the declaration can be found, which constants belongs together, and what concept the constants represent.

3-30. Exception classes which indicate an error condition MUST end with Error, otherwise they SHOULD be suffixed with Exception.

Code Block
languagecpp
class AccessError {
  ...
}

Exception classes are really not part of the main design of the program, and naming them like this makes them stand out relative to the other classes.

3-31. Functions (methods returning something) SHOULD be named after what they return and procedures (void methods) after what they do.

Code Block
languagecpp
double & getElevation(unsigned int antennaId), void pointAntenna(Source const & source)

Increase readability. Makes it clear what the unit should do and especially all the things it is not supposed to do. This again makes it easier to keep the code clean of side effects.

3-32. Parameters in functions SHOULD be declared in order of output, input, default input.

Keeps inputs together and when SWIG is used avoids moving output parameters out of the middle of the list.

3-33. (Deleted)

3-34. Uncertainty values associated with a variable SHOULD be suffixed by one of 'Var', 'Cov', 'Sigma'.

There is no universal suffix for uncertainties; i.e. no 'Err' suffix will be used.

The cases that we have identified, and their appropriate suffixes, are:

Standard deviation: 'Sigma' (not Rms, as rms doesn't imply that the mean's subtracted)

Covariance: 'Cov'

Variance: 'Var'

 

Code Block
languagecpp
float xAstrom;          // x position computed by a centroiding algorithm
float xAstromSigma;     // Uncertainty of xAstrom
float yAstrom;
float yAstromSigma;
float xyAstromCov;

 

The postfix 'Err' can easily be misinterpreted as error flags. Use the full 'Sigma' since 'Sig' can easily be misinterpreted as 'Signal'

3-35. Unused.

3-36. (Deleted)

3-39. Names for static functions or methods that read from disk SHOULD start with 'read'.

For consistency with existing code, prefer "read" over "load".

3-40. Names for static methods that naturally start with some sort of creation verb SHOULD start with "make".

...