-
Notifications
You must be signed in to change notification settings - Fork 394
Naming Conventions
C++ allows for arbitrary length identifier names, so there's no reason to be terse when naming variables. I'm looking at you EDIRSK
, EINTSU
, and the rest. You can use multiple full words in a name, what a concept. There are two common styles for separating words in a name:
CamelCase
snake_case
The C/C++ libraries use snake_case
(think size_type
or std::unordered_map
) which has the advantage that it can also work with spell checkers. CamelCase
is more common with Java. I personally prefer snake_case
, but all of those underscores can really do a number on your right pinky! I have seen both in EnergyPlus.
One aspect of a naming convention is distinguishing types from variables. There are a few options here:
- One somewhat common convention is for types start with capital letters (e.g.,
MyClass
) and variable (and function) names start with lower-case letters (e.g.,myVariable
).- [SM] Do we want to specify a preference for my_method over myMethod? The former is probably more common now. Qt and some libs use the latter. An exclusion when the case is vital to the meaning should be allowed.
- Another convention I have seen is for types to start or end with a certain character group. For instance, all
struct
/class
types either start withC_
or end with_c
and all enumerated types start withT_
or end with_t
(e.g.,C_MyClass
orMyClass_c
). - Another possibility is to use the keywords
struct
,class
, andenum
whenever declaring a variable of the appropriate type (e.g.,class MyClass object
). C++ does not require this, but it can help with "self documentation". And sometimes syntax coloring too!
EnergyPlus does not currently follow any standard practice here, not even the lower-case/upper-case split.
Another aspect of a naming convention is distinguishing variables of different scopes, i.e., local, global, object, and (since C++14) compile-time constants. EnergyPlus doesn't actually use global variables anymore (see this page for an explanation) so this is really just for local and object variables and compile time constants. Here are some possibilities:
- One way to distinguish object variable names is to prepend references to them with
this->
if the object name is not otherwise explicit. C++ does not require this because it has a precedence/shadowing rule for variable resolution and so it assumes (this->
) if the variable is not declared locally, but this is a possibility. - Another mechanism for distinguishing object variable names is to prepend them with
m_
(which is short formember
).- [SM] Name decorating by storage type is needed to distinguish the data from its accessors but putting the decoration at the front of the name obscures readability. Suggest
x
for public data,x_
for private data,x()
for accessors for readability.
- [SM] Name decorating by storage type is needed to distinguish the data from its accessors but putting the decoration at the front of the name obscures readability. Suggest
- One convention for distinguishing constants is by making them all-caps, e.g.,
constexpr int PI=3.14159265358979323
.- [SM] That is more common for macros. Could be informative to readers on the other hand sometimes the constness is an implementation detail that shouldn't leak into the point of use. Also, it emphasizes the constants visually when they may be relatively unimportant:
foo( arg, ROUTINENAME )
is not lovely. - [AR] This has been my experience as well.
- [SM] That is more common for macros. Could be informative to readers on the other hand sometimes the constness is an implementation detail that shouldn't leak into the point of use. Also, it emphasizes the constants visually when they may be relatively unimportant:
- Local variables (including function parameters, which are technically local to the function) are typically not decorated in any special way, and so are identified by this lack of decoration.
EnergyPlus does not follow any consistent practice here either!
Back in the day (it was a Wednesday) there was this practice called Hungarian Notation (named after Microsoft Word developer and Chief Architect Charles Simonyi) that prepended every variable with a signature corresponding to its type, e.g., szName
(sz
is the signature for zero/null-terminated string) and arriZones
(arri
is the signature for array of int
). I have seen a bit of this in EnergyPlus, specifically type names or type values starting with i
(indicating int
), but it is not pervasive. I don't believe Hungarian is used much these days and I don't think there is much value in using it in EnergyPlus.
A pervasive pattern in EnergyPlus is to give arrays and other collections singular names, e.g., EPVector<DataHeatBalance::ZoneData> Zone
or EPVector<DataSurfaces::SurfaceData> Surface
. A better practice is to use plural names or names that at least suggest that this is a collection of more than one object, e.g., EPVector<DataHeatBalance::ZoneData> zones
or EPVector<DataSurfaces::SurfaceData> surfaceVec
.
Actually there are a few other naming problems with these declarations. First, DataHeatBalance
and DataSurfaces
are not good namespace
names, HBal
and Surf
are better (see this page for an explanation). Second, ZoneData
and SurfaceData
are not good type names. So, what you're telling me is that these classes contain ... data? Get out of here! Zone_c
and Surface_c
or even just Zone
and Surface
(with the struct
modifier). EPVector<HBal::Zone_c> zones;
or EPVector<struct Surf::Surface> surfaceList;
. Isn't that better?
The canonical loop induction variable is i
. If you have nested loops, the convention is to use j
, k
, etc. for the second, third, and so on loop levels.