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