[configure] Add new target.
[mono-project.git] / mcs / CodingStyle
blob6a3528e7c6ada140a8d8eca1b2273ba16970a394
1 * Coding Style for the Mono C# source code.
3 * Class Libraries and Assembly Layout
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.
22 * Missing implementation bits
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:
28         [MonoTODO("My Function is not available on Mono")]
29         int MyFunction ()
30         {
31                 throw new NotImplementedException ();
32         }
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.
38 * Tagging buggy code
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.
44         Do not use XXX or obscure descriptions, because otherwise people
45         will not be able to understand what you mean.
47 * Tagging Problematic specs.
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.
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.
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).
62         In those cases, use the keyword "LAMESPEC".
63         
65 * Coding considerations and style.
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.
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.
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:
83                 for (i = 0; i < 10; i++) {
84                         if (something (i)) {
85                                 do_more ();
86                         }
87                 }
89         This take precious space, instead write it like this:
91                 for (i = 0; i < 10; i++) {
92                         if (!something (i))
93                                 continue;
94                         do_more ();
95                 }
97 * Performance and readability
99         It is more important to be correct than to be fast.
101         It is more important to be maintainable than to be fast.
103         Fast code that is difficult to maintain is likely going to
104         be looked down upon.
106 * Style Guidelines
108                 * Use a space before an opening parenthesis when calling
109                   functions, or indexing, like this:
111                         method (a);
112                         b [10];
114                 * Do not put a space after the opening parenthesis and the 
115                   closing one, ie:
117                         good: method (a);       array [10];
119                         bad:  method ( a );     array[ 10 ];
121                 * Inside a code block, put the opening brace on the same line
122                   as the statement:
124                         good:
125                                 if (a) {
126                                         code ();
127                                         code ();
128                                 }
130                         bad:
131                                 if (a) 
132                                 {
133                                         code ();
134                                         code ();
135                                 }
137                 * Avoid using unecessary open/close braces, vertical space
138                   is usually limited:
140                         good:
141                                 if (a)
142                                         code ();
144                         bad:
145                                 if (a) {
146                                         code ();
147                                 }
149                 * When defining a method, use the C style for brace placement, 
150                   that means, use a new line for the brace, like this:
152                         good:
153                                 void Method ()
154                                 {
155                                 }
157                         bad:
158                                 void Method () {
159                                 }
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.
166                         good:
167                                 int Property {
168                                         get {
169                                                 return value;
170                                         }
171                                 }
173                         bad:
174                                 int Property 
175                                 {
176                                         get {
177                                                 return value;
178                                         }
179                                 }
181                   Notice how the accessor "get" also keeps its brace on the same
182                   line.
184                   For very small properties, you can compress things:
186                         ok:
187                                 int Property {
188                                         get { return value; }
189                                         set { x = value; }
190                                 }
192                 * Use white space in expressions liberally, except in the presence
193                   of parenthesis:
195                         good:
197                                 if (a + 5 > method (blah () + 4))
199                         bad:
200                                 if (a+5>method(blah()+4))
202                 * For any new files, please use a descriptive introduction, like
203                   this:
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                         //
214                 * If you are modyfing someone else's code, and your contribution
215                   is significant, please add yourself to the Authors list.
217                 * Switch statements have the case at the same indentation as the
218                   switch:
220                         switch (x) {
221                         case 'a':
222                                 ...
223                         case 'b':
224                                 ...
225                         }
227                 * Argument names should use the camel casing for
228                   identifiers, like this:
230                         good:
231                                 void Method (string myArgument)
233                         bad:
234                                 void Method (string lpstrArgument)
235                                 void Method (string my_string)
237                 * Empty methods: They should have the body of code using two    
238                   lines, in consistency with the rest:
240                         good:
241                                 void EmptyMethod ()
242                                 {
243                                 }
245                         bad:
246                                 void EmptyMethod () {}
248                                 void EmptyMethod () 
249                                 {}
250                 
251                 * Line length: The line length for C# source code is 134 columns.
254                   If your function declaration arguments go beyond
255                   this point, please align your arguments to match the
256                   opening brace, like this:
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                         }
276                 * Variable declaration indentation.
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:
282                   Good:
284                         void Method ()
285                         {
286                                 string b;
287                                 int    a;
288                                 byte   c;
289                         }
291                   Bad:
293                         void Method ()
294                         {
295                                 string          b;
296                                 int             a;
297                                 byte            c;
298                         }
300                 * Braces and the `else' clause
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:
305                   Good:
307                         if (..) {
309                         } else {
310                 
311                         }
312         
313                   Bad:
315                         if (..) {
317                         } 
318                         else {
319                 
320                         }
322                   Bad:
324                         if (..) {
326                         } else 
327                         {               
328                         }
330                   Bad:
332                         if (..) {
334                         } 
335                         else 
336                         {
337                 
338                         }
340 * RCS and CVS tags
342         Some users like to use the special RCS/CVS tags in their
343         source code: $id$, $log$ and so on.  
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. 
349 * File formats
351         Historically our repository has used a mix of line-endings,
352         this is a mistake that we are trying hard to fix.
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).
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:
362                 $ svn add file.cs
364         Execute this command:
366                 $ svn propset svn:eol-style native file.cs
368         Which will make the file automatically receive the proper
369         treatment from that point on.
371         Please verify before commiting that your changes wont loose
372         history, you can do this by running:
374                 $ svn diff
376         And examining the output.
378 * ChangeLogs
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.
384         The format looks like this:
386         2004-11-19  Raja R Harinath  <rharinath@novell.com>
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.
396                 * file.cs (MainForm): Updated version.
398         The date, author, email address in the first line.
400         From that point on a list of changes in a file-by-file basis,
401         describing what changes were done.
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
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.
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.
420 * Examples:
422 class X : Y {
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!");
429                 if (argument_1 < argument_2) {
430                         if (argument_1 * 3 > 4)
431                                 return true;
432                         else
433                                 return false;
434                 }
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         }
445         bool MyProperty {
446                 get {
447                         return x;
448                 }
450                 set {
451                         x = value;
452                 }
453         }
455         void AnotherMethod () 
456         {
457                 if ((a + 5) != 4) {
458                 }
460                 while (blah) {
461                         if (a)
462                                 continue;
463                         b++;
464                 }
465         }
468 * Conditional compilation
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.
474         Try to avoid negative tests that have an else clause, for
475         example:
477             #if !NET_2_0
478                 CODE_FOR_1_0
479             #else
480                 CODE_FOR_2_0
481             #endif
483         Instead use:
485             #if NET_2_0
486                 CODE_FOR_2_0
487             #else
488                 CODE_FOR_1_0
489             #endif
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.
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
501         For 2.0 classes, this is even simpler as code can be trivially
502         factored out into 
504                  MyHelperClass.cli.cs
505                  MyHelperClass.jvm.cs
507         By using partial classes.