]> git.lyx.org Git - lyx.git/blob - development/coding/Rules
Scons for the last commit.
[lyx.git] / development / coding / Rules
1 Rules for the code in LyX
2 -------------------------
3 [updated from the C++STYLE distributed with the GNU C++ Standard]
4
5 The aim of this file is to serve as a guide for the developers, to aid us to
6 get clean and uniform code. This document is still incomplete.
7
8 We really like to have new developers joining the LyX Project. However,
9 we have had problems in the past with developers leaving the
10 project and their contributed code in a far from perfect state. Most
11 of this happened before we really became aware of these issues,
12 but still, we don't want it to happen again. So we have put together
13 some guidelines and rules for the developers.
14
15
16 General
17 -------
18
19 These guidelines should save us a lot of work while cleaning up the code and
20 help us to have quality code. LyX has been haunted by problems coming from
21 unfinished projects by people who have left the team. Those problems will
22 hopefully disappear if the code is easy to hand over to somebody else.
23
24 In general, if you want to contribute to the main source, we expect at least
25 that you:
26
27 - the most important rule first: kiss (keep it simple stupid), always
28   use a simple implementation in favor of a more complicated one.
29   This eases maintenance a lot.
30 - write good C++ code: Readable, well commented and taking advantage of the
31   OO model. Follow the formatting guidelines. See Formatting.
32 - adapt the code to the structures already existing in LyX, or in the case
33   that you have better ideas, discuss them on the developer's list before
34   writing the code.
35 - take advantage of the C++ standard library. especially don't use
36   custom containers when a standard container is usable; learn to use
37   the algorithms and functors in the standard library.
38 - be aware of exceptions and write exception safe code. See Exceptions.
39 - document all variables, methods, functions, classes etc. We are
40   using the source documentation program doxygen, a program that handles
41   javadoc syntax, to document sources. You can download doxygen from :
42
43   http://www.stack.nl/~dimitri/doxygen/
44
45 - we have certain code constructs that we try to follow. See Code
46   Constructs.
47
48
49 Submitting Code
50 ---------------
51
52 It is implicitly understood that all patches contributed to The LyX
53 Project is under the Gnu General Public License, version 2 or later.
54 If you have a problem with that, don't contribute code.
55
56 Also please don't just pop up out of the blue with a huge patch (or
57 small) that changes something substantial in LyX. Always discuss your
58 ideas with the developers on the developer's mailing list.
59
60 When you create the patch, please use "diff -up" since we find that a
61 lot easier to read than the other diff formats. Also please do not
62 send patches that implements or fixes several different things; several
63 patches is a much better option.
64
65 We also require you to provide a commit message entry with every patch,
66 this describes in detail what the patch is doing.
67
68
69 Code Constructs
70 ---------------
71
72 We have several guidelines on code constructs, some of these exist to
73 make the code faster, others to make the code clearer. Yet others
74 exist to allow us to take advantage of the strong type checking
75 in C++.
76
77 - Declaration of variables should wait as long as possible. The rule
78   is: "Don't declare it until you need it." In C++ there are a lot of
79   user defined types, and these can very often be expensive to
80   initialize. This rule connects to the next rule too.
81
82 - Declare the variable as const if you don't need to change it. This
83   applies to POD types like int as well as classes.
84
85 - Make the scope of a variable as small as possible.
86
87 - Make good use of namespaces. Prefer anonymous namespaces to declaring
88   "static" for file scope.
89
90 - Prefer preincrement to postincrement whenever possible.
91   Preincrement has potential of being faster than postincrement. Just
92   think about the obvious implementations of pre/post-increment. This
93   rule applies to decrement too.
94
95         ++T;
96         --U;
97         -NOT-
98         T++; // wrong
99         U--; // wrong
100
101 - Try to minimize evaluation of the same code over and over. This is
102   aimed especially at loops.
103
104         Container::iterator end = large.end();
105         for (Container::iterator it = large.begin(); it != end; ++it) {
106                 ...;
107         }
108         -NOT-
109         for (Container::iterator it = large.begin();
110              it != large.end(); ++it) {
111                 ...;
112         }
113
114 - For functions and methods that return a non-POD type T, return T
115   const instead. This gives better type checking, and will give a
116   compiler warning when temporaries are used wrongly.
117
118         T const add(...);
119         -NOT-
120         T add(...);
121
122 - Avoid using the default cases in switch statements unless you have
123   too. Use the correct type for the switch expression and let the
124   compiler ensure that all cases are exhausted.
125
126         enum Foo {
127                 foo,
128                 bar
129         };
130         Foo f = ...;
131         switch (f) {
132         case foo: ...; break;
133         case bar: ...; break;
134         default: ...; break; // not needed and would shadow a wrong use of Foo
135         }
136
137
138 Exceptions
139 ----------
140
141 Even if LyX currently is not using exceptions we need to be aware of
142 them. One important thing to realize is that you often do not have to
143 use throw, try or catch to be exception safe. Let's look at the
144 different types of exceptions safety: (These are taken from Herb
145 Sutter's book[ExC++]
146
147 "
148 1. Basic guarantee: Even in the presence of exceptions thrown by T or
149         other exceptions, Stack objects don't leak resources.
150         Note that this also implies that the container will be
151         destructible and usable even if an exception is thrown while
152         performing some container operation. However, if an exception
153         is thrown, the container will be in a consistent, but not
154         necessarily predictable, state. Containers that support the
155         basic guarantee can work safely in some settings.
156
157 2. Strong guarantee: If an operation terminates because of an
158         exception, program state will remain unchanged.
159         This always implies commit-or-rollback semantics, including
160         that no references or iterators into the container be
161         invalidated if an operation fails. For example, if a Stack
162         client calls Top and then attempts a Push that fails because
163         of an exception, then the state of the Stack object must be
164         unchanged and the reference returned from the prior call to
165         Top must still be valid. For more information on these
166         guarantees, see Dave Abrahams's documentation of the SGI
167         exception-safe standard library adaption at:
168
169         http://www.stlport.org/doc/exception_safety.html
170
171         Probably the most interesting point here is that when you
172         implement the basic guarantee, the strong guarantee often
173         comes for free. For example, in our Stack implementation,
174         almost everything we did was needed to satisfy just the basic
175         guarantee -- and what's presented above very nearly satisfies
176         the strong guarantee, with little of no extra work. Not half
177         bad, considering all the trouble we went to.
178
179         In addition to these two guarantees, there is one more
180         guarantee that certain functions must provide in order to make
181         overall exception safety possible:
182
183 3. Nothrow guarantee: The function will not emit an exception under any
184         circumstances.
185         Overall exception safety isn't possible unless certain
186         functions are guaranteed not to throw. In particular, we've
187         seen that this is true for destructors; later in this
188         miniseries, we'll see that it's also needed in certain helper
189         functions, such as Swap().
190 "
191
192 For all cases where we might be able to write exception safe functions
193 without using try, throw or catch we should do so. In particular we
194 should look over all destructors to ensure that they are as exception
195 safe as possible.
196
197 Later when more compiler support exceptions sufficiently well we will
198 begin using them too. One reason for this is that the C++ standard
199 library actually requires exceptions, e.g. "new" will throw
200 bad_allocation if the requested memory is not available.
201
202
203 Formatting
204 ----------
205
206 * Only one declaration on each line.
207         int a;
208         int b;
209         -NOT-
210         int a, b; // wrong
211   This is especially important when initialization is done at the same
212   time:
213         string a = "Lars";
214         string b = "Gullik";
215         -NOT-
216         string a = "Lars", b = "Gullik"; // wrong
217
218         [Note that 'string a = "Lars"' is formally calling a copy constructor 
219         on a temporary constructed from a string literal and therefore has the
220         potential of being more expensive then direct construction by
221         'string a("Lars")'. However the compiler is allowed to elide the copy
222         (even if it had side effects), and modern compilers typically do so.
223         Given these equal costs, LyX code favours the '=' idiom as it is in
224         line with the traditional C-style initialization, _and_ cannot be
225         mistaken as function declaration, _and_ reduces the level of nested
226         parantheses in more initializations.]
227         
228
229 * Pointers and references
230         char * p = "flop";
231         char & c = *p;
232         -NOT-
233         char *p = "flop"; // wrong
234         char &c = *p;     // wrong
235
236   Some time ago we had a huge discussion on this subject and after
237   convincing argumentation from Asger this is what we decided. Also note
238   that we will have:
239         char const * p;
240         -NOT-
241         const char * p; // wrong
242
243 * Operator names and parentheses
244         operator==(type)
245         -NOT-
246         operator == (type)  // wrong
247
248   The == is part of the function name, separating it makes the
249   declaration look like an expression.
250
251 * Function names and parentheses
252         void mangle()
253         -NOT-
254         void mangle ()  // wrong
255
256 * Enumerators
257         enum {
258                 one = 1,
259                 two = 2,
260                 three = 3
261         };
262         -NOT-
263         enum { one = 1, two = 2, three 3 }; // wrong
264         -NOT-
265         enum {
266                 ONE = 1,
267                 TWO = 2,
268                 THREE = 3
269         };
270
271 * Naming rules for classes
272
273   - Use descriptive but simple and short names. Do not abbreviate.
274
275   - Class names are usually capitalized, and function names lowercased.
276     Enums are named like Classes, values are usually in lower-case.
277
278   - Long variables are named like thisLongVariableName.
279
280   New types are capitalized, so this goes for typedefs, classes, structs
281   and enums.
282
283 * Formatting
284
285   - Adapt the formatting of your code to the one used in the
286     other parts of LyX. In case there is different formatting for
287     the same construct, use the one used more often.
288
289 * Use existing structures
290
291   - Use string wherever possible. LyX will someday move to Unicode, and
292     that will be easy if everybody uses string now. Unicode strings 
293     should prefer using docstring instead of UTF-8 encoded std::string.
294
295   - Check out the filename and path tools in filetools.h
296
297   - Check out the string tools in lstring.h.
298
299   - Use the LyXErr class to report errors and messages using
300     the lyxerr instantiation.
301
302   [add description of other existing structures]
303
304
305 * Declarations
306
307   - Use this order for the access sections of your class: public,
308     protected, private. The public section is interesting for every
309     user of the class. The private section is only of interest for the
310     implementors of the class (you). [Obviously not true since this is
311     for developers, and we do not want one developer only to be able to
312     read and understand the implementation of class internals. Lgb]
313
314   - Avoid declaring global objects in the declaration file of the class.
315     If the same variable is used for all objects, use a static member.
316
317   - Avoid global or static variables. An exception to this rule is
318     very private stuff like the math stack.
319
320
321 * File headers
322
323   - If you create a new file, the top of the file should look something
324     like this :
325
326   /**
327    * \file NewFile.cpp
328    * This file is part of LyX, the document processor.
329    * Licence details can be found in the file COPYING.
330    *
331    * \author Kaiser Sose
332    *
333    * Full author contact details are available in file CREDITS
334    */
335
336 * Documentation
337
338   - The documentation is generated from the header files.
339   - You document for the other developers, not for yourself.
340   - You should document what the function does, not the implementation.
341   - in the .cpp files you document the implementation.
342   - Single line description (///), multiple lines description (/** ... */)
343   - see the doxygen webpage referenced above
344
345
346 * NAMING RULES FOR USER-COMMANDS
347
348   Here's the set of rules to apply when a new command name is introduced:
349
350   1) Use the object.event order. That is, use `word-forward' instead of
351      `forward-word'.
352   2) Don't introduce an alias for an already named object. Same for events.
353   3) Forward movement or focus is called `forward' (not `right').
354   4) Backward movement or focus is called `backward' (not `left').
355   5) Upward movement of focus is called `up'.
356   6) Downward movement is called `down'.
357   7) The begin of an object is called `begin' (not `start').
358   8) The end of an object is called `end'.
359
360
361  *************************************************************
362
363  How to create class interfaces.
364  (a.k.a How Non-Member Functions Improve Encapsulation)
365  ======================================================
366
367         I recently read an article by Scott Meyers in C/C++ User's
368 Journal (Vol.18,No.2), where he makes a strong case on how non-member
369 functions makes classes more encapsulated, not less. Just skipping
370 to the core of this provides us with the following algorithm for
371 deciding what kind of function to add to a class interface:
372
373         - We need to add a function f to the class C's API.
374
375         if (f needs to be virtual)
376                 make f a member function of C;
377         else if (f is operator>> or operator<<) {
378                 make f a non-member function;
379                 if (f needs access to non-public members of C)
380                         make f a friend of C;
381         } else if (f needs type conversions on its left-most argument) {
382                 make f a non-member function;
383                 if (f needs access to non-public members of C)
384                         make f a friend of C;
385         } else if (f can be implemented via C's public interface)
386                 make f a non-member function;
387         else
388                 make f a member function of C;
389
390 (I'll fill in more from Scott Meyers article when time allows.)
391
392 References
393 ----------
394
395 [ExC++] Sutter, Herb. Exceptional C++: 47 engineering puzzles,
396         programming problems, and solutions. ISBN 0-201-61562-2