1 Rules for the code in LyX
2 -------------------------
3 [updated from the C++STYLE distrubuted with the GNU C++ Standard]
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 uncomplete.
8 We really like to have new developers joining the LyX Project. However
9 since 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 that 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.
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.
23 In general, if you want to contribute to the main source, we expect at least
26 - the most important rule first: kiss (keep it simple stupid), always
27 use a simple implementation in favour of a more complicated one.
28 This eases maintenence 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 case that
32 you have better ideas, discuss them on the developer's list before writing
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 doc++, a program that handles
40 javadoc syntax, to document sources. See Source Documentation.
41 - we have certain code constructs that we try to follow. See Code
48 It is implicitly understood that all patches contributed to The LyX
49 Project is under the Gnu General Public Lisence, it you have a problem
50 with that, don't contribute code.
52 Also please don't just pup up out of the blue with a huge patch (or
53 small) that changes something substantial in LyX. Always discuss your
54 ideas with the developers on the developers mailinglist.
56 When you create the patch, please use "diff -up" since we find that a
57 lot easier to read than the other diff formats. Also please do not
58 send patches that implements/fix several different things, several
59 patches is a much better option.
61 We also expect you to provide a ChangeLog entry with every patch, this
62 describes shortly what the patch is doing. The ChangeLog entry follows
65 1999-12-13 Lars Gullik Bjønnes <larsbj@lyx.org>
67 * src/support/lyxstring.C (find): assert bug fixed.
73 We have several guidelines on code constructs, some of these exists to
74 make the code faster, others to make the code clearer. Yet others
75 exists to make us able to take advantage of the strong type checking
78 - Declaration of variables should wait as long as possible. The rule
79 is: "Don't declare it until you need it." In C++ there are a lot of
80 user defined types, and these can very often be expensive to
81 initialize. This rule connects to the next rule too.
83 - Make the scope of a variable as small as possible.
85 - Prefere preincrement to postincrement whenever possible.
86 Preincrement has potential of beeing faster than postincrement. Just
87 thing about the obvious implementations of pre/post-increment. This
88 rule applies to decrement too.
96 - Try to minimize evaluation of the same code over and over. This is
97 aimed especially at loops.
99 Container::iterator end = large.end();
100 for (Container::iterator it = large.begin(), it != end; ++it) {
104 for (Container::iterator it = large.begin();
105 it != large.end(); ++it) {
109 - For functions and metods that returns a non-POD type T, return T
110 const instead. This gives better type checking, and will give a
111 compiler warning when temporaries are used wrongly.
121 Even if LyX currently is not using exceptions we need to be aware of
122 them. One important thing to realize is that you often do not have to
123 use throw,try or catch to be exception safe. Let's look at the
124 different types of exceptions safety: (These are taken from Herb
128 1. Basic guarantee: Even in te presence of exceptions thrown by T or
129 other exceptions, Stack objects don't leak resources.
130 Note that this also implies that the container will be
131 destructible and usable even if an exception is thrown wile
132 performing some container operation. However, if an exception
133 is thrown, the container will be in a consistent, but not
134 necessarily predictable, state. Containers that support the
135 basic guarantee can work safely in some settings.
137 2. Strong guarantee: If an operation terminates because of an
138 exception, program state will remain uncanged.
139 This always implies commit-or-rollback samantics, including
140 that no references or iterators into the container be
141 invalidated if an operation fails. For example, if a Stack
142 client calls Top and then attempts a Push that fails because
143 of an exception, then the state of the Stack object must be
144 unchanged and the reference returned from the prior call to
145 Top must still be valid. For more information on there
146 guarantees, see Dave Abrahams's documentation of the SGI
147 exception-safe standard library adaption at:
148 http://www.metabyte.com/~fbp/stl/eg_contract.html
150 Probably te most interesting point here is tat wen you
151 implement the basic guarantee, the strong guarantee often
152 comes for free. For example, in our Stack implementation,
153 alost everything we did was needed to satisfy just the basic
154 guarantee -- and wath's presented above very nearly satisfires
155 the strong guarantee, with little of no extra work. Not half
156 bad, considering all the trouble we went to.
158 In addition to tese two guarantees, there is one more
159 guarantee that certain functions must provide in order to make
160 overall exception safety possible:
162 3. Nothrow guarantee: Te function will not emit an exception under any
164 Overall exception safety isn't possible unless certain
165 functions are guaranteed not to throw. In particualr, we've
166 seen that this is true for destructors; later in tis
167 miniseries, we'll see that it's also needed in certain helper
168 functions, such as Swap().
171 For all cases where we might be able to write exception safe functions
172 without using try,throw or catch we should do so. In particular we
173 should look over all destructors to ensure that they are as exception
176 Later when more compiler support exceptions sufficiently well we will
177 begin using them too. One reason for this is that the C++ standard
178 library actually requires exceptions, e.g. "new" will throw
179 bad_allocation if the requested memory is not available.
185 * Only one delaration on each line.
190 This is especially important when initialization is done at the same
195 string a("Lars"), b("Gullik"); // wrong
197 * Pointers and references
201 char *p = "flop"; // wrong
202 char &c = *p; // wrong
204 Some time ago we had a huge discusion on this subject and after
205 convincing argumentation from Asger this is what we decided. Also note
209 const char * p; // wrong
211 * Operator names and parentheses
214 operator == (type) // wrong
216 The == is part of the function name, separating it makes the
217 declaration look like an expression.
219 * Function names and parentheses
222 void mangle () // wrong
231 enum { one = 1, two = 2, three 3 }; // wrong
233 * Naming rules for classes
235 - Use descriptive but simple and short names. For stuff specific to LyX
236 use LyX as prefix. Some modules, like mathed or spellchecker, could have
238 [I am not so sure about the LyX prefix]
240 - Class names are usually capitalized, and function names lowercased.
241 Enums are named like Classes, enum values in CAPS.
243 - Long variables are named like thisLongVariableName.
245 New types are capitalized, so this goes for typedefs,classes,structs
250 - Please adapt the formatting of your code to the setting in LyX in that
251 particular file. Lars and Asger are slowly, but surely moving the source
252 towards Linux kernel style formatting, aka K&R style. We suggest that you
253 also do this, but this is NOT something that has been decided generally.
256 * Use existing structures
258 - Use string whereever possible. LyX will someday move to Unicode, and
259 that will be easy if everybody uses string now.
261 - Check out the filename and path tools in filetools.h
263 - Check out the string tools in lstring.h, and the SubString class
266 - Use the DebugStream class to report errors and messages using
267 the lyxerr instantation.
269 [add description of other existing structures]
274 - Use this order for the access sections of your class: public,
275 protected, private. The public section is interesting for every
276 user of the class. The private section is only of interest for the
277 implementors of the class (you). [Obvously not true since this is
278 for developers, and we do not want one developer only to be able to
279 read and understand the implementation of class internals. Lgb]
281 - Avoid to declare global objects in the declaration file of the class.
282 If the same variable is used for all object, use a static member.
284 - Avoid global or static variables. An exception to this rule is
285 very private stuff like the math stack.
287 - Use the const keyword like this: char const * instead of const char *
288 because this is more logical.
293 - The documentation is generated from the header files.
294 - You document for the other developers, not for yourself.
295 - You should document what the funtion do, not the implementation.
296 - in the .C files you document the implementation.
297 - Single line description (///), multiple lines description (/** ... */)
298 - You make the documentation by doing "make srcdoc" in the root,
299 and then you'll find HTML in the srcdoc/ directory. Read with
300 Netscape for best results.
303 * NAMING RULES FOR USER-COMMANDS
305 Here's the set of rules to apply when a new command name is introduced:
307 1) Use the object.event order. That is, use `word-forward' instead of
309 2) Don't introduce an alias for an already named object. Same for events.
310 3) Forward movement or focus is called `forward' (not `right').
311 4) Backward movement or focus is called `backward' (not `left').
312 5) Upward movement of focus is called `up'.
313 6) Downward movement is called `down'.
314 7) The begin of an object is called `begin' (not `start').
315 8) The end of an object is called `end'.
318 * Using external GUI constructors (XForms fdesign)
320 - Fdesign generated files should not be changed at all. The only changes
321 needed are gettext, compability with 0.81 or when you have made your own
322 xforms objects and have just a dummy in the .fd file in place of your
323 own. In case you have to change the generated files for any of the
324 reasons above, you should provide a patch against the clean generated
325 file. Your callbacks must be in a separate file.
327 *************************************************************
329 How to create class interfaces.
330 (a.k.a How Non-Member Functions Improve Encapsulation)
331 ======================================================
333 I recently read an article by Scott Meyers in C/C++ Users
334 Journal (Vol.18,No.2), where he makes a strong case on how non-member
335 functions makes classes more encapsulated, not less. Just to skipping
336 to the core of this provides us with the following algorithm for
337 deciding what kind of function to add to a class interface:
339 - We need to add a function f to the class C's API.
341 if (f needs to be virtual)
342 make f a member function of C;
343 else if (f is operator>> or operator<<) {
344 make f a non-member funtion;
345 if (f needs access to non-public members of C)
346 make f a friend of C;
347 } else if (f needs type conversions on its left-most argument) {
348 make f a non-member function;
349 if (f needs access to non-public members of C)
350 make f a friend of C;
351 } else if (f can be implemented via C's public interface)
352 make f a non-member function;
354 make f a member function of C;
356 Unfortunately, to make the best use of this kind of Class API's we
357 need namespaces. As soon as Jean-Marc stop using gcc 2.8 and other
358 compilers seem more or less up to date on namespaces we will begin to
359 use them. _BUT_ we should begin to use the above algoritm ASAP. We
360 should also go through old code and apply this algorithm to the
361 existing member functions. That will help maintainability in the
364 (I'll fill in more from Scott Meyers article when time allows.)
369 [ExC++] Sutter, Herb. Exceptional C++: 47 engineering puzzles,
370 programming problems, and solutions. ISBN 0-201-61562-2