Pegasus Enhancement Proposal (PEP)
PEP #: 221
Title: Pegasus Coding Conventions
Status: Approved
Version History:
Version | Date | Author | Change Description |
---|---|---|---|
1.0 | 23 February 2005 | Roger Kumpf | Initial submittal, based on documents in pegasus/doc directory in CVS (conventions.txt, portability.txt, CodeReviewNotes.txt, and DOCREMARKS). |
1.1 | 1 March 2005 | Roger Kumpf | Updated based on 3/1/05 architecture review comments. Approved version (Ballot 95). |
2.0 | 21 March 2005 | Roger Kumpf | Opened up for additional conventions. |
2.1 | 5 August 2005 | Roger Kumpf | Updated based on comments and architecture team discussions. |
2.2 | 21 February 2006 | Roger Kumpf | Updated based on review comments. |
2.3 | 24 February 2006 | Roger Kumpf | Updated based on review comments and architecture team discussion. |
2.4 | 10 March 2006 | Roger Kumpf | Updated based on ballot comments. Approved version (Ballot 111). |
3.0 | 10 March 2006 | Roger Kumpf | Opened up for additional conventions. |
3.1 | 20 November 2008 | Roger Kumpf | Updated based on review comments. |
3.2 | 26 November 2008 | Roger Kumpf | Updated based on review comments. |
3.3 | 4 December 2008 | Roger Kumpf | Updated based on review comments. Approved version (Ballot 160). |
Abstract: This document formalizes the Pegasus coding conventions.
The following items comprise the Pegasus coding conventions. Suggestions for additional conventions are listed here for discussion:
Proposed Solution
Formatting
Not this:
for (...)
{
}
Or this:
for (...) {
}
for (...)
{
}
if
,
for
, or while
statement), even if the body
contains just a single statement.
Do this:
Not this:
for (...)
{
i++;
}
for (...)
i++;
else
statements rather
than placing then on the same line as a preceding '}
'.
Do this:
Not this:
if (...)
{
i++;
}
else
{
j++;
}
if (...)
{
i++;
} else
{
j++;
}
void MyClass::myMethod(
const char* someReallyLongName,
const char* someOtherReallyLongName);
Not this:
callingMyFunction(
arg1,
arg2,
arg3);
Each argument should be placed on a separate line.
An exception is made for callingMyFunction(arg1,
arg2,
arg3);
PEG_TRACE
and
PEG_TRACE_CSTRING
statements, where the first two
arguments should be placed on the opening line:
PEG_TRACE((TRC_HTTP, Tracer::LEVEL3,
"Connection IP address = %s",
(const char*)_ipAddress.getCString()));
if
, while
, or for
condition that does not fit on a single line, indent peer subconditions
according to their level of nesting and indent other continuation lines
using normal indenting. Do this:
Not this:
if ((variable1 == variable2) ||
((anotherVariableToConsider ==
variable1 + variable2) &&
(dayOfWeek == "Tuesday")))
if ((variable1 == variable2) ||
((anotherVariableToConsider ==
variable1 + variable2) &&
(dayOfWeek == "Tuesday")))
sum = a + b + c +
d + e + f +
g + h;
int
f()
{
}
(void)
" for an empty parameter list.
Use "()
" instead.
Not this:
void f(int i);
f(10);
void f (int i);
f (10);
Not this:
if (i > 0)
for (i = 0; i < 10; i++)
if(i > 0)
for(i = 0; i < 10; i++)
Not this:
if (cond)
while (cond)
if ( cond )
while ( cond )
Not this:
Array<Uint8> myArray;
Array <Uint8> myArray;
Not this:
int x;
float y;
int x;
float y;
public:
",
"protected:
", and
"private:
". Do this:
class X
{
public:
int f();
...
private:
int _g();
...
};
#
' indicating a preprocessing directive is placed
at the beginning of a line. Nested preprocessing directives are
indented with one space after the '#
' for each level of
nesting. The #ifndef
used for header file include protection
is not considered a level of nesting. For example:
#ifdef PEGASUS_HAS_SIGNALS
# ifdef PEGASUS_OS_TYPE_WINDOWS
# include <windows.h>
# else
# include <unistd.h>
# endif
#endif
switch
statement, indent the case
statement from the switch
and indent the case logic from
the case
statement. For example:
switch(n)
{
case 0:
printf("Rock");
break;
case 1:
printf("Paper");
break;
case 2:
printf("Scissors");
break;
default:
printf("Error");
break;
}
return
statement.
Naming
ThisIsAClassName
.
thisIsAMemberName
.
thisIsAMethodName()
.
_thisIsAPrivateMemberName
,
_thisIsAPrivateMethodName()
.
PEGASUS_
.
PEGASUS_CONSTANT_NAME
.
ThisIsAFileName.cpp
.
PEGASUS_
and have
this form: PEGASUS_ENVIRONMENT_VARIABLE
.
This applies to environment variables that control the build and test
configuration as well as those (if any) used by Pegasus at run time.
TestFeature1
.
Style
Not this:
#include <Pegasus/Common/Array.h>
#include "Array.h"
0
" rather than "NULL
"
as a null pointer value.
throw()
declarations. These may be used
only when a method must not (and will not) throw any exception not
specified in the throw clause. When a throw()
clause is needed, include it on the method declaration and definition.
const
declarations liberally,
but not on "plain old data type" parameters.
while this logic causes two String constructions and an assignment:
String s = foo();
String s;
...
s = foo();
new
and delete
to manage dynamic
memory, not malloc
, free
, or
strdup
.catch
block, avoid specifying the object to throw so that exception subtype
information is not lost and construction of an extra exception
object is avoided. Do this:
Not this:
catch (Exception&)
{
...
throw;
}
catch (Exception& e)
{
...
throw e;
}
delete
operator. Do this:
Not this:
delete ptr;
if (ptr)
{
delete ptr;
}
is preferred to this:
void func(const String& s);
void func(String s);
string
class. (These tend to produce bloat and may have
portability issues.) These files should not be included:
<string>
,
<vector>
,
<map>
,
<mmap>
,
<set>
,
<mset>
,
<stack>
,
<queue>
,
and other STL header files.assert()
directly. Instead, use
PEGASUS_ASSERT()
in production code and
PEGASUS_TEST_ASSERT()
in test programs.String::EMPTY
. This is the default value.Buffer::getData()
ensures the resulting string is
null-terminated.Documentation
/** */
rather than ///
for DOC++
comments.
class X
{
public:
/**
Creates widgets.
@param numWidgets The number of widgets to create.
@return true if successful, false otherwise.
*/
Boolean createWidgets(Uint32 numWidgets);
};
/**
Does something useful.
*/
/**
Does something quite useful.
*/
void f();
/**
The previous method has a newline after it
to improve its visibility.
*/
void g();
Portability Considerations
#ifdef
's should be minimized
and discouraged. It is preferred to abstract the mechanics of
dissimilar platforms in separate modules (such as DirPOSIX.cpp vs.
DirWindows.cpp) or by using abstraction functions or macros such as
those that appear below.ostream
, istream
, cout
, and
cerr
) must be enclosed in a PEGASUS_STD()
macro (which prepends std::
to the argument on some
platforms).
PEGASUS_STD()
macro in a source file.
Instead, specify PEGASUS_USING_STD;
at the beginning of
the file.
PEGASUS_USING_STD;
or
PEGASUS_USING_PEGASUS;
in a header file.
PEGASUS_<LIBRARY>_LINKAGE
symbol in a
Linkage.h file. Each symbol that is exported from the library
must be declared with this linkage macro. For example:
class PEGASUS_COMMON_LINKAGE String;
PEGASUS_COMMON_LINKAGE void globalFunction();
main()
function must return an int (required by
Windows NT).
ultostr()
; use sprintf()
instead.
void f() throw TooBad;
Use this instead:
class X
{
public:
static const Uint32 COLOR = 225;
};
And add the definition in the source file:
class X
{
public:
static const Uint32 COLOR;
};
const Uint32 X::COLOR = 225;
PEGASUS_64BIT_CONVERSION_WIDTH
for
printf and scanf conversions of 64-bit integers rather than
ll
or L
.
Do this:
Instead of this:
Sint64 i64 = 10;
printf("i64 value = %" PEGASUS_64BIT_CONVERSION_WIDTH "d.\n", i64);
Sint64 i64 = 10;
printf("i64 value = %lld.\n", i64);
Not this:
class X
{
public:
int myMethod();
};
class X
{
public:
int X::myMethod();
};
Pegasus::
to scope symbols. Not all platforms
support C++ namespaces, and this will cause a compilation failure. If
a symbol must be explicitly scoped to the Pegasus namespace, use the
PEGASUS_NAMESPACE()
macro instead.const
parameters in method
declarations and definitions.Discussion
Copyright (c) 2005 EMC Corporation; Hewlett-Packard
Development Company, L.P.; IBM Corp.; The Open Group;
VERITAS Software Corporation
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following
conditions:
THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE
INCLUDED IN ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Template last modified: March 9th 2004 by Martin Kirk
Template version: 1.8