]> git.lyx.org Git - lyx.git/blob - development/Code_rules/Rules
52d29fbccae5ea2f9e748c96d6f62c3e7df45a51
[lyx.git] / development / Code_rules / Rules
1 Rules for the code in LyX
2 -------------------------
3 [updated from the C++STYLE distrubuted 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 uncomplete.
7
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.
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 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 
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 - 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
41   Constructs.
42
43
44 Submiting Code
45 ------------------
46
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.
50
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.
54
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.
59
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
62 this syntax:
63
64 1999-12-13  Lars Gullik Bjønnes  <larsbj@lyx.org>
65
66         * src/support/lyxstring.C (find): assert bug fixed.
67
68
69 Code Constructs
70 ---------------
71
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
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 - Make the scope of a variable as small as possible.
83
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.
88
89         ++T;
90         --U;
91         -NOT-
92         T++; // wrong
93         U--; // wrong
94
95 - Try to minimize evaluation of the same code over and over. This is
96   aimed especially at loops.
97
98         Container::iterator end = large.end();
99         for (Container::iterator it = large.begin(), it != end; ++it) {
100                 ...;
101         }
102         -NOT-
103         for (Container::iterator it = large.begin();
104              it != large.end(); ++it) {
105                 ...;
106         }
107
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.
111
112         T const add(...);
113         -NOT-
114         T add(...);
115
116
117 Formatting
118 ----------
119
120 * Only one delaration on each line.
121         int a;
122         int b;
123         -NOT-
124         int a, b; // wrong
125   This is especially important when initialization is done at the same
126   time:
127         string a("Lars");
128         string b("Gullik");
129         -NOT-
130         string a("Lars"), b("Gullik"); // wrong
131
132 * Pointers and references
133         char * p = "flop";
134         char & c = *p;
135         -NOT-
136         char *p = "flop"; // wrong
137         char &c = *p;     // wrong
138
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
141   that we will have:
142         char const * p;
143         -NOT-
144         const char * p; // wrong
145
146 * Operator names and parentheses
147         operator==(type)
148         -NOT-
149         operator == (type)  // wrong
150
151   The == is part of the function name, separating it makes the
152   declaration look like an expression.
153
154 * Function names and parentheses
155         void mangle()
156         -NOT-
157         void mangle ()  // wrong
158
159 * Enumerators
160         enum {
161                 one = 1,
162                 two = 2,
163                 three = 3
164         };
165         -NOT-
166         enum { one = 1, two = 2, three 3 }; // wrong
167
168 * Naming rules for classes
169
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
172     other prefixes.
173     [I am not so sure about the LyX prefix]
174
175   - Class names are usually capitalized, and function names lowercased.
176     Enums are named like Classes, enum values in CAPS.
177
178   - Long variables are named like thisLongVariableName.
179
180   New types are capitalized, so this goes for typedefs,classes,structs
181   and enums.
182
183 * Formatting
184
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.
189
190
191 * Use existing structures
192
193   - Use string whereever possible. LyX will someday move to Unicode, and
194     that will be easy if everybody uses string now.
195
196   - Check out the filename and path tools in filetools.h
197
198   - Check out the string tools in lstring.h, and the SubString class
199     and the regex class.
200
201   - Use the DebugStream class to report errors and messages using
202     the lyxerr instantation.
203
204   [add description of other existing structures]
205
206
207 * Declarations
208   
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]
215   
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.
218
219   - Avoid global or static variables. An exception to this rule is 
220     very private stuff like the math stack.
221
222   - Use the const keyword like this: char const * instead of const char *
223     because this is more logical.
224
225
226 * Documentation
227
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.
236
237
238 * NAMING RULES FOR USER-COMMANDS
239    
240   Here's the set of rules to apply when a new command name is introduced:
241  
242   1) Use the object.event order. That is, use `word-forward' instead of 
243      `forward-word'.
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'.
251
252
253 * Using external GUI constructors (XForms fdesign)
254
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.
261
262  *************************************************************
263
264  How to create class interfaces.
265  (a.k.a How Non-Member Functions Improve Encapsulation)
266  ======================================================
267
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:
273
274         - We need to add a function f to the class C's API.
275
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;
288         else
289                 make f a member function of C;
290  
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
297 future.
298
299 (I'll fill in more from Scott Meyers article when time allows.)