Naming Conventions#

Caution

This guide has been based on LSST’s C++ API documentation guide. Please respect the creators and contributor of the original guide as they have done an external work.

General Limitations#

Warning

Identifiers should consist of English words. Other languages, jargons, jokes or abuses are forbidden.

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.

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.

  • timeRange not taiRange.

Abbreviations#

Abbreviations in names SHOULD be avoided.

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. For example, write:

  • command instead of cmd;

  • copy instead of cp;

  • point instead of pt;

  • compute instead of comp;

  • initialize instead of init.

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

  • html instead of HypertextMarkupLanguage;

  • cpu instead of CentralProcessingUnit;

  • ccd instead of ChargeCoupledDevice.

Acronyms, Initialisms, Alphabetisms#

In English abbreviations have been written with a full stop/period/point in place of the deleted part to show the ellipsis of letters, although the colon and apostrophe have also had this role. Such punctuation is diminishing with the belief that the presence of all-capital letters is sufficient to indicate that the word is an abbreviation. But, in code, identifiers with acronyms in all-capital letters style are much less readable. That is why we propose to keep using pascal style for acronyms.

For example we choose DomObject instead of DOMObject (where DOM is Document Object Model).

// Use this
enum class Enum
{
    Sfinae
};
// Instead of this
enum class Enum
{
    SFINAE
};

Uppercase acronyms are not allowed for enumerators too.

// Use this
enum class Enum
{
    Sfinae
};
// Instead of this
enum class Enum
{
    SFINAE
};

This rule concerns only established acronyms, initialisms and alphabetisms. Moreover such things should be used sparingly, and limited to very common usages in the relevant community.

Warning

Remember, using of your own acronyms, initialisms or alphabetisms is forbidden.

This means that obscure abbreviations should be avoided too: clarity is probably more important than brevity.

  • apertureDiam would be better than apDia

Booleans#

Names for boolean variables and methods SHOULD be obviously boolean.

Examples of good names include:

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.

Negated boolean variable names MUST be avoided.

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.

Complement names#

Complement names MUST be used for complement operations, as this reduces complexity by symmetry.

For example:

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

Shorternings#

It is recommended to use well-known abbreviations of given domain instead of their full equivalents. Use of one- or two-letter identifiers and shortenings in words is forbidden with exception of worldwide known. However developer (and maintainer) should be consistent in one module bounds.

Examples of allowed shortenings are shown in tables below (list is not closed).

Shortering

Meaning

i, j, k, idx

Loop counters, Index

x, y

Coordinates

e, ex

Exception

init

Initialize

it, itEnd, it* (itObject, itValues)

Iterator

p, *Ptr (pObject, EntityPtr)

Pointer

ref, *Ref (objectRef, valuesRef)

Reference

id

Identifier

opt, *Opt, opt* (optObject, EntityOpt)

Optional

Identifiers#

Scope Designation#

Names of local and non-constant static variables, class members, function and template arguments are prepended with prefix that designates scope.

Scope

Prefix

Example

Local variable

None

int lineSize{ 0 };

Static constant variable

static const int lineSize{ 0 };

Static non-constant variable

static const int lineSize{ 0 };

Static constexpr variable

static constexpr int lineSize{ 0 };

Function parameter

_

func(int _lineSize);

Template type parameter

template<typename _VisitorType>

Template value parameter

template<int _someValue>

Class field

m_

int m_lineSize;

Class static field

ms_

int ms_lineSize;

Global variable

g_

int g_lineSize;

Methods and Functions#

It is recommended to use predefined naming schemes for common actions. Predefined naming schemes can be found below. However if your method name can’t be fit into those schemes, there are some rules that can help you.

  • Names representing methods or functions SHOULD naturally describe the action of the method (and so will usually start with a verb).

  • 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:

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

Methods for creating new objects#

Naming Scheme

Example

Description

create*

EntityPtr createEntity();
std::unique_ptr<Node> createNode();

Method that creates entity objects (e.g. factory methods). Usually return object and do not save it internally.

Should be used in most cases.

build*,

make*,

provide*

SearcherPtr provideSearcher();

Method creates utility objects. Can be used to distinct methods within scope (class).

Prefix create* can be used if you prefer.

clone*

ObjectPtr clone();

Clone method (as exception from create*).

Methods for returning objects#

Naming Scheme

Example

Description

get*

Object const & getObject() const;

Method returns non-null object by reference. if object is not present by some reasons, should throw an exception.

Should have O(1) complexity.

tryGet*

Object const * tryGetObject() const;

Method returns pointer to object that not always exists.

Returned pointer must always be non-owning.

take*

Object const & takeObject() const;

Method returns non-null non-constant object by reference. Prefer this method to overloaded version of get* method.

tryTake*

Object const * tryTakeObject() const;

Method returns by non-constant pointer object that not always exists. Prefer this method to overloaded version of tryGet* method.

Returned pointer must always be non-owning.

find*

Object const * findObject() const;
Object * findObject();

Method searches object and returns optional value (pointer or std::optional).

Method should have O(1)* or O(logN) complexity.

Returned pointer must always be non-owning.

Methods for returning statuses/flags/props#

Naming Scheme

Example

Description

is*

bool isActive() const;
bool isPort() const;

Method answers questions like: * is an object of a specific kind/type? * has it some state (full, initialized, etc)? Should have O(1) complexity.

has*

bool hasChildren() const;

Method answers if object has a certain props.

are*

bool areEqual(...);
bool Class::equalsTo(...) const;

Comparison methods.

Use either free function with 2 (or more) parameters. Second form should be used in case of class method.

get*

int getSize() const;

Methods returns values of some props or flags.

Methods for modifying objects#

Naming Scheme

Example

Description

set*

void setName(...);
void setMatched();

Method modifies single or several props.

reset*

void resetDesign(...);
void resetDesign();

Method can act in two ways: #. cleans props in case of empty parameters, #. or modifies props with new values passed to method.

add*

Object const & addObject(...);
void addObject(Object const &);

Method creates new object, saves to internal collection. And finally return reference to newly created object.

Or method just adds already created object to internal collection.

ensure*

Node const & ensureNode(...);

Same as add*, but used to explicitly point that cache is used. Cache can be used to avoid duplicates or to optimize algorithm.

If object with same properties already exist, it will be returned. No new instance will be created in this case.

try*

void tryEmplace(...);

Method performs action that fails (relatively) often. The fallback function call might be followed after failure.