lyx_mirror/development/coding/CodingRulesAndAdvice.lyx

1807 lines
33 KiB
Plaintext

#LyX 2.0.0svn created this file. For more info see http://www.lyx.org/
\lyxformat 345
\begin_document
\begin_header
\textclass scrbook
\use_default_options true
\language english
\inputencoding auto
\font_roman default
\font_sans default
\font_typewriter default
\font_default_family default
\font_sc false
\font_osf false
\font_sf_scale 100
\font_tt_scale 100
\graphics default
\paperfontsize default
\spacing single
\use_hyperref false
\papersize default
\use_geometry false
\use_amsmath 1
\use_esint 1
\cite_engine basic
\use_bibtopic false
\paperorientation portrait
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\quotes_language english
\papercolumns 1
\papersides 1
\paperpagestyle default
\listings_params "basicstyle={\footnotesize}"
\tracking_changes true
\output_changes false
\author "Kornel Benko" Kornel.Benko@berlin.de
\end_header
\begin_body
\begin_layout Title
LyX Development
\begin_inset Newline newline
\end_inset
Rules and Recommendations
\end_layout
\begin_layout Chapter
Rules for the code in LyX
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
Updated from the C++STYLE distributed with the GNU C++ Standard.
\end_layout
\end_inset
\end_layout
\begin_layout Standard
The aim of this file is to serve as a guide for the developers, to aid us
to get clean and uniform code.
This document is incomplete.
We really like to have new developers joining the LyX Project.
However, we have had problems in the past with developers leaving the project
and their contributed code in a far from perfect state.
Most of this happened before we really became aware of these issues, but
still, we don't want it to happen again.
So we have put together some guidelines and rules for the developers.
\end_layout
\begin_layout Section
General
\end_layout
\begin_layout Standard
These guidelines should save us a lot of work while cleaning up the code
and help us to have quality code.
LyX has been haunted by problems coming from unfinished projects by people
who have left the team.
Those problems will hopefully disappear if the code is easy to hand over
to somebody else.
In general, if you want to contribute to the main source, we expect at
least that you:
\end_layout
\begin_layout Itemize
the most important rule first: KISS (Keep It Simple Stupid), always use
a simple implementation in favor of a more complicated one.
This eases maintenance a lot.
\end_layout
\begin_layout Itemize
write good C++ code: Readable, well commented and taking advantage of the
OO model.
Follow the formatting guidelines.
See Formatting.
\end_layout
\begin_layout Itemize
adapt the code to the structures already existing in LyX, or in the case
that you have better ideas, discuss them on the developer's list before
writing the code.
\end_layout
\begin_layout Itemize
take advantage of the C++ standard library.
Especially don't use custom containers when a standard container is usable;
learn to use the algorithms and functors in the standard library.
\end_layout
\begin_layout Itemize
be aware of exceptions and write exception safe code.
See Exceptions.
\end_layout
\begin_layout Itemize
document all variables, methods, functions, classes etc.
We are using the source documentation program doxygen, a program that handles
javadoc syntax, to document sources.
You can download doxygen from: http://www.stack.nl/~dimitri/doxygen/
\end_layout
\begin_layout Itemize
we have certain code constructs that we try to follow.
See Code Constructs.
\end_layout
\begin_layout Section
Submitting Code
\end_layout
\begin_layout Standard
It is implicitly understood that all patches contributed to The LyX Project
is under the Gnu General Public License, version 2 or later.
If you have a problem with that, don't contribute code.
Also please don't just pop up out of the blue with a huge patch (or small)
that changes something substantial in LyX.
Always discuss your ideas with the developers on the developer's mailing
list.
When you create the patch, please use "diff -up" since we find that a lot
easier to read than the other diff formats.
Also please do not send patches that implements or fixes several different
things; several patches is a much better option.
We also require you to provide a commit message entry with every patch,
this describes in detail what the patch is doing.
\end_layout
\begin_layout Section
Code Constructs
\end_layout
\begin_layout Standard
We have several guidelines on code constructs, some of these exist to make
the code faster, others to make the code clearer.
Yet others exist to allow us to take advantage of the strong type checking
in C++.
\end_layout
\begin_layout Itemize
Declaration of variables should wait as long as possible.
The rule is: "Don't declare it until you need it." In C++ there are a lot
of user defined types, and these can very often be expensive to initialize.
This rule connects to the next rule too.
\end_layout
\begin_layout Itemize
Declare the variable as const if you don't need to change it.
This applies to POD types like int as well as classes.
\end_layout
\begin_layout Itemize
Make the scope of a variable as small as possible.
\end_layout
\begin_layout Itemize
Make good use of namespaces.
Prefer anonymous namespaces to declaring "static" for file scope.
\end_layout
\begin_layout Itemize
Prefer preincrement to postincrement whenever possible.
\end_layout
\begin_layout Itemize
Preincrement has potential of being faster than postincrement.
Just think about the obvious implementations of pre/post-increment.
This rule applies to decrement too.
\end_layout
\begin_layout Itemize
Use:
\end_layout
\begin_deeper
\begin_layout Standard
\begin_inset listings
lstparams "basicstyle={\footnotesize},language={C++}"
inline false
status open
\begin_layout Plain Layout
++T;
\end_layout
\begin_layout Plain Layout
--U;
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Do not use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
T++; // not used in LyX
\end_layout
\begin_layout Plain Layout
U--;// not used in LyX
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
Try to minimize evaluation of the same code over and over.
This is aimed especially at loops.
\begin_inset Newline newline
\end_inset
Use:
\end_layout
\begin_deeper
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
Container::iterator end = large.end();
\end_layout
\begin_layout Plain Layout
for (Container::iterator it = large.begin(); it != end; ++it) {
\end_layout
\begin_layout Plain Layout
...;
\end_layout
\begin_layout Plain Layout
}
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Do not use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
for (Container::iterator it = large.begin(); it != large.end(); ++it) {
\end_layout
\begin_layout Plain Layout
...;
\end_layout
\begin_layout Plain Layout
}
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
For functions and methods that return a non-POD type
\begin_inset Foot
status open
\begin_layout Plain Layout
Plain Ol' Data type
\end_layout
\end_inset
T, return T const instead.
This gives better type checking, and will give a compiler warning when
temporaries are used wrongly.
\end_layout
\begin_deeper
\begin_layout Standard
Use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
T const add(..);
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Do not use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
T add(..);
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
Avoid using the default cases in switch statements unless you have too.
Use the correct type for the switch expression and let the compiler ensure
that all cases are exhausted.
\end_layout
\begin_layout Itemize
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
enum Foo {
\end_layout
\begin_layout Plain Layout
FOO_BAR1,
\end_layout
\begin_layout Plain Layout
FOO_BAR2
\end_layout
\begin_layout Plain Layout
};
\end_layout
\begin_layout Plain Layout
\end_layout
\begin_layout Plain Layout
Foo f = ...;
\end_layout
\begin_layout Plain Layout
\end_layout
\begin_layout Plain Layout
switch (f) {
\end_layout
\begin_layout Plain Layout
case FOO_BAR1: ...;
\end_layout
\begin_layout Plain Layout
break;
\end_layout
\begin_layout Plain Layout
case FOO_BAR2: ...;
\end_layout
\begin_layout Plain Layout
break;
\end_layout
\begin_layout Plain Layout
default: ...;
\end_layout
\begin_layout Plain Layout
// not needed and would shadow a wrong use of Foo
\end_layout
\begin_layout Plain Layout
break;
\end_layout
\begin_layout Plain Layout
}
\end_layout
\end_inset
\end_layout
\begin_layout Section
Exceptions
\end_layout
\begin_layout Standard
Be aware of the presence of exceptions.
One important thing to realize is that you often do not have to use throw,
try or catch to be exception safe.
Let's look at the different types of exceptions safety: (These are taken
from Herb Sutter's book[ExC++]
\end_layout
\begin_layout Enumerate
Basic guarantee: Even in the presence of exceptions thrown by T or other
exceptions, Stack objects don't leak resources.
Note that this also implies that the container will be destructible and
usable even if an exception is thrown while performing some container operation.
However, if an exception is thrown, the container will be in a consistent,
but not necessarily predictable, state.
Containers that support the basic guarantee can work safely in some settings.
\end_layout
\begin_layout Enumerate
Strong guarantee: If an operation terminates because of an exception, program
state will remain unchanged.
This always implies commit-or-rollback semantics, including that no references
or iterators into the container be invalidated if an operation fails.
For example, if a Stack client calls Top and then attempts a Push that
fails because of an exception, then the state of the Stack object must
be unchanged and the reference returned from the prior call to Top must
still be valid.
For more information on these guarantees, see Dave Abrahams's documentation
of the SGI exception-safe standard library adaption at: http://www.stlport.org/do
c/exception_safety.html Probably the most interesting point here is that
when you implement the basic guarantee, the strong guarantee often comes
for free.
For example, in our Stack implementation, almost everything we did was
needed to satisfy just the basic guarantee -- and what's presented above
very nearly satisfies the strong guarantee, with little o
\change_inserted 0 1288157484
r
\change_deleted 0 1288157483
f
\change_unchanged
no extra work.
Not half bad, considering all the trouble we went to.
In addition to these two guarantees, there is one more guarantee that certain
functions must provide in order to make overall exception safety possible:
\end_layout
\begin_layout Enumerate
No throw guarantee: The function will not emit an exception under any circumstan
ces.
Overall exception safety isn't possible unless certain functions are guaranteed
not to throw.
In particular, we've seen that this is true for destructors; later in this
miniseries, we'll see that it's also needed in certain helper functions,
such as Swap().
\end_layout
\begin_layout Standard
For all cases where we might be able to write exception safe functions without
using try, throw or catch we should do so.
In particular we should look over all destructors to ensure that they are
as exception safe as possible.
\end_layout
\begin_layout Section
Formatting
\end_layout
\begin_layout Itemize
Only one declaration on each line.
\end_layout
\begin_deeper
\begin_layout Standard
Use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
int a;
\end_layout
\begin_layout Plain Layout
int b;
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Do not use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
int a,b; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
This is especially important when initialization is done at the same time:
\end_layout
\begin_layout Standard
Use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
string a = "Lars";
\end_layout
\begin_layout Plain Layout
string b = "Gullik";
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Do not use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
string a = "Lars", b = "Gullik"; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
[Note that 'string a = "Lars"' is formally calling a copy constructor on
a temporary constructed from a string literal and therefore has the potential
of being more expensive then direct construction by 'string a("Lars")'.
However the compiler is allowed to elide the copy (even if it had side
effects), and modern compilers typically do so.
Given these equal costs, LyX code favours the '=' idiom as it is in line
with the traditional C-style initialization, _and_ cannot be mistaken as
function declaration, _and_ reduces the level of nested parantheses in
more initializations.]
\end_layout
\end_deeper
\begin_layout Itemize
Pointers and references:
\end_layout
\begin_deeper
\begin_layout Standard
Use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
char * p = "flop";
\end_layout
\begin_layout Plain Layout
char & c = *p;
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Do not use:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
char *p = "flop"; // not used in LyX
\end_layout
\begin_layout Plain Layout
char &c = *p; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Some time ago we had a huge discussion on this subject and after convincing
argumentation from Asger this is what we decided.
Also note that we will have:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
char const * p;
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
const char * p; // not used in LyX
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
Operator names and parentheses
\end_layout
\begin_deeper
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
operator==(type)
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
operator == (type) // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
The == is part of the function name, separating it makes the declaration
look like an expression.
\end_layout
\end_deeper
\begin_layout Itemize
Function names and parentheses
\end_layout
\begin_deeper
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
void mangle()
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
void mangle () // not used in LyX
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
Enumerators
\end_layout
\begin_deeper
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
enum Foo {
\end_layout
\begin_layout Plain Layout
FOO_ONE = 1,
\end_layout
\begin_layout Plain Layout
FOO_TWO = 2,
\end_layout
\begin_layout Plain Layout
FOO_THREE = 3
\end_layout
\begin_layout Plain Layout
};
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
enum { one = 1, two = 2, three 3 }; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
enum {
\end_layout
\begin_layout Plain Layout
One = 1,
\end_layout
\begin_layout Plain Layout
Two = 2,
\end_layout
\begin_layout Plain Layout
Three = 3
\end_layout
\begin_layout Plain Layout
};
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
Null pointers
\end_layout
\begin_deeper
\begin_layout Standard
Using a plain 0 is always correct and least effort to type.
So:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
void * p = 0;
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
void * p = NULL; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
void * p = '
\backslash
0'; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
and not
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
void * p = 42 - 7 * 6; // not used in LyX
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Note: As an exception, imported third party code as well as code interfacing
the "native" APIs (src/support/os_*) can use NULL.
\end_layout
\end_deeper
\begin_layout Itemize
Naming rules for classes
\end_layout
\begin_deeper
\begin_layout Itemize
Use descriptive but simple and short names.
Do not abbreviate.
\end_layout
\begin_layout Itemize
Class names are usually capitalized, and function names lowercased.
\end_layout
\begin_layout Itemize
Enums are named like Classes, values are usually in lower-case.
\end_layout
\begin_layout Itemize
Public API is camel-case ('void setAFlagToAValue(bool)')
\end_layout
\begin_layout Itemize
Members variables are underscored ('enable_this_feature_flag_') with a final
'_'
\end_layout
\begin_layout Itemize
Private/protected functions are also camel-case
\end_layout
\begin_layout Itemize
New types are capitalized, so this goes for typedefs, classes, structs and
enums.
\end_layout
\end_deeper
\begin_layout Itemize
Formatting
\end_layout
\begin_deeper
\begin_layout Itemize
Adapt the formatting of your code to the one used in the other parts of
LyX.
In case there is different formatting for the same construct, use the one
used more often.
\end_layout
\end_deeper
\begin_layout Itemize
Use existing structures
\end_layout
\begin_deeper
\begin_layout Itemize
\change_inserted 0 1288159254
\begin_inset CommandInset label
LatexCommand label
name "Use-string-wherever"
\end_inset
\change_unchanged
Use string wherever possible.
LyX will someday move to Unicode, and that will be easy if everybody uses
string now.
Unicode strings should prefer using docstring instead of UTF-8 encoded
std::string.
\end_layout
\begin_layout Itemize
Check out the filename and path tools in filetools.h
\end_layout
\begin_layout Itemize
Check out the string tools in lstring.h.
\end_layout
\begin_layout Itemize
Use the LyXErr class to report errors and messages using the lyxerr instantiatio
n.
[add description of other existing structures]
\end_layout
\end_deeper
\begin_layout Itemize
Declarations
\end_layout
\begin_deeper
\begin_layout Itemize
Use this order for the access sections of your class: public, protected,
private.
The public section is interesting for every user of the class.
The private section is only of interest for the implementors of the class
(you).
[Obviously not true since this is for developers, and we do not want one
developer only to be able to read and understand the implementation of
class internals.
Lgb]
\end_layout
\begin_layout Itemize
Avoid declaring global objects in the declaration file of the class.
If the same variable is used for all objects, use a static member.
\end_layout
\begin_layout Itemize
Avoid global or static variables.
\end_layout
\end_deeper
\begin_layout Itemize
File headers
\end_layout
\begin_deeper
\begin_layout Standard
If you create a new file, the top of the file should look something like
this :
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
/**
\end_layout
\begin_layout Plain Layout
*
\backslash
file NewFile.cpp
\end_layout
\begin_layout Plain Layout
* This file is part of LyX, the document processor.
\end_layout
\begin_layout Plain Layout
* Licence details can be found in the file COPYING.
\end_layout
\begin_layout Plain Layout
*
\end_layout
\begin_layout Plain Layout
*
\backslash
author Kaiser Sose
\end_layout
\begin_layout Plain Layout
*
\end_layout
\begin_layout Plain Layout
* Full author contact details are available in file CREDITS
\end_layout
\begin_layout Plain Layout
*/
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Itemize
Documentation
\end_layout
\begin_deeper
\begin_layout Itemize
The documentation is generated from the header files.
\end_layout
\begin_layout Itemize
You document for the other developers, not for yourself.
\end_layout
\begin_layout Itemize
You should document what the function does, not the implementation.
\end_layout
\begin_deeper
\begin_layout Itemize
in the .cpp files you document the implementation.
\end_layout
\end_deeper
\begin_layout Itemize
Single line description (///), multiple lines description (/** ...
*/) see the doxygen webpage referenced above
\end_layout
\end_deeper
\begin_layout Section
Naming rules for Lyx User Functions (LFUNs)
\end_layout
\begin_layout Standard
Here is the set of rules to apply when a new command name is introduced:
\end_layout
\begin_layout Enumerate
Use the object.event order.
That is, use `word-forward' instead of`forward-word'.
\end_layout
\begin_layout Enumerate
Don't introduce an alias for an already named object.
Same for events.
\end_layout
\begin_layout Enumerate
Forward movement or focus is called `forward' (not `right').
\end_layout
\begin_layout Enumerate
Backward movement or focus is called `backward' (not `left').
\end_layout
\begin_layout Enumerate
Upward movement of focus is called `up'.
\end_layout
\begin_layout Enumerate
Downward movement is called `down'.
\end_layout
\begin_layout Enumerate
The begin of an object is called `begin' (not `start').
\end_layout
\begin_layout Enumerate
The end of an object is called `end'.
\end_layout
\begin_layout Section
How to create class interfaces
\end_layout
\begin_layout Standard
(a.k.a How Non-Member Functions Improve Encapsulation)
\end_layout
\begin_layout Standard
I recently read an article by Scott Meyers
\change_deleted 0 1288158556
in
\change_unchanged
, where he makes a strong case on how non-member functions makes classes
more encapsulated, not less.
Just skipping to the core of this provides us with the following algorithm
for deciding what kind of function to add to a class interface:
\end_layout
\begin_layout Itemize
We need to add a function f to the class C's API.
\end_layout
\begin_deeper
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
if (f needs to be virtual)
\end_layout
\begin_layout Plain Layout
make f a member function of C;
\end_layout
\begin_layout Plain Layout
else if (f is operator>> or operator<<) {
\end_layout
\begin_layout Plain Layout
make f a non-member function;
\end_layout
\begin_layout Plain Layout
if (f needs access to non-public members of C)
\end_layout
\begin_layout Plain Layout
make f a friend of C;
\end_layout
\begin_layout Plain Layout
} else if (f needs type conversions on its left-most argument) {
\end_layout
\begin_layout Plain Layout
make f a non-member function;
\end_layout
\begin_layout Plain Layout
if (f needs access to non-public members of C)
\end_layout
\begin_layout Plain Layout
make f a friend of C;
\end_layout
\begin_layout Plain Layout
} else if (f can be implemented via C's public interface)
\end_layout
\begin_layout Plain Layout
make f a non-member function;
\end_layout
\begin_layout Plain Layout
else
\end_layout
\begin_layout Plain Layout
make f a member function of C;
\end_layout
\end_inset
\end_layout
\end_deeper
\begin_layout Chapter
Recommendations
\end_layout
\begin_layout Standard
These are some rules for effective C++ programming.
These are taken from Scott Meyers
\begin_inset CommandInset citation
LatexCommand cite
key "key-4"
\end_inset
, and are presented in their short form.
These are not all the rules Meyers presents, only the most important of
them.
LyX does not yet follow these rules, but they should be the goal.
\end_layout
\begin_layout Itemize
use const and inline instead of #define
\end_layout
\begin_layout Itemize
use the same form in corresponding calls to new and delete, i.e.
write delete[] obj; if new obj[n]; was used to create the object and write
delete obj; if you wrote new obj; Notice strings should be std::string's
instead of char *'s.
\change_inserted 0 1288159280
(this contradicts to
\begin_inset CommandInset ref
LatexCommand ref
reference "Use-string-wherever"
\end_inset
)
\change_unchanged
\end_layout
\begin_layout Itemize
define a default constructor, copy constructor and an assignment operator
for all classes with dynamically allocated memory that are not made noncopyable
\end_layout
\begin_layout Itemize
do not define default constructor, copy constructor and an assignment operator
if the compiler generated one would do the same
\end_layout
\begin_layout Itemize
make destructors virtual in base classes and only there
\end_layout
\begin_layout Itemize
assign to all data members in operator=()
\end_layout
\begin_layout Itemize
strive for class interfaces that are complete and minimal
\end_layout
\begin_layout Itemize
differentiate among member functions, global functions and friend functions
\end_layout
\begin_layout Itemize
avoid data members in the public interface
\end_layout
\begin_layout Itemize
use const whenever possible
\end_layout
\begin_layout Itemize
pass and return objects by reference instead of by value
\end_layout
\begin_layout Itemize
choose carefully between function overloading and parameter defaulting
\end_layout
\begin_layout Itemize
never return a reference to a local object or a dereferenced pointer initialized
by new within the function
\end_layout
\begin_layout Itemize
use enums for integral constants
\end_layout
\begin_layout Itemize
minimize compilation dependencies between files
\end_layout
\begin_layout Itemize
pay attention to compiler warnings
\end_layout
\begin_layout Itemize
differentiate between inheritance of interface and inheritance of implementation
\end_layout
\begin_layout Itemize
differentiate between inheritance and templates
\end_layout
\begin_layout Itemize
ensure that global objects are initialized before they are used
\end_layout
\begin_layout Itemize
avoid conditions to 'if' and 'while' that span more than a line
\end_layout
\begin_layout Chapter
\start_of_appendix
Notes
\end_layout
\begin_layout Itemize
And one of mine: (Lgb)
\end_layout
\begin_deeper
\begin_layout Itemize
when swi
\change_inserted 0 1288159389
t
\change_unchanged
ching on enums, refrain from using "default:" if possible
\end_layout
\end_deeper
\begin_layout Itemize
And one of mine: (Andre')
\end_layout
\begin_deeper
\begin_layout Itemize
try to implement your class in a way that the automatically generated copy
constructor and copy assignment work out-of-the box
\end_layout
\begin_layout Itemize
I don't have problems with using boost in the implementation _if and only
if_ it provides actual benefits over less intrusive alternatives.
I do have a problem with needlessly sprinkling 'boost::' over interfaces,
especially if it does not add any value.
\end_layout
\begin_deeper
\begin_layout Standard
Given that there seems to be an unconditional "typedef unsigned int quint32;"
in qglobal.h I don't think there's any platform supported by current LyX
that could not use 'unsigned int' (and an static assert in some implementation
file for the unlikely case some ILP64 zombie raises its ugly head again.
And if that happens, using <cstdint> would still be a better choice...)
\end_layout
\begin_layout Standard
The idea is to create something that's not compilable as soon as the condition
is violated.
There are lots of possibilities to achieve this, some examples follow:
\end_layout
\begin_layout Standard
In C++0x there's a "built-in":
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
static_assert(sizeof(int) == 4, "Funny platform")
\end_layout
\end_inset
\end_layout
\begin_layout Standard
until then on namespace scope:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
#include <boost/static_assert.hpp> BOOST_STATIC_ASSERT(sizeof(int) == 4)
\end_layout
\end_inset
\end_layout
\begin_layout Standard
or without boost:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
template<bool Condition> struct static_assert_helper;
\end_layout
\begin_layout Plain Layout
template <> struct static_assert_helper<true> {};
\end_layout
\begin_layout Plain Layout
enum { dummy = sizeof(static_assert_helper<sizeof(int) == 4>)};
\end_layout
\end_inset
\end_layout
\begin_layout Standard
or somewhat brutish without templates, in any function:
\end_layout
\begin_layout Standard
\begin_inset listings
inline false
status open
\begin_layout Plain Layout
const int d = sizeof(int) - 4;
\end_layout
\begin_layout Plain Layout
switch(0) {
\end_layout
\begin_layout Plain Layout
case 0:
\end_layout
\begin_layout Plain Layout
case !(d*d):
\end_layout
\begin_layout Plain Layout
break;
\end_layout
\begin_layout Plain Layout
}
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Any of them in a .cpp file will break compilation as soon as sizeof(int)
is not equal 4.
Personally I prefer something like the third version (or the first, if
using C++0x is allowed).
\end_layout
\end_deeper
\end_deeper
\begin_layout Itemize
And one of mine: (vfr)
\end_layout
\begin_deeper
\begin_layout Itemize
On dynamics_casts
\begin_inset Flex URL
status open
\begin_layout Plain Layout
http://www.lyx.org/trac/changeset/35855
\end_layout
\end_inset
:
\end_layout
\begin_deeper
\begin_layout Standard
A dynamic_cast is necessary when:
\end_layout
\begin_layout Itemize
the object to be casted is from an external library because we can't add
Qxxx::asXxxx() to Qt e.g.:
\end_layout
\begin_deeper
\begin_layout Itemize
QAbstractListModel to GuiIdListModel,
\end_layout
\begin_layout Itemize
QValidator to PathValidator,
\end_layout
\begin_layout Itemize
QWidget to TabWorkArea,
\end_layout
\begin_layout Itemize
QWidget to GuiWorkArea;
\end_layout
\end_deeper
\begin_layout Itemize
the object is to be casted from an interface to the implementing class,
because the Interface does not know by whom it is implemented:
\end_layout
\begin_deeper
\begin_layout Itemize
ProgressInterface to GuiProgress,
\end_layout
\begin_layout Itemize
Application to GuiApplication.
\end_layout
\end_deeper
\begin_layout Standard
A dynamic_cast can be replaced by:
\end_layout
\begin_layout Itemize
already existing as***Inset() functions, e.g.:
\end_layout
\begin_deeper
\begin_layout Itemize
asHullInset(),
\end_layout
\begin_layout Itemize
asInsetMath()->asMacro(),
\end_layout
\begin_layout Itemize
asInsetText();
\end_layout
\end_deeper
\begin_layout Itemize
A static_cast when we are sure this can't go wrong, e.g.:
\end_layout
\begin_deeper
\begin_layout Itemize
we are sure that CellData::inset->clone() is an InsetTableCell,
\end_layout
\begin_layout Itemize
in cases where we explicitly check it->lyxCode().
\end_layout
\end_deeper
\end_deeper
\end_deeper
\begin_layout Bibliography
\begin_inset CommandInset bibitem
LatexCommand bibitem
key "key-1"
\end_inset
S.
Meyers.
Effective C++, 50 Specific Ways to Improve Your Programs and Design.
Addison-Wesley, 1992
\end_layout
\begin_layout Bibliography
\begin_inset CommandInset bibitem
LatexCommand bibitem
key "key-2"
\end_inset
Sutter, Herb.
Exceptional C++: 47 engineering puzzles, programming problems, and solutions.
ISBN 0-201-61562-2
\end_layout
\begin_layout Bibliography
\begin_inset CommandInset bibitem
LatexCommand bibitem
key "key-4"
\end_inset
Scott Meyers, C/C++ User's Journal (Vol.18,No.2)
\end_layout
\end_body
\end_document