1999-09-27 18:44:28 +00:00
|
|
|
|
Rules for the code in LyX
|
|
|
|
|
-------------------------
|
2000-10-13 08:44:10 +00:00
|
|
|
|
[updated from the C++STYLE distributed with the GNU C++ Standard]
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
The aim of this file is to serve as a guide for the developers, to aid us to
|
2000-10-13 08:44:10 +00:00
|
|
|
|
get clean and uniform code. This document is still incomplete.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
1999-12-13 21:59:26 +00:00
|
|
|
|
We really like to have new developers joining the LyX Project. However
|
|
|
|
|
since 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 that 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.
|
|
|
|
|
|
2000-08-05 05:17:18 +00:00
|
|
|
|
General
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
|
In general, if you want to contribute to the main source, we expect at least
|
|
|
|
|
that you:
|
|
|
|
|
|
2000-08-05 05:17:18 +00:00
|
|
|
|
- the most important rule first: kiss (keep it simple stupid), always
|
2000-10-13 08:44:10 +00:00
|
|
|
|
use a simple implementation in favor of a more complicated one.
|
|
|
|
|
This eases maintenance a lot.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
- write good C++ code: Readable, well commented and taking advantage of the
|
2000-08-05 05:17:18 +00:00
|
|
|
|
OO model. Follow the formatting guidelines. See Formatting.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
- adapt the code to the structures already existing in LyX, or in case that
|
|
|
|
|
you have better ideas, discuss them on the developer's list before writing
|
|
|
|
|
the code.
|
2000-08-05 05:17:18 +00:00
|
|
|
|
- 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.
|
2000-08-07 20:58:24 +00:00
|
|
|
|
- be aware of exceptions and write exception safe code. See Exceptions.
|
2000-08-05 05:17:18 +00:00
|
|
|
|
- document all variables, methods, functions, classes etc. We are
|
|
|
|
|
using the source documentation program doc++, a program that handles
|
|
|
|
|
javadoc syntax, to document sources. See Source Documentation.
|
|
|
|
|
- we have certain code constructs that we try to follow. See Code
|
|
|
|
|
Constructs.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2000-01-24 18:34:46 +00:00
|
|
|
|
|
2000-10-13 08:44:10 +00:00
|
|
|
|
Submitting Code
|
|
|
|
|
---------------
|
2000-08-05 05:17:18 +00:00
|
|
|
|
|
|
|
|
|
It is implicitly understood that all patches contributed to The LyX
|
2000-10-13 08:44:10 +00:00
|
|
|
|
Project is under the Gnu General Public License, it you have a problem
|
2000-08-05 05:17:18 +00:00
|
|
|
|
with that, don't contribute code.
|
|
|
|
|
|
|
|
|
|
Also please don't just pup up out of the blue with a huge patch (or
|
|
|
|
|
small) that changes something substantial in LyX. Always discuss your
|
2000-10-13 08:44:10 +00:00
|
|
|
|
ideas with the developers on the developers mailing list.
|
2000-08-05 05:17:18 +00:00
|
|
|
|
|
|
|
|
|
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/fix several different things, several
|
|
|
|
|
patches is a much better option.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
2000-08-05 05:17:18 +00:00
|
|
|
|
We also expect you to provide a ChangeLog entry with every patch, this
|
|
|
|
|
describes shortly what the patch is doing. The ChangeLog entry follows
|
|
|
|
|
this syntax:
|
1999-12-13 21:59:26 +00:00
|
|
|
|
|
|
|
|
|
1999-12-13 Lars Gullik Bj<42>nnes <larsbj@lyx.org>
|
|
|
|
|
|
|
|
|
|
* src/support/lyxstring.C (find): assert bug fixed.
|
|
|
|
|
|
2000-08-05 05:17:18 +00:00
|
|
|
|
|
|
|
|
|
Code Constructs
|
|
|
|
|
---------------
|
|
|
|
|
|
|
|
|
|
We have several guidelines on code constructs, some of these exists to
|
|
|
|
|
make the code faster, others to make the code clearer. Yet others
|
|
|
|
|
exists to make us able to take advantage of the strong type checking
|
|
|
|
|
in C++.
|
|
|
|
|
|
|
|
|
|
- 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.
|
|
|
|
|
|
|
|
|
|
- Make the scope of a variable as small as possible.
|
|
|
|
|
|
2000-10-13 08:44:10 +00:00
|
|
|
|
- Prefer preincrement to postincrement whenever possible.
|
|
|
|
|
Preincrement has potential of being faster than postincrement. Just
|
2000-08-05 05:17:18 +00:00
|
|
|
|
thing about the obvious implementations of pre/post-increment. This
|
|
|
|
|
rule applies to decrement too.
|
|
|
|
|
|
|
|
|
|
++T;
|
|
|
|
|
--U;
|
|
|
|
|
-NOT-
|
|
|
|
|
T++; // wrong
|
|
|
|
|
U--; // wrong
|
|
|
|
|
|
|
|
|
|
- Try to minimize evaluation of the same code over and over. This is
|
|
|
|
|
aimed especially at loops.
|
|
|
|
|
|
|
|
|
|
Container::iterator end = large.end();
|
2000-10-12 10:46:06 +00:00
|
|
|
|
for (Container::iterator it = large.begin(); it != end; ++it) {
|
2000-08-05 05:17:18 +00:00
|
|
|
|
...;
|
|
|
|
|
}
|
|
|
|
|
-NOT-
|
|
|
|
|
for (Container::iterator it = large.begin();
|
|
|
|
|
it != large.end(); ++it) {
|
|
|
|
|
...;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-13 08:44:10 +00:00
|
|
|
|
- For functions and methods that return a non-POD type T, return T
|
2000-08-05 05:17:18 +00:00
|
|
|
|
const instead. This gives better type checking, and will give a
|
|
|
|
|
compiler warning when temporaries are used wrongly.
|
|
|
|
|
|
|
|
|
|
T const add(...);
|
|
|
|
|
-NOT-
|
|
|
|
|
T add(...);
|
|
|
|
|
|
2000-09-26 13:54:57 +00:00
|
|
|
|
- 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.
|
|
|
|
|
|
|
|
|
|
enum Foo {
|
|
|
|
|
foo,
|
|
|
|
|
bar
|
|
|
|
|
};
|
|
|
|
|
Foo f = ...;
|
|
|
|
|
switch (f) {
|
|
|
|
|
case foo: ...; break;
|
|
|
|
|
case bar: ...; break;
|
|
|
|
|
default: ...; break; // not needed and would shadow a wrong use of Foo
|
|
|
|
|
}
|
2000-08-05 05:17:18 +00:00
|
|
|
|
|
2000-08-07 20:58:24 +00:00
|
|
|
|
Exceptions
|
|
|
|
|
----------
|
|
|
|
|
|
|
|
|
|
Even if LyX currently is not using exceptions we need to be aware of
|
|
|
|
|
them. 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
|
|
|
|
|
Sutters book[ExC++]
|
|
|
|
|
|
|
|
|
|
"
|
2000-10-12 10:46:06 +00:00
|
|
|
|
1. Basic guarantee: Even in the presence of exceptions thrown by T or
|
|
|
|
|
other exceptions, Stack objects don't leak resources.
|
2000-08-07 20:58:24 +00:00
|
|
|
|
Note that this also implies that the container will be
|
|
|
|
|
destructible and usable even if an exception is thrown wile
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
2. Strong guarantee: If an operation terminates because of an
|
2000-10-13 08:44:10 +00:00
|
|
|
|
exception, program state will remain unchanged.
|
|
|
|
|
This always implies commit-or-rollback semantics, including
|
2000-08-07 20:58:24 +00:00
|
|
|
|
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 there
|
|
|
|
|
guarantees, see Dave Abrahams's documentation of the SGI
|
|
|
|
|
exception-safe standard library adaption at:
|
|
|
|
|
http://www.metabyte.com/~fbp/stl/eg_contract.html
|
|
|
|
|
|
2000-10-12 10:46:06 +00:00
|
|
|
|
Probably the most interesting point here is that when you
|
2000-08-07 20:58:24 +00:00
|
|
|
|
implement the basic guarantee, the strong guarantee often
|
|
|
|
|
comes for free. For example, in our Stack implementation,
|
2000-10-13 08:44:10 +00:00
|
|
|
|
almost everything we did was needed to satisfy just the basic
|
|
|
|
|
guarantee -- and what's presented above very nearly satisfies
|
2000-08-07 20:58:24 +00:00
|
|
|
|
the strong guarantee, with little of no extra work. Not half
|
|
|
|
|
bad, considering all the trouble we went to.
|
|
|
|
|
|
2000-10-12 10:46:06 +00:00
|
|
|
|
In addition to these two guarantees, there is one more
|
2000-08-07 20:58:24 +00:00
|
|
|
|
guarantee that certain functions must provide in order to make
|
|
|
|
|
overall exception safety possible:
|
|
|
|
|
|
2000-10-12 10:46:06 +00:00
|
|
|
|
3. Nothrow guarantee: The function will not emit an exception under any
|
|
|
|
|
circumstances.
|
2000-08-07 20:58:24 +00:00
|
|
|
|
Overall exception safety isn't possible unless certain
|
2000-10-13 08:44:10 +00:00
|
|
|
|
functions are guaranteed not to throw. In particular, we've
|
2000-10-12 10:46:06 +00:00
|
|
|
|
seen that this is true for destructors; later in this
|
2000-08-07 20:58:24 +00:00
|
|
|
|
miniseries, we'll see that it's also needed in certain helper
|
|
|
|
|
functions, such as Swap().
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
For all cases where we might be able to write exception safe functions
|
2000-10-12 10:46:06 +00:00
|
|
|
|
without using try, throw or catch we should do so. In particular we
|
2000-08-07 20:58:24 +00:00
|
|
|
|
should look over all destructors to ensure that they are as exception
|
|
|
|
|
safe at possible.
|
|
|
|
|
|
|
|
|
|
Later when more compiler support exceptions sufficiently well we will
|
|
|
|
|
begin using them too. One reason for this is that the C++ standard
|
|
|
|
|
library actually requires exceptions, e.g. "new" will throw
|
|
|
|
|
bad_allocation if the requested memory is not available.
|
|
|
|
|
|
|
|
|
|
|
2000-08-05 05:17:18 +00:00
|
|
|
|
Formatting
|
|
|
|
|
----------
|
|
|
|
|
|
2000-10-13 08:44:10 +00:00
|
|
|
|
* Only one declaration on each line.
|
2000-08-05 05:17:18 +00:00
|
|
|
|
int a;
|
|
|
|
|
int b;
|
|
|
|
|
-NOT-
|
|
|
|
|
int a, b; // wrong
|
|
|
|
|
This is especially important when initialization is done at the same
|
|
|
|
|
time:
|
|
|
|
|
string a("Lars");
|
|
|
|
|
string b("Gullik");
|
|
|
|
|
-NOT-
|
|
|
|
|
string a("Lars"), b("Gullik"); // wrong
|
|
|
|
|
|
1999-12-13 21:59:26 +00:00
|
|
|
|
* Pointers and references
|
2000-08-05 05:17:18 +00:00
|
|
|
|
char * p = "flop";
|
|
|
|
|
char & c = *p;
|
|
|
|
|
-NOT-
|
|
|
|
|
char *p = "flop"; // wrong
|
|
|
|
|
char &c = *p; // wrong
|
|
|
|
|
|
2000-10-13 08:44:10 +00:00
|
|
|
|
Some time ago we had a huge discussion on this subject and after
|
2000-08-05 05:17:18 +00:00
|
|
|
|
convincing argumentation from Asger this is what we decided. Also note
|
|
|
|
|
that we will have:
|
|
|
|
|
char const * p;
|
|
|
|
|
-NOT-
|
|
|
|
|
const char * p; // wrong
|
1999-12-13 21:59:26 +00:00
|
|
|
|
|
|
|
|
|
* Operator names and parentheses
|
2000-08-05 05:17:18 +00:00
|
|
|
|
operator==(type)
|
|
|
|
|
-NOT-
|
|
|
|
|
operator == (type) // wrong
|
1999-12-13 21:59:26 +00:00
|
|
|
|
|
|
|
|
|
The == is part of the function name, separating it makes the
|
2000-08-05 05:17:18 +00:00
|
|
|
|
declaration look like an expression.
|
1999-12-13 21:59:26 +00:00
|
|
|
|
|
|
|
|
|
* Function names and parentheses
|
2000-08-05 05:17:18 +00:00
|
|
|
|
void mangle()
|
|
|
|
|
-NOT-
|
|
|
|
|
void mangle () // wrong
|
1999-12-13 21:59:26 +00:00
|
|
|
|
|
|
|
|
|
* Enumerators
|
2000-08-05 05:17:18 +00:00
|
|
|
|
enum {
|
|
|
|
|
one = 1,
|
|
|
|
|
two = 2,
|
|
|
|
|
three = 3
|
|
|
|
|
};
|
|
|
|
|
-NOT-
|
|
|
|
|
enum { one = 1, two = 2, three 3 }; // wrong
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
* Naming rules for classes
|
|
|
|
|
|
|
|
|
|
- Use descriptive but simple and short names. For stuff specific to LyX
|
|
|
|
|
use LyX as prefix. Some modules, like mathed or spellchecker, could have
|
|
|
|
|
other prefixes.
|
1999-12-13 21:59:26 +00:00
|
|
|
|
[I am not so sure about the LyX prefix]
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
- Class names are usually capitalized, and function names lowercased.
|
1999-12-13 21:59:26 +00:00
|
|
|
|
Enums are named like Classes, enum values in CAPS.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
- Long variables are named like thisLongVariableName.
|
|
|
|
|
|
2000-10-12 10:46:06 +00:00
|
|
|
|
New types are capitalized, so this goes for typedefs, classes, structs
|
2000-08-05 05:17:18 +00:00
|
|
|
|
and enums.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
* Formatting
|
|
|
|
|
|
|
|
|
|
- Please adapt the formatting of your code to the setting in LyX in that
|
|
|
|
|
particular file. Lars and Asger are slowly, but surely moving the source
|
|
|
|
|
towards Linux kernel style formatting, aka K&R style. We suggest that you
|
|
|
|
|
also do this, but this is NOT something that has been decided generally.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* Use existing structures
|
|
|
|
|
|
2000-10-13 08:44:10 +00:00
|
|
|
|
- Use string wherever possible. LyX will someday move to Unicode, and
|
1999-12-13 21:59:26 +00:00
|
|
|
|
that will be easy if everybody uses string now.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
- Check out the filename and path tools in filetools.h
|
|
|
|
|
|
1999-12-13 21:59:26 +00:00
|
|
|
|
- Check out the string tools in lstring.h, and the SubString class
|
|
|
|
|
and the regex class.
|
|
|
|
|
|
|
|
|
|
- Use the DebugStream class to report errors and messages using
|
2000-10-13 08:44:10 +00:00
|
|
|
|
the lyxerr instantiation.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
[add description of other existing structures]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* Declarations
|
|
|
|
|
|
|
|
|
|
- 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
|
2000-10-12 10:46:06 +00:00
|
|
|
|
implementors of the class (you). [Obviously not true since this is
|
1999-12-13 21:59:26 +00:00
|
|
|
|
for developers, and we do not want one developer only to be able to
|
|
|
|
|
read and understand the implementation of class internals. Lgb]
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
- Avoid to declare global objects in the declaration file of the class.
|
|
|
|
|
If the same variable is used for all object, use a static member.
|
|
|
|
|
|
|
|
|
|
- Avoid global or static variables. An exception to this rule is
|
|
|
|
|
very private stuff like the math stack.
|
|
|
|
|
|
|
|
|
|
- Use the const keyword like this: char const * instead of const char *
|
|
|
|
|
because this is more logical.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* Documentation
|
|
|
|
|
|
|
|
|
|
- The documentation is generated from the header files.
|
|
|
|
|
- You document for the other developers, not for yourself.
|
2000-10-13 08:44:10 +00:00
|
|
|
|
- You should document what the function does, not the implementation.
|
1999-09-27 18:44:28 +00:00
|
|
|
|
- in the .C files you document the implementation.
|
1999-12-13 21:59:26 +00:00
|
|
|
|
- Single line description (///), multiple lines description (/** ... */)
|
1999-09-27 18:44:28 +00:00
|
|
|
|
- You make the documentation by doing "make srcdoc" in the root,
|
|
|
|
|
and then you'll find HTML in the srcdoc/ directory. Read with
|
|
|
|
|
Netscape for best results.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* NAMING RULES FOR USER-COMMANDS
|
|
|
|
|
|
|
|
|
|
Here's the set of rules to apply when a new command name is introduced:
|
|
|
|
|
|
|
|
|
|
1) Use the object.event order. That is, use `word-forward' instead of
|
|
|
|
|
`forward-word'.
|
|
|
|
|
2) Don't introduce an alias for an already named object. Same for events.
|
|
|
|
|
3) Forward movement or focus is called `forward' (not `right').
|
|
|
|
|
4) Backward movement or focus is called `backward' (not `left').
|
|
|
|
|
5) Upward movement of focus is called `up'.
|
|
|
|
|
6) Downward movement is called `down'.
|
|
|
|
|
7) The begin of an object is called `begin' (not `start').
|
|
|
|
|
8) The end of an object is called `end'.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* Using external GUI constructors (XForms fdesign)
|
|
|
|
|
|
|
|
|
|
- Fdesign generated files should not be changed at all. The only changes
|
2000-09-26 13:54:57 +00:00
|
|
|
|
needed are gettext, compability with 0.88 or when you have made your own
|
1999-09-27 18:44:28 +00:00
|
|
|
|
xforms objects and have just a dummy in the .fd file in place of your
|
|
|
|
|
own. In case you have to change the generated files for any of the
|
|
|
|
|
reasons above, you should provide a patch against the clean generated
|
|
|
|
|
file. Your callbacks must be in a separate file.
|
2000-03-06 02:42:40 +00:00
|
|
|
|
|
|
|
|
|
*************************************************************
|
|
|
|
|
|
|
|
|
|
How to create class interfaces.
|
|
|
|
|
(a.k.a How Non-Member Functions Improve Encapsulation)
|
|
|
|
|
======================================================
|
|
|
|
|
|
|
|
|
|
I recently read an article by Scott Meyers in C/C++ Users
|
|
|
|
|
Journal (Vol.18,No.2), where he makes a strong case on how non-member
|
|
|
|
|
functions makes classes more encapsulated, not less. Just to skipping
|
|
|
|
|
to the core of this provides us with the following algorithm for
|
|
|
|
|
deciding what kind of function to add to a class interface:
|
|
|
|
|
|
|
|
|
|
- We need to add a function f to the class C's API.
|
|
|
|
|
|
|
|
|
|
if (f needs to be virtual)
|
|
|
|
|
make f a member function of C;
|
|
|
|
|
else if (f is operator>> or operator<<) {
|
2000-10-13 08:44:10 +00:00
|
|
|
|
make f a non-member function;
|
2000-03-06 02:42:40 +00:00
|
|
|
|
if (f needs access to non-public members of C)
|
|
|
|
|
make f a friend of C;
|
|
|
|
|
} else if (f needs type conversions on its left-most argument) {
|
|
|
|
|
make f a non-member function;
|
|
|
|
|
if (f needs access to non-public members of C)
|
|
|
|
|
make f a friend of C;
|
|
|
|
|
} else if (f can be implemented via C's public interface)
|
|
|
|
|
make f a non-member function;
|
|
|
|
|
else
|
|
|
|
|
make f a member function of C;
|
|
|
|
|
|
|
|
|
|
Unfortunately, to make the best use of this kind of Class API's we
|
2000-10-13 08:44:10 +00:00
|
|
|
|
need namespaces. As soon as Jean-Marc stops using gcc 2.8 and other
|
2000-03-06 02:42:40 +00:00
|
|
|
|
compilers seem more or less up to date on namespaces we will begin to
|
|
|
|
|
use them. _BUT_ we should begin to use the above algoritm ASAP. We
|
|
|
|
|
should also go through old code and apply this algorithm to the
|
|
|
|
|
existing member functions. That will help maintainability in the
|
|
|
|
|
future.
|
|
|
|
|
|
2000-08-05 05:17:18 +00:00
|
|
|
|
(I'll fill in more from Scott Meyers article when time allows.)
|
2000-08-07 20:58:24 +00:00
|
|
|
|
|
|
|
|
|
References
|
|
|
|
|
----------
|
|
|
|
|
|
|
|
|
|
[ExC++] Sutter, Herb. Exceptional C++: 47 engineering puzzles,
|
|
|
|
|
programming problems, and solutions. ISBN 0-201-61562-2
|