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