-
Notifications
You must be signed in to change notification settings - Fork 69
Coding Standard
Start with AL_USD then pascal case
AL_USDProtoStuff
AL_usd_SomeNode
AL_usd_Import
AL_usd_Export
AL_usd_SomeCommand
Use 2 spaces for indentation.
#define AL_ALL_IN_CAPS(X)
Any variables dealing with array lengths, or byte counts, should be size_t. I am a little loose on this definition though - in some places uint32_t may be more appropriate - e.g. Maya's array containers use 32 bit unsigned integers for their counts.
auto is good. Use it wherever it makes sense within function bodies.
void goodUseOfAuto(const std::vector<int>& blah)
{
for(auto i : blah)
{
std::cout << i << "\n";
}
}
class BadUseOfAuto
{
public:
// do not use auto for return types. It's really annoying.
auto getFoo()
{ return m_foo; }
private:
float m_foo;
};
class Base
{
public:
virtual void doStuff();
}:
class Derived : public Base
{
public:
// always use the override specifier
void doStuff() override;
}:
std::vector<int32_t> values = getFromSomewhere();
// use range based for where possible. (for constant values)
for(auto value : values)
{
std::cout << value << std::endl;
}
// use range based for where possible. (for mutable values)
for(auto& value : values)
{
value = 42;
}
// if that is not possible, prefer:
for(auto it = values.begin(), end = values.end(); it != end; ++it)
{
*it = 42;
}
// and if you *really* need indices
for(size_t i = 0, num = values.size(); i != num; ++i)
{
values[i] = i;
}
// This is bad.
for(size_t i = 0; i != values.size(); ++i)
{
values[i] = i;
}
// This is also bad.
for(auto it = values.begin(); it != values.end(); ++it)
{
*it = 42;
}
AL as the first namespace then lower case only namespaces. Contents of the namespaces should not be indented.
namespace AL {
namespace inside {
namespace out {
class Foo {};
}
}
}
Nope, Nope, Nope, Nope. Using namespace is a crime against humanity.
pascal case names
class WellNamedClass
{
public:
WellNamedClass();
/// \brief member functions should start with a lower case.
/// Ideally they should include some doxygen docs!
/// \param someVar Indicate valid values in the docs
/// \return any info about error codes returned is useful.
void memberFunc(int32_t someVar) const;
/// inline functions *can* be good things, but only if they are actually very small!
/// If the function body fits neatly on one line, it's a good inline function.
/// If however the function body is quite large, move it to the cpp file!
inline int32_t someVar() const
{ return m_someVar; }
private:
// member vars should all begin with 'm_',
int32_t m_someVar;
};
Member variables in classes and structs, should ALWAYS be ordered based on sizeof(type), with the biggest variables first, the smallest variables last. This has two nice little side effects:
Compiler generated padding will never be inserted into the middle of a class (only at the end if needed). Variables that require alignment will always be correctly aligned.
struct BadStruct
{
bool m_bool;
int32_t m_int32;
int8_t m_int8;
double m_double;
int16_t m_int16;
float m_float;
};
struct GoodStruct
{
double m_double;
float m_float;
int32_t m_int32;
int16_t m_int16;
int8_t m_int8;
bool m_bool;
};
// sizeof(BadStruct) == 32
// sizeof(GoodStruct) == 24
enums are good things.
If the enums are in the global scope, use 'enum class' to scope the enum values. If the enum is contained within a class, then it's probably easier to use a normal enum Bit flags cannot be 'enum class', so try to scope within a class or namespace. Specifying the base type of the enum is also good (e.g. does it use 32bits, 8bits, etc).
enum class MyEnumType : uint32_t
{
kPossibleValue1,
kPossibleValue2,
kPossibleValue3
};
class SomeType
{
enum MyEnumType : uint32_t
{
kPossibleValue1,
kPossibleValue2,
kPossibleValue3
};
};
if(condition)
{
}
else
if(condition2)
{
}
else
{
}
while(condition)
{
}
for(int i = 0, n = 10; i < n; ++i)
{
}
switch(value)
{
case 1:
break;
case 2:
{
someCode();
}
break;
default:
break;
}
When using multiple conditions within an if or while, make sure the cheapest conditions are on the left
bool enabled = false;
// this is bad
if(someFunctionCall() && enabled)
{
}
// this is better
if(enabled && someFunctionCall())
{
}
When using an if/else statement, ensure that the most likely case happens first
bool unlikelyToBeTrue = someCondition();
// this is bad
if(unlikelyToBeTrue)
{
// mis-predicted branch!
}
else
{
}
// this is better
if(!unlikelyToBeTrue)
{
// branch predictor says thank you!
}
else
{
}
camel case names
WellNamedFile.h
camel case names
libWellNamed.so
physical headers organization and namespaces have to reflect each other
#include "AL/inside/out/WellNamedFile.h"
namespace AL {
namespace inside {
namespace out {
class Foo
{
};
}
}
}
AL as the parent package then lower case only package names
AL.inside.out
pascal case names
class WellNamedClass (Object):
camel case names
wellNamedModule.py