...
Numbered Headings | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Naming ConventionsGeneral Naming Conventions3-0. Guidance on Selecting Names
3-1. Names of user defined types MUST be in mixed case starting with uppercase.
Common practice in the C++ development community. The capitalization rule for class names should be all words in the name capitalized, e.g., " 3-2. Variable names MUST be in mixed case starting with lower case.
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.
In general, the use of such constants should be minimized. In many cases implementing the value as a method is a better choice:
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
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.
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-5. A name representing a typedef MUST be initial letter capitalized, camel-case with no prefix of the enclosing class.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:
3.5 A name representing a typedef MUST be initial letter capitalized, camel-case with no prefix of the enclosing class.
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 nameIf the typedef is a template
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 nameIf the typedef is a template specialization of a concrete type, the typedef name should typically include some indication of the parameter type (e.g. "
The original package developer will specify in the
Three options are available for using a namespace when defining symbols
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.
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 ' 3-8. Abbreviations and acronyms MUST not be uppercase when used as name.
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
:: ' operator.
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. "
(TBD In the future, commentary will be added on restrictions regarding single letter private functions)
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:
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.
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:
3-12. All names MUST be written in English and use American English spelling.
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 3-14. The name of the object is implicit, and SHOULD be avoided in a method name.
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] ".
3-37a Names representing containers of DM objects SHOULD be of the form: " [element class name, ignoring ptrs][capitalized STL name] ".
3-38 Names representing static factory methods SHOULD indicate the special properties of the objects created by that factory method.
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:
Specific Naming Conventions3-15. The terms ' |
Code Block | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
Antenna().Drive().getFoo() |
rather than:
Code Block | ||
---|---|---|
| ||
getAntenna().getDrive().getFoo() |
3-16. (Deleted)
3-17. The term 'find' SHOULD be used in methods where something is looked up.
Code Block | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 ofcmd
copy
instead ofcp
point
instead ofpt
compute
instead ofcomp
initialize
instead ofinit
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 HypertextMarkupLanguagecpu
instead ofCentralProcessingUnit
ccd
instead ofChargeCoupledDevice
etc.
3-27. Deleted
3-28. Negated boolean variable names MUST be avoided.
Code Block | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
enum { GRADE_HIGH, GRADE_MIDDLE, GRADE_LOW }; |
Where possible, put enums in appropriate classes, in which case the GRADE_
isn't needed:
Code Block | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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-
35. Unused.3-36. (Deleted)
...
40. Names for static methods that naturally start with some sort of creation verb SHOULD start with "make".For consistency with existing code, prefer "make" over "build", "create", or "compute" (at least when the method is a static method of the class that is being constructed). |