-
Notifications
You must be signed in to change notification settings - Fork 73
MeaningfulNaming
#Meaningful naming
Consider carefully how you name identifiers. Use lots of meaning, and little space.
###Examples to avoid
Who was it that said that poets should compress meaning down to it's most concise components, twisting the language into it's most effective form? Isn't that the job of a programmer?
How we name things matters. And programmers name things constantly. It's handy to be good at it.
namespace BadExamples
{
class Foo
{
public:
// avoid -- prefer to rephrase in positive way
// (also consider adding "Is" at the start)
bool Bad();
// avoid -- it's negative, and it's too long
bool DoesNotHavePendingResources();
};
// avoid -- Box and Ray are mentioned in a
// different order to parameters. It's confusing
auto BoxVsRayIntersection(const Ray&, const Box&) -> IntersectionResult;
}
###Use positive phrasing
Generally it's clear to use positive phrasing on function names.
Consider:
// double negative is hard to understand...
if (!foo.DoesNotHavePendingResources()) {}
if (!(readyToExecute || foo.DoesNotHavePendingResources())) {}
// "HasPendingResources" is clearer with or without the "not"
if (foo.HasPendingResources()) {}
if (!foo.HasPendingResources()) {}
###Use "Calculate" in the name of expensive functions
Consider:
class Foo
{
public:
Float3 GetPosition() const;
Float3 CalculatePosition() const;
}
Most clients will generally expect GetPosition()
to be a very short. Upon first reading, we might expect GetPosition()
to be an inline function that just returned member.
However, CalculatePosition()
is explicitly the opposite. CalculatePosition()
needs to do some work to return the position. So a client should not call it multiple times from the same functions (cache the result instead!)
###Common names used in XLE
Some names are repeated in many places in XLE:
class Foo
{
public:
// "moveFrom" and "copyFrom" are often used in
// for constructors and assignment operators.
Foo(const Foo& copyFrom);
Foo& operator=(const Foo& copyFrom);
Foo(Foo&& moveFrom);
Foo& operator=(Foo&& moveFrom);
};
// "lhs" and "rhs" are often used for operators
bool operator(const Foo& lhs, const Foo& rhs);
###Naming geometric transforms
Prefer to use "AToB" type names for geometric transforms.
Eg, localToWorld
, cellToProjection,
worldToView
.
These tend to be clearer than viewTransform,
cellTransform,
etc.
###Named casting operators
A "named casting operator" is a function that will convert one object to another. In XLE, these functions typically take the form:
NewObject As{NewObject}(const OldObject&);
For example:
Float4x4 AsFloat4x4(const Float3x4&);
Float3x4 AsFloat3x4(const Float4x4&);
float* AsFloatArray(Float4x4& m);
This is similar to the C# style of named casting operators.
These types of functions are expected to be (generally) nondestructive. In the above example, AsFloat4x4(const Float3x4&)
is nondestructive (no information is lost in the conversion).
However, AsFloat3x4(const Float4x4&)
can sometimes be destructive (according to our rules of 3x4 geometric transform matrices). In a case like this, we would expect to find an assert
in AsFloat3x4
to check for cases where information might be lost.