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 - document all variables, methods, functions, classes etc. We are
38 using the source documentation program doc++, a program that handles
39 javadoc syntax, to document sources. See Source Documentation.
40 - we have certain code constructs that we try to follow. See Code
47 It is implicitly understood that all patches contributed to The LyX
48 Project is under the Gnu General Public Lisence, it you have a problem
49 with that, don't contribute code.
51 Also please don't just pup up out of the blue with a huge patch (or
52 small) that changes something substantial in LyX. Always discuss your
53 ideas with the developers on the developers mailinglist.
55 When you create the patch, please use "diff -up" since we find that a
56 lot easier to read than the other diff formats. Also please do not
57 send patches that implements/fix several different things, several
58 patches is a much better option.
60 We also expect you to provide a ChangeLog entry with every patch, this
61 describes shortly what the patch is doing. The ChangeLog entry follows
64 1999-12-13 Lars Gullik Bjønnes <larsbj@lyx.org>
66 * src/support/lyxstring.C (find): assert bug fixed.
72 We have several guidelines on code constructs, some of these exists to
73 make the code faster, others to make the code clearer. Yet others
74 exists to make us able to take advantage of the strong type checking
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.
82 - Make the scope of a variable as small as possible.
84 - Prefere preincrement to postincrement whenever possible.
85 Preincrement has potential of beeing faster than postincrement. Just
86 thing about the obvious implementations of pre/post-increment. This
87 rule applies to decrement too.
95 - Try to minimize evaluation of the same code over and over. This is
96 aimed especially at loops.
98 Container::iterator end = large.end();
99 for (Container::iterator it = large.begin(), it != end; ++it) {
103 for (Container::iterator it = large.begin();
104 it != large.end(); ++it) {
108 - For functions and metods that returns a non-POD type T, return T
109 const instead. This gives better type checking, and will give a
110 compiler warning when temporaries are used wrongly.
120 * Only one delaration on each line.
125 This is especially important when initialization is done at the same
130 string a("Lars"), b("Gullik"); // wrong
132 * Pointers and references
136 char *p = "flop"; // wrong
137 char &c = *p; // wrong
139 Some time ago we had a huge discusion on this subject and after
140 convincing argumentation from Asger this is what we decided. Also note
144 const char * p; // wrong
146 * Operator names and parentheses
149 operator == (type) // wrong
151 The == is part of the function name, separating it makes the
152 declaration look like an expression.
154 * Function names and parentheses
157 void mangle () // wrong
166 enum { one = 1, two = 2, three 3 }; // wrong
168 * Naming rules for classes
170 - Use descriptive but simple and short names. For stuff specific to LyX
171 use LyX as prefix. Some modules, like mathed or spellchecker, could have
173 [I am not so sure about the LyX prefix]
175 - Class names are usually capitalized, and function names lowercased.
176 Enums are named like Classes, enum values in CAPS.
178 - Long variables are named like thisLongVariableName.
180 New types are capitalized, so this goes for typedefs,classes,structs
185 - Please adapt the formatting of your code to the setting in LyX in that
186 particular file. Lars and Asger are slowly, but surely moving the source
187 towards Linux kernel style formatting, aka K&R style. We suggest that you
188 also do this, but this is NOT something that has been decided generally.
191 * Use existing structures
193 - Use string whereever possible. LyX will someday move to Unicode, and
194 that will be easy if everybody uses string now.
196 - Check out the filename and path tools in filetools.h
198 - Check out the string tools in lstring.h, and the SubString class
201 - Use the DebugStream class to report errors and messages using
202 the lyxerr instantation.
204 [add description of other existing structures]
209 - Use this order for the access sections of your class: public,
210 protected, private. The public section is interesting for every
211 user of the class. The private section is only of interest for the
212 implementors of the class (you). [Obvously not true since this is
213 for developers, and we do not want one developer only to be able to
214 read and understand the implementation of class internals. Lgb]
216 - Avoid to declare global objects in the declaration file of the class.
217 If the same variable is used for all object, use a static member.
219 - Avoid global or static variables. An exception to this rule is
220 very private stuff like the math stack.
222 - Use the const keyword like this: char const * instead of const char *
223 because this is more logical.
228 - The documentation is generated from the header files.
229 - You document for the other developers, not for yourself.
230 - You should document what the funtion do, not the implementation.
231 - in the .C files you document the implementation.
232 - Single line description (///), multiple lines description (/** ... */)
233 - You make the documentation by doing "make srcdoc" in the root,
234 and then you'll find HTML in the srcdoc/ directory. Read with
235 Netscape for best results.
238 * NAMING RULES FOR USER-COMMANDS
240 Here's the set of rules to apply when a new command name is introduced:
242 1) Use the object.event order. That is, use `word-forward' instead of
244 2) Don't introduce an alias for an already named object. Same for events.
245 3) Forward movement or focus is called `forward' (not `right').
246 4) Backward movement or focus is called `backward' (not `left').
247 5) Upward movement of focus is called `up'.
248 6) Downward movement is called `down'.
249 7) The begin of an object is called `begin' (not `start').
250 8) The end of an object is called `end'.
253 * Using external GUI constructors (XForms fdesign)
255 - Fdesign generated files should not be changed at all. The only changes
256 needed are gettext, compability with 0.81 or when you have made your own
257 xforms objects and have just a dummy in the .fd file in place of your
258 own. In case you have to change the generated files for any of the
259 reasons above, you should provide a patch against the clean generated
260 file. Your callbacks must be in a separate file.
262 *************************************************************
264 How to create class interfaces.
265 (a.k.a How Non-Member Functions Improve Encapsulation)
266 ======================================================
268 I recently read an article by Scott Meyers in C/C++ Users
269 Journal (Vol.18,No.2), where he makes a strong case on how non-member
270 functions makes classes more encapsulated, not less. Just to skipping
271 to the core of this provides us with the following algorithm for
272 deciding what kind of function to add to a class interface:
274 - We need to add a function f to the class C's API.
276 if (f needs to be virtual)
277 make f a member function of C;
278 else if (f is operator>> or operator<<) {
279 make f a non-member funtion;
280 if (f needs access to non-public members of C)
281 make f a friend of C;
282 } else if (f needs type conversions on its left-most argument) {
283 make f a non-member function;
284 if (f needs access to non-public members of C)
285 make f a friend of C;
286 } else if (f can be implemented via C's public interface)
287 make f a non-member function;
289 make f a member function of C;
291 Unfortunately, to make the best use of this kind of Class API's we
292 need namespaces. As soon as Jean-Marc stop using gcc 2.8 and other
293 compilers seem more or less up to date on namespaces we will begin to
294 use them. _BUT_ we should begin to use the above algoritm ASAP. We
295 should also go through old code and apply this algorithm to the
296 existing member functions. That will help maintainability in the
299 (I'll fill in more from Scott Meyers article when time allows.)