Skip to content

MeaningfulNaming

djewsbury edited this page Feb 3, 2015 · 3 revisions

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