Merge pull request #260 from pcc/topmost
[mono.git] / mcs / CodingStyle
1 * Coding Style for the Mono C# source code.
2
3 * Class Libraries and Assembly Layout
4
5         The class libraries are grouped together in the assemblies
6         they belong.
7         
8         Each directory here represents an assembly, and inside each
9         directory we divide the code based on the namespace they
10         implement.
11         
12         In addition, each assembly directory contains a Test directory
13         that holds the NUnit tests for that assembly.
14         
15         We use a new build system which is described by various README
16         files in mcs/build
17         
18         The build process typically builds an assembly, but in some
19         cases it also builds special versions of the assemblies
20         intended to be used for testing.
21
22 * Missing implementation bits
23
24         If you implement a class and you are missing implementation bits,
25         please use the attribute [MonoTODO].  This attribute can be used
26         to programatically generate our status web pages:
27
28         [MonoTODO("My Function is not available on Mono")]
29         int MyFunction ()
30         {
31                 throw new NotImplementedException ();
32         }
33
34         Ideally, write a human description of the reason why there is
35         a MonoTODO, this will be useful in the future for our
36         automated tools that can assist in developers porting their code.
37
38 * Tagging buggy code
39
40         If there is a bug in your implementation tag the problem by using
41         the word "FIXME" in the code, together with a description of the 
42         problem.
43
44         Do not use XXX or obscure descriptions, because otherwise people
45         will not be able to understand what you mean.
46
47 * Tagging Problematic specs.
48
49         If the documentation and the Microsoft implementation do
50         differ (you wrote a test case to prove this), I suggest that you edit
51         the file `mcs/class/doc/API-notes' so we can keep track of these problems
52         and submit our comments to ECMA or Microsoft and seek clarification.
53
54         Sometimes the documentation might be buggy, and sometimes the implementation
55         might be buggy.  Lets try to identify and pinpoint which one
56         is the correct one.
57
58         Sometimes the specification will be lame (consider Version.ToString (fieldCount)
59         where there is no way of knowing how many fields are available, making the API
60         not only stupid, but leading to unreliable code).
61
62         In those cases, use the keyword "LAMESPEC".
63         
64
65 * Coding considerations and style.
66
67         In order to keep the code consistent, please use the following
68         conventions.  From here on `good' and `bad' are used to attribute
69         things that would make the coding style match, or not match.  It is not
70         a judgement call on your coding abilities, but more of a style and 
71         look call.  Please try to follow these guidelines to ensure prettiness.
72
73         Use 8 space tabs for writing your code (hopefully we can keep
74         this consistent).  If you are modifying someone else's code, try
75         to keep the coding style similar.
76
77         Since we are using 8-space tabs, you might want to consider the Linus
78         Torvals trick to reduce code nesting.  Many times in a loop, you will
79         find yourself doing a test, and if the test is true, you will nest.
80         Many times this can be changed.  Example:
81
82
83                 for (i = 0; i < 10; i++) {
84                         if (something (i)) {
85                                 do_more ();
86                         }
87                 }
88
89         This take precious space, instead write it like this:
90
91                 for (i = 0; i < 10; i++) {
92                         if (!something (i))
93                                 continue;
94                         do_more ();
95                 }
96
97 * Performance and readability
98
99         It is more important to be correct than to be fast.
100
101         It is more important to be maintainable than to be fast.
102
103         Fast code that is difficult to maintain is likely going to
104         be looked down upon.
105
106 * Style Guidelines
107
108                 * Use a space before an opening parenthesis when calling
109                   functions, or indexing, like this:
110
111                         method (a);
112                         b [10];
113
114                 * Do not put a space after the opening parenthesis and the 
115                   closing one, ie:
116
117                         good: method (a);       array [10];
118
119                         bad:  method ( a );     array[ 10 ];
120
121                 * Inside a code block, put the opening brace on the same line
122                   as the statement:
123
124                         good:
125                                 if (a) {
126                                         code ();
127                                         code ();
128                                 }
129
130                         bad:
131                                 if (a) 
132                                 {
133                                         code ();
134                                         code ();
135                                 }
136
137                 * Avoid using unecessary open/close braces, vertical space
138                   is usually limited:
139
140                         good:
141                                 if (a)
142                                         code ();
143
144                         bad:
145                                 if (a) {
146                                         code ();
147                                 }
148
149                 * When defining a method, use the C style for brace placement, 
150                   that means, use a new line for the brace, like this:
151
152                         good:
153                                 void Method ()
154                                 {
155                                 }
156
157                         bad:
158                                 void Method () {
159                                 }
160
161                 * Properties and indexers are an exception, keep the
162                   brace on the same line as the property declaration.
163                   Rationale: this makes it visually
164                   simple to distinguish them.
165
166                         good:
167                                 int Property {
168                                         get {
169                                                 return value;
170                                         }
171                                 }
172
173                         bad:
174                                 int Property 
175                                 {
176                                         get {
177                                                 return value;
178                                         }
179                                 }
180
181                   Notice how the accessor "get" also keeps its brace on the same
182                   line.
183
184                   For very small properties, you can compress things:
185
186                         ok:
187                                 int Property {
188                                         get { return value; }
189                                         set { x = value; }
190                                 }
191
192                 * Use white space in expressions liberally, except in the presence
193                   of parenthesis:
194
195                         good:
196
197                                 if (a + 5 > method (blah () + 4))
198
199                         bad:
200                                 if (a+5>method(blah()+4))
201
202                 * For any new files, please use a descriptive introduction, like
203                   this:
204
205                         //
206                         // System.Comment.cs: Handles comments in System files.
207                         //
208                         // Author:
209                         //   Juan Perez (juan@address.com)
210                         //
211                         // (C) 2002 Address, Inc (http://www.address.com)
212                         //
213
214                 * If you are modyfing someone else's code, and your contribution
215                   is significant, please add yourself to the Authors list.
216
217                 * Switch statements have the case at the same indentation as the
218                   switch:
219
220                         switch (x) {
221                         case 'a':
222                                 ...
223                         case 'b':
224                                 ...
225                         }
226
227                 * Argument names should use the camel casing for
228                   identifiers, like this:
229
230                         good:
231                                 void Method (string myArgument)
232
233                         bad:
234                                 void Method (string lpstrArgument)
235                                 void Method (string my_string)
236
237                 * Empty methods: They should have the body of code using two    
238                   lines, in consistency with the rest:
239
240                         good:
241                                 void EmptyMethod ()
242                                 {
243                                 }
244
245                         bad:
246                                 void EmptyMethod () {}
247
248                                 void EmptyMethod () 
249                                 {}
250                 
251                 * Line length: The line length for C# source code is 134 columns.
252
253
254                   If your function declaration arguments go beyond
255                   this point, please align your arguments to match the
256                   opening brace, like this:
257
258                         void Function (int arg, string argb,
259                                        int argc)
260                         {
261                         }
262          
263                   When invoking functions, the rule is different, the
264                   arguments are not aligned with the previous
265                   argument, instead they begin at the tabbed position,
266                   like this:
267           
268                         void M ()
269                         {
270                                 MethodCall ("Very long string that will force",
271                                         "Next argument on the 8-tab pos",
272                                         "Just like this one")
273                 
274                         }
275
276                 * Variable declaration indentation.
277
278                   Sometimes it is convenient to indent the variables to make the code
279                   look pretier, but do not add gratuitous space, try to use the minimally
280                   necessary space, for example:
281
282                   Good:
283
284                         void Method ()
285                         {
286                                 string b;
287                                 int    a;
288                                 byte   c;
289                         }
290
291                   Bad:
292
293                         void Method ()
294                         {
295                                 string          b;
296                                 int             a;
297                                 byte            c;
298                         }
299
300                 * Braces and the `else' clause
301
302                   If there are braces closing or opening next to the else clause,
303                   they go on the same line as the word `else', for example:
304
305                   Good:
306
307                         if (..) {
308
309                         } else {
310                 
311                         }
312         
313                   Bad:
314
315                         if (..) {
316
317                         } 
318                         else {
319                 
320                         }
321
322                   Bad:
323
324                         if (..) {
325
326                         } else 
327                         {               
328                         }
329
330                   Bad:
331
332                         if (..) {
333
334                         } 
335                         else 
336                         {
337                 
338                         }
339
340 * RCS and CVS tags
341
342         Some users like to use the special RCS/CVS tags in their
343         source code: $id$, $log$ and so on.  
344
345         The use of these is not permitted on the Mono source code
346         repository.   This metadata belongs on a ChangeLog or in the
347         SVN metadata. 
348
349 * File formats
350
351         Historically our repository has used a mix of line-endings,
352         this is a mistake that we are trying hard to fix.
353
354         For existing files, please make sure that you do not convert 
355         the file, as that causes us to loose precious history (the
356         full file is commited).
357
358         For new files that you create, please make sure that you use
359         Subversion's support for mapping the line endings
360         automatically, after adding your file:
361
362                 $ svn add file.cs
363
364         Execute this command:
365
366                 $ svn propset svn:eol-style native file.cs
367
368         Which will make the file automatically receive the proper
369         treatment from that point on.
370
371         Please verify before commiting that your changes wont loose
372         history, you can do this by running:
373
374                 $ svn diff
375
376         And examining the output.
377
378 * ChangeLogs
379
380         ChangeLogs are the files that we use to track the project
381         history.  ChangeLogs are found one per directory, or in small
382         projects, one per project.
383
384         The format looks like this:
385
386         2004-11-19  Raja R Harinath  <rharinath@novell.com>
387
388                 * Makefile (%-profiles): Go through an intermediate
389                 set of rules.  Move body to ...
390                 (profiles-do--%): ... this.
391                 (profiles-do--run-test): Customized rule that usefully
392                 runs with 'make -j' and 'make -k'.
393                 (profiles-do--all, profile-do--%--all): Orchestrate
394                 the bootstrap process.
395
396                 * file.cs (MainForm): Updated version.
397
398         The date, author, email address in the first line.
399
400         From that point on a list of changes in a file-by-file basis,
401         describing what changes were done.
402
403         This information must be cut and pasted into your commit
404         message, so the information ends up in two places: in the
405         subversion repository metadata and also on the source code
406         distirbution (which does not have the Subversion metadata).
407                 
408 * Warnings
409
410         Avoid commiting code with warnings to the repository, the use
411         of #pragmas to disable warnings is strongly discouraged, but
412         can be used on unique cases.  Please justify the use of the
413         warning ignore clause on a comment.
414
415         Do not commit changes to the Makefiles that removes warnings,
416         if anything warnings should be eliminated one at a time, and
417         if not possible, they must be flagged.
418
419
420 * Examples:
421
422 class X : Y {
423
424         bool Method (int argument_1, int argument_2)
425         {
426                 if (argument_1 == argument_2)
427                         throw new Exception (Locale.GetText ("They are equal!");
428
429                 if (argument_1 < argument_2) {
430                         if (argument_1 * 3 > 4)
431                                 return true;
432                         else
433                                 return false;
434                 }
435
436                 //
437                 // This sample helps keep your sanity while using 8-spaces for tabs
438                 // 
439                 VeryLongIdentifierWhichTakesManyArguments (
440                         Argument1, Argument2, Argument3,
441                         NestedCallHere (
442                                 MoreNested));
443         }
444
445         bool MyProperty {
446                 get {
447                         return x;
448                 }
449
450                 set {
451                         x = value;
452                 }
453         }
454
455         void AnotherMethod () 
456         {
457                 if ((a + 5) != 4) {
458                 }
459
460                 while (blah) {
461                         if (a)
462                                 continue;
463                         b++;
464                 }
465         }
466 }
467
468 * Conditional compilation
469
470         Ideally we would not need conditional compilation, and the use
471         of #ifdef is strongly discouraged.  But due to our support for
472         old C# 1.0 compilers we have to use it in a few places.
473
474         Try to avoid negative tests that have an else clause, for
475         example:
476
477             #if !NET_2_0
478                 CODE_FOR_1_0
479             #else
480                 CODE_FOR_2_0
481             #endif
482
483         Instead use:
484
485             #if NET_2_0
486                 CODE_FOR_2_0
487             #else
488                 CODE_FOR_1_0
489             #endif
490
491         When a major feature differs across compilation targets, try
492         to factor out the code into a separate class, a helper class
493         or a separate file, and include that in your profile while
494         surrounding that helper file/class with the ifdefs to reduce
495         the amount of ifdefs in the code.
496
497         For instance, this is used for some parts of Grasshopper where
498         the code is ifdefed out, when large parts of a file would have
499         been ifdefed out, we moved the code into a MyOtherFile.jvm.cs
500
501         For 2.0 classes, this is even simpler as code can be trivially
502         factored out into 
503
504                  MyHelperClass.cli.cs
505                  MyHelperClass.jvm.cs
506
507         By using partial classes.