Coding Standard and Guidelines: Difference between revisions

From OpenPetra Wiki
Jump to navigation Jump to search
 
(29 intermediate revisions by 5 users not shown)
Line 10: Line 10:
# 'Uncrustify' and 'StyleCop' and how we use them with Petra are described in [[Coding Standards Tools: 'Uncrustify' and 'StyleCop']].
# 'Uncrustify' and 'StyleCop' and how we use them with Petra are described in [[Coding Standards Tools: 'Uncrustify' and 'StyleCop']].


This 'C# Coding Style Guide' was inspired by the [http://www.icsharpcode.net/TechNotes/ C# Coding Style Guide], written by Mike Krüger. This is used by the sharpDevelop programmers who work on the SharpDevelop IDE.
This 'C# Coding Style Guide' was inspired by the [http://www.icsharpcode.net/TechNotes/ C# Coding Style Guide] written by Mike Krüger. This is used by the SharpDevelop programmers who work on the SharpDevelop IDE.


=File Organization=
=File Organization=
Line 16: Line 16:
==C# Sourcefiles==
==C# Sourcefiles==


* Keep your classes/files short: try hard not to exceed 3.000 lines of code, never go beyond 4.000 lines of code.
* Keep your classes/files short: try hard not to exceed 3.000 lines of code and never go beyond 4.000 lines of code.
** Exception to that
** Exception to that:
*** Auto-generated code can ignore that rule if the generated file doesn't need to be looked at/touched by developers.
*** Auto-generated code can ignore that rule if the generated file doesn't need to be looked at/touched by developers.
* Divide your code up, make structures clearer.  
* Divide your code up and make structures clearer.  
* Every class should go in a separate file.  
* Every class should go in a separate file.  
** Exceptions to that
** Exceptions to that:
*** Helper classes for the main class in the same file are allowed. Those helper classes must be private classes, though!
*** Helper classes for the main class in the same file are allowed, but they must be private classes!
*** Auto-generated code can ignore that rule if the generated file doesn't need to be looked at/touched by developers.
*** Auto-generated code can ignore that rule if the generated file doesn't need to be looked at/touched by developers.
* The file name should reflect the name of the class in the file (.cs as extension of course).
* The file name should reflect the name of the class in the file (.cs as extension of course).
** Exception to that
** Exception to that:
*** The file name of a source file can have the last part of a Namespace in it ''if'' the Namespace is nested quite deeply ''and''  
*** The file name of a source file can have the last part of a Namespace in it ''if'' the Namespace is nested quite deeply ''and''  
the directory structure doesn't reflect that deep nesting anymore (see [[Coding_Standard_and_Guidelines#Directory_Layout|'Directory Layout']] below). Example: DataAggregates.PPartnerAddress.cs in Namespace 'Ict.Petra.Server.MPartner.'''DataAggregates'''' in directory 'U:\openpetraorg\csharp\ICT\Petra\Server\lib\MPartner'.
the directory structure doesn't reflect that deep nesting anymore (see [[Coding_Standard_and_Guidelines#Directory_Layout|'Directory Layout']] below). Example: DataAggregates.PPartnerAddress.cs in Namespace 'Ict.Petra.Server.MPartner.'''DataAggregates'''' in directory 'U:\openpetraorg\csharp\ICT\Petra\Server\lib\MPartner'.
Line 35: Line 35:


* Create a directory for every namespace. Example: for Namespace 'Ict.Petra.Server.App.Core' use 'U:\delphi.net\ICT\Petra\Server\app\' as the path (do not use the Namespace name with dots for directory names).
* Create a directory for every namespace. Example: for Namespace 'Ict.Petra.Server.App.Core' use 'U:\delphi.net\ICT\Petra\Server\app\' as the path (do not use the Namespace name with dots for directory names).
** Exceptions to that
** Exceptions to that:
*** Additional directories might be placed inbetween parts of the Namespace ''if'' that benefits the directory structure ''and'' a agreed rule when to do that is followed. Example: Namespace 'Ict.Petra.Server.MPartner.DataAggregates' resides in directory 'U:\delphi.net\ICT\Petra\Server\'''lib'''\MPartner'. Note the 'lib' directory, which is inserted.
*** Additional directories might be placed inbetween parts of the Namespace ''if'' that benefits the directory structure ''and'' an agreed rule when to do that is followed. Example: Namespace 'Ict.Petra.Server.MPartner.DataAggregates' resides in directory 'U:\delphi.net\ICT\Petra\Server\'''lib'''\MPartner'. Note the 'lib' directory, which is inserted.
*** ''If'' a Namespace is nested quite deeply, we can opt to have the directory structure ''not'' reflecting that deep nesting. In that case, the last part of a Namespace should then be part of the file name of a Class (see [[Coding_Standard_and_Guidelines#C.23_Sourcefiles |'C# Sourcefiles']] above).
*** ''If'' a Namespace is nested quite deeply, we can opt to have the directory structure ''not'' reflecting that deep nesting. In that case, the last part of a Namespace should then be part of the file name of a Class (see [[Coding_Standard_and_Guidelines#C.23_Sourcefiles |'C# Sourcefiles']] above).
See also [['Explanation of Directory Structure and Rules']] for more detailed information!




Line 50: Line 53:
Specifically, '''we indent everything with four spaces''' - <font color="blue">Enforced by Uncrustify</font>. This applies for the indendation from column 1 to the indendation level of the current code and also to any further indendations from there.
Specifically, '''we indent everything with four spaces''' - <font color="blue">Enforced by Uncrustify</font>. This applies for the indendation from column 1 to the indendation level of the current code and also to any further indendations from there.


By using spaces, not tabs, we can ensure that our code is indented identically for every developer and in every editor. Would we use tabs, the indentation could vary.
By using spaces, not tabs, we can ensure that our code is indented identically for every developer and in every editor. If we used tabs, the indentation could vary.


'''Don't use tabs for indentation - use spaces!''' <font color="blue">Enforced by Uncrustify.</font>
'''Don't use tabs for indentation - use spaces!''' <font color="blue">Enforced by Uncrustify.</font>
Line 56: Line 59:
==Wrapping Lines==
==Wrapping Lines==


When an expression will not fit on a single line, break it up before it reaches more than 150 characters. <font color="blue">Enforced by Uncrustify.</font> You might want to break it up before that for readability.
When an expression will not fit on a single line, break it up before it reaches more than '''150''' characters. <font color="blue">Enforced by Uncrustify.</font> You might want to break it up before that for readability.


Follow these general principles when breaking up a line:  
Follow these general principles when breaking up a line:  
Line 66: Line 69:


Example of breaking up method calls:
Example of breaking up method calls:
<pre>
LongMethodCall(expr1, expr2,
LongMethodCall(expr1, expr2,
 
      expr3, expr4, expr5);  // indented at the standard indentation level
    expr3, expr4, expr5);  // indented at the standard indentation level
</pre>


or
or


<pre>
LongMethodCall(expr1, expr2,
LongMethodCall(expr1, expr2,
 
                expr3, expr4, expr5);  // aligned with the beginning of the expression on the previous line
                expr3, expr4, expr5);  // aligned with the beginning of the expression on the previous line
</pre>


The first is preferred because it results in uniformly formatted code, but if indenting with the second method makes for better reading in a specific case then use the second method.
The first is preferred because it results in uniformly formatted code, but if indenting with the second method makes for better reading in a specific case then use the second method.
Line 87: Line 86:
PREFER:
PREFER:


<pre>
var = a * b / (c - g + f) +  
var = a * b / (c - g + f) +  
 
    4 * z;
    4 * z;
</pre>


BAD STYLE – AVOID:
BAD STYLE – AVOID:
<pre>
var = a * b / (c - g +  
var = a * b / (c - g +  
 
    f) + 4 * z;
    f) + 4 * z;
</pre>


The first is preferred, since the break occurs outside the paranthesized expression (higher level rule).
The first is preferred, since the break occurs outside the paranthesized expression (higher level rule).
Line 127: Line 122:
Block comments may be useful in rare cases, refer to the TechNote [http://www.icsharpcode.net/TechNotes/Commenting20020413.pdf 'The fine Art of Commenting'] for an example.
Block comments may be useful in rare cases, refer to the TechNote [http://www.icsharpcode.net/TechNotes/Commenting20020413.pdf 'The fine Art of Commenting'] for an example.


''A rule of thumb says that generally, the length of a comment should not exceed the length of the code explained by too much, as this is an indication of too complicated, potentially buggy, code.''
''As a general rule of thumb, the length of a comment should not overly exceed the length of the code it explains as this is an indication of too complicated (and potentially buggy) code.''


''For ''commenting out sections of code'', use the 'Single Line Comments' (despite their name) to distinguish better between ''code comments'' and ''commented out'' code.''
''For commenting out sections of code, use the 'Single Line Comments' (despite their name) to distinguish better between code that has comments attached and code that is commented out.''


==Single Line Comments==
==Single Line Comments==


You should use the <code>//</code> (two forward slahes) comment style to "comment out" code (SharpDevelop has a shotcut key for it, Alt+/). ''It may be used for commenting out sections of code too.''
Developers should use the <code>//</code> (two forward slahes) comment style to "comment out" code (SharpDevelop has a shotcut key for it, Alt+/). ''It may be used for commenting out sections of code too.''


Note on using StyleCop: because we will use StyleCop, rather use <code>////</code> (four forward slashes) instead of <code>//</code> when commenting out ''single'' lines of code. This helps the tool to not confuse it with a single line comment (which is not commented out code). (Refers to StyleCop Rule SA1512: SingleLineCommentsMustNotBeFollowedByBlankLine.)
Note on using StyleCop: because we will use StyleCop, you should rather use <code>////</code> (four forward slashes) instead of <code>//</code> when commenting out ''single'' lines of code. This helps the tool to not confuse it with a single line comment (which is not commented out code). (Refers to StyleCop Rule SA1512: SingleLineCommentsMustNotBeFollowedByBlankLine.)




Line 172: Line 167:


The first category contains tags like <code><summary></code>, <code><param></code> or <code><exception></code>.  
The first category contains tags like <code><summary></code>, <code><param></code> or <code><exception></code>.  
These represent items that represent the elements of a program's API which must be documented for the program to be useful to other programmers.  
These tags represent the elements of a program's API which must be documented for the program to be useful to other programmers.  
These tags usually have attributes such as <code>name</code> or <code>cref</code> as demonstrated in the multi line example above.
They usually have attributes such as <code>name</code> or <code>cref</code> (as demonstrated in the multi line example above) and are
These attributes are checked by the compiler, so they should be valid.
checked by the compiler, so they should be valid.


The latter category governs the layout of the documentation, using tags such as <code><nowiki><code></nowiki></code>, <code><list></code> or <code><para></code>.
The latter category governs the layout of the documentation, using tags such as <code><nowiki><code></nowiki></code>, <code><list></code> or <code><para></code>.


For a fuller explanation of XML comments see [[CSharp_In-Code_Documentation_with_MS_XML_Tags CSharp In-Code Documentation with MS XML Tags]].  
For a fuller explanation of XML comments see [['CSharp In-Code Documentation with MS XML Tags']].  
For information on how to produce API-style documentation for C# Projects whose .cs files contain XML Comment Tags see [[How_to_produce_CSharp_API_Documentation How to produce CSharp API Documentation]].
For information on how to produce API-style documentation for C# Projects whose .cs files contain XML Comment Tags, see [['How to produce CSharp API Documentation']].


For information on commenting best practice and further issues related to commenting, see the TechNote [http://www.icsharpcode.net/TechNotes/Commenting20020413.pdf 'The fine Art of Commenting'].
For information on commenting best practice and further issues related to commenting, see the TechNote [http://www.icsharpcode.net/TechNotes/Commenting20020413.pdf 'The fine Art of Commenting'].
Line 214: Line 209:
The above example also demonstrates the drawbacks of non-obvious variable names.  
The above example also demonstrates the drawbacks of non-obvious variable names.  


''Be clear when naming variables.'' Using self-explanatory variable names such as <code>IndentLevel</code> make above comments obsolete.
''Be clear when naming variables.'' Using self-explanatory variable names such as <code>IndentLevel</code> eradicates the need for making explanatory comments.


==Initialization==
==Initialization==
Line 229: Line 224:
Initialisations should be followed by an empty line so that they are visually set apart from the rest of the source code. <font color="blue">Enforced by Uncrustify if the initialisations are part of declarations.</font>
Initialisations should be followed by an empty line so that they are visually set apart from the rest of the source code. <font color="blue">Enforced by Uncrustify if the initialisations are part of declarations.</font>


Note: When initializing a Dialog/Modal Form (by using .ShowDialog instead of .Show), use the following construct to be sure the Form is released from memory when it is closed:
'''Note:''' when initializing a Dialog/Modal Form (by using .ShowDialog instead of .Show), use the following construct to be sure the Form is released from memory when it is closed:


<pre>
using (TOpenFileDialog openFileDialog = new TOpenFileDialog())  
using (TOpenFileDialog openFileDialog = new TOpenFileDialog())  
{
{
    openFileDialog.ShowDialog();
  openFileDialog.ShowDialog();
    ...
    ...
}  <font color="gray">// .NET will release openFileDialog automatically, so we can't forget about it!</font>
}  <font color="gray">// .NET will release openFileDialog automatically, so we can't forget about it!</font>
</pre>


Background: Forms shown with .ShowDialog are not released from memory, but kept in memory so the caller can call methods after the Form is closed to retrieve parameters. Therefore one can forget to release the form from memory later.
'''Background:''' forms shown with .ShowDialog are not released from memory, but kept in memory so the caller can call methods after the Form is closed to retrieve parameters. Therefore, you can forget to release the form from memory later.


==Class, Interface and Namespace Declarations==
==Class, Interface and Namespace Declarations==
Line 254: Line 247:
* Code block separation
* Code block separation
** An empty line should preceed and succeed each class, interface or namespace block.
** An empty line should preceed and succeed each class, interface or namespace block.
*** Exceptions
*** Exceptions:
**** if a class, interface or namespace block begins immediately after another class, interface or namespace block has been started with an opening brace "{": no empty line.
**** if a class, interface or namespace block begins immediately after another class, interface or namespace block has been started with an opening brace "{": then no empty line should be inserted.
**** if a class, interface or namespace block ends and another enclosing code block also ends immediately after the closing brace "}": no empty line.
**** if a class, interface or namespace block ends and another enclosing code block also ends immediately after the closing brace "}": then no empty line should be inserted.


For example:
For example:


<pre>
namespace MyNamespace
namespace MyNamespace
'''{'''                                                    <font color="gray">// no empty line</font>
'''{'''                                                    <font color="gray">// no empty line</font>
    class TMySample : TMyClass, IMyInterface
    class TMySample : TMyClass, IMyInterface
    '''{'''
    '''{'''
        void DoSomething()
        void DoSomething()
        '''{'''
        '''{'''
       
       
        '''}'''
        '''}'''
       
       
        void DoAnotherThing()
        void DoAnotherThing()
        '''{'''
        '''{'''
       
       
        '''}'''
        '''}'''
    '''}'''
    '''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
    class TMyOtherSample : TMySample, IMyOtherInterface
    class TMyOtherSample : TMySample, IMyOtherInterface
    '''{'''
    '''{'''
        void DoSomething()
        void DoSomething()
        '''{'''
        '''{'''
       
       
        '''}'''
        '''}'''
       
       
        void DoAnotherThing()
        void DoAnotherThing()
        '''{'''
        '''{'''
       
       
        '''}'''
        '''}'''
    '''}'''                                                  <font color="gray">// no empty line</font>
    '''}'''                                                  <font color="gray">// no empty line</font>
'''}'''
'''}'''
</pre>


For another brace placement example look at section 'Code Examples - Brace placement example'.
For another brace placement example look at section 'Code Examples - Brace placement example'.
Line 308: Line 299:
For example:
For example:


<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
public MySample'''('''int AMyInt''')'''
public MySample'''('''int AMyInt''')'''
'''{'''
'''{'''
    this.FMyInt = AMyInt;
    this.FMyInt = AMyInt;
'''}'''
'''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
void Inc'''()'''
void Inc'''()'''
'''{'''
'''{'''
    ++FMyInt;
    ++FMyInt;
'''}'''
'''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


<font color="blue">Enforced by Uncrustify: all rules</font>
<font color="blue">Enforced by Uncrustify: all rules</font>
Line 329: Line 318:


* Braces
* Braces
** Class braces placement rules should be applied. <font color="blue">Enforced by Uncrustify: all rules, except for 'opening curly bracket must be on new line' (Uncrustify can't enforce that for EventHandlers).</font>
** Class braces placement rules should be applied. <font color="blue">Enforced by Uncrustify: all rules, except for 'opening curly bracket must be on a new line' (Uncrustify can't enforce that for EventHandlers).</font>
* Spacing
* Spacing
** For properties where both 'get' and 'set' blocks are present, an empty line should be placed between the 'get' block and the 'set' block.
** For properties where both 'get' and 'set' blocks are present, an empty line should be placed between the 'get' block and the 'set' block.
Line 340: Line 329:


For example:
For example:
<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
public int Amount  
public int Amount  
'''{'''
'''{'''
    get  
    get  
    '''{'''
    '''{'''
        ...
        ...
    '''}'''
    '''}'''
                                                        <font color="gray">// empty line goes here</font>     
                                                      <font color="gray">// empty line goes here</font>     
    set  
    set  
    '''{'''
    '''{'''
        ...  
        ...
 
    '''}'''
    '''}'''
'''}'''
'''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
public EventHandler MyCustomEventHandler
public EventHandler MyCustomEventHandler
'''{'''
'''{'''
    add  
    add  
    '''{'''
    '''{'''
        ...
        ...
    '''}'''
    '''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
    remove  
    remove  
    '''{'''
    '''{'''
        ...
        ...
    '''}'''
    '''}'''
'''}'''
'''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
public this'''['''string index]
public this'''['''string index]
'''{'''
'''{'''
    get;
    get;
                                                        <font color="gray">// empty line goes here</font>     
                                                      <font color="gray">// empty line goes here</font>     
    set;
    set;
'''}'''
'''}'''
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


==Simple Statements==
==Simple Statements==
Line 398: Line 385:
In a situation where more than one condition is specified (eg. in <code>if</code>, <code>for</code> or <code>do-while</code>-statments), please follow these guidelines:
In a situation where more than one condition is specified (eg. in <code>if</code>, <code>for</code> or <code>do-while</code>-statments), please follow these guidelines:
* Place each condition on a separate line.
* Place each condition on a separate line.
* Place the ''&&'' and ''||'' that connects the conditions on the same line as the next condition. (see example)
* Place the ''&&'' and ''||'' that connects the conditions on the same line as the next condition. (See example.)
* If you have a very complicated condition statement, try to align the different conditions. The goal is to make the condition more readable in the end, so you may use you discretion here as well.
* If you have a very complicated condition statement, try to align the different conditions. The goal is to make the condition more readable in the end, so you may use your discretion here as well.


Example:
Example:
<pre>
if (((''condition1)''
if (((''condition1)''
      && (''condition2'')
    && (''condition2'')
      || (''condition3''
    || (''condition3''
          && ''condition4''))
        && ''condition4''))
    (&& !''condition5''))
    (&& !''condition5''))
{
{
    ...
  ...
}
}
</pre>


==If, if-else, if else-if else Statements==
==If, if-else, if else-if else Statements==
Line 421: Line 406:
* Spacing
* Spacing
** A space character should be put between "if" and the opening parenthesis "(".
** A space character should be put between "if" and the opening parenthesis "(".
** No space character should be put between the opening bracket "(" and the following code, no space character between code and the closing bracket ")".
** No space character should be put between the opening bracket "(" and the ensuing code statement(s), or between the code statement(s) and the closing bracket ")".
* Code block separation
* Code block separation
** An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
** An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
Line 428: Line 413:


For example:
For example:
<pre>
                        <font color="gray">// empty line goes here</font>
                        <font color="gray">// empty line goes here</font>
if '''('''condition''')'''
if '''('''condition''')'''
{
{
    DoSomething();
    DoSomething();
    ...
    ...
}
}
                        <font color="gray">// empty line goes here</font>
                        <font color="gray">// empty line goes here</font>
if '''('''condition''')'''  
if '''('''condition''')'''  
{
{
    DoSomething();
    DoSomething();
    ...
    ...
}  
}  
else  
else  
{
{
    DoSomethingOther();
    DoSomethingOther();
    ...
    ...
}
}
                        <font color="gray">// empty line goes here</font>
                        <font color="gray">// empty line goes here</font>
if '''('''condition''')'''
if '''('''condition''')'''
{
{
    DoSomething();
    DoSomething();
    ...
    ...
}  
}  
else if '''('''condition''')'''
else if '''('''condition''')'''
{
{
    DoSomethingOther();
    DoSomethingOther();
    ...
    ...
}  
}  
else  
else  
{
{
    DoSomethingOtherAgain();
    DoSomethingOtherAgain();
    ...
    ...
}
}
                        <font color="gray">// empty line goes here</font>
                        <font color="gray">// empty line goes here</font>
</pre>


<font color="blue">Enforced by Uncrustify: all rules</font>
<font color="blue">Enforced by Uncrustify: all rules</font>


==6.4 For / Foreach Statements==
==For / Foreach Statements==


<code>For</code> and <code>foreach</code> statements should follow the following formatting rules:
<code>For</code> and <code>foreach</code> statements should follow the following formatting rules:
Line 475: Line 458:
* Spacing
* Spacing
** A space character should be put between "for"/"foreach" and the opening parenthesis "(".
** A space character should be put between "for"/"foreach" and the opening parenthesis "(".
** No space character should be put between the opening bracket "(" and the following code, no space character between code and the closing bracket ")".
** No space character should be put between the opening bracket "(" and the ensuing code statement(s), or between the code statement(s) and the closing bracket ")".
** <code>for</code> only
** <code>for</code> only
*** Space characters should be put after the semicolon ";" which separates the initialisation, condition and execution code parts (contained inside the brackets).
*** Space characters should be put after the semicolon ";" which separates the initialisation, condition and execution code parts (contained inside the brackets).
Line 486: Line 469:


For example:
For example:
<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
for '''('''int Counter = 0; Counter < 5; ++Counter''')'''  
for '''('''int Counter = 0; Counter < 5; ++Counter''')'''  
{
{
    ...
    ...
}
}
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
foreach '''('''int MyIterator in IntList''')'''  
foreach '''('''int MyIterator in IntList''')'''  
{
{
    ...
    ...
}
}
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


<font color="blue">Enforced by Uncrustify: all rules</font>
<font color="blue">Enforced by Uncrustify: all rules</font>


==6.5 While/do-while Statements==
==While/Do-While Statements==


<code>while/do</code> statements should follow the following formatting rules:
<code>while/do</code> statements should follow the following formatting rules:
Line 510: Line 491:
* Spacing
* Spacing
** A space character should be put between "while" and the opening parenthesis "(".
** A space character should be put between "while" and the opening parenthesis "(".
** No space character should be put between the opening bracket "(" and the condition, no space character between the condition and the closing bracket ")".
** No space character should be put between the opening bracket "(" and the condition, or between the condition and the closing bracket ")".
* Code block separation
* Code block separation
** An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
** An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
Line 517: Line 498:


For example:
For example:
<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
while '''('''condition''')'''
while '''('''condition''')'''
{
{
    ...
    ...
}
}
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


An empty while should have the following form:
An empty while should have the following form:


<pre>
while '''(condition)'''
while '''(condition)'''
{
{
    ;
    ;
}
}
</pre>


A do-while statement should have the following form:
A do-while statement should have the following form:


<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
do  
do  
{
{
    ...
    ...
} while '''('''condition''')''';
} while '''('''condition''')''';
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


<font color="blue">Enforced by Uncrustify: all rules</font>
<font color="blue">Enforced by Uncrustify: all rules</font>


==6.6 Switch Statements==
==Switch Statements==


A <code>switch</code> statement should follow the following formatting rules:
A <code>switch</code> statement should follow the following formatting rules:
Line 556: Line 531:
* Spacing
* Spacing
** A space character should be put between "switch" and the opening parenthesis "(".
** A space character should be put between "switch" and the opening parenthesis "(".
** No space character should be put between the opening bracket "(" and the condition, no space character between the condition and the closing bracket ")".
** No space character should be put between the opening bracket "(" and the condition, or between the condition and the closing bracket ")".
* Code block separation
* Code block separation
** An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
** An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
** An empty line should succeed each 'break;' statement.
** An empty line should succeed each 'break;' statement.
*** Exception: no empty line after the 'break;' statement in the 'default' block.
*** Exception: no empty line after the 'break;' statement in the 'default' block.
* Other line breaks
* Other line breaks:
** the <code>case ''x'':</code> condition and the following statement(s) as well as the <code>default:</code> line and the following statement(s) should be separated by a line break.
** the <code>case ''x'':</code> condition and its ensuing statement(s), as well as the <code>default:</code> line and its statement(s), should be separated by a line break.


For example:
For example:
<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
switch '''('''condition''')'''
switch '''('''condition''')'''
{
{
    case A:                                            <font color="gray">// line break here</font>
    case A:                                            <font color="gray">// line break here</font>
        ...
        ...
        break;
        break;
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
    case B:                                            <font color="gray">// line break here</font>
    case B:                                            <font color="gray">// line break here</font>
        ...
        ...
        break;
        break;
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
    default:                                          <font color="gray">// line break here</font>
    default:                                          <font color="gray">// line break here</font>
        ...
        ...
        break;                                        <font color="gray">// NO empty line to follow!</font>
        break;                                        <font color="gray">// NO empty line to follow!</font>
}
}
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


<font color="blue">Enforced by Uncrustify: all rules</font>
<font color="blue">Enforced by Uncrustify: all rules</font>


==6.7 Try-catch Statements==
==Try-Catch Statements==


<code>try-catch</code> statements should follow the following formatting rules:
<code>try-catch</code> statements should follow these formatting rules:


* Braces
* Braces
Line 598: Line 571:


For example:
For example:
<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
try  
try  
{
{
    ...
    ...
}  
}  
catch (Exception)  
catch (Exception)  
{
{
    ...
    ...
}
}
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


or
or


<pre>
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
try  
try  
{
{
    ...
    ...
}  
}  
catch (ApplicationException ae)  
catch (ApplicationException ae)  
{
{
    ...
    ...
}
}
catch (Exception e)  
catch (Exception e)  
{
{
    ...
    ...
}  
}  
finally  
finally  
{
{
    ...
    ...
}
}
                                                        <font color="gray">// empty line goes here</font>
                                                      <font color="gray">// empty line goes here</font>
</pre>


<font color="blue">Enforced by Uncrustify: all rules, except for  
<font color="blue">Enforced by Uncrustify -</font> all rules, except for:
* 'Code block separation' (Uncrustify can't enforce that);
* 'Code block separation' (Uncrustify can't enforce that);
* 'Opening curly bracket must be on new line' for the 'finally' statement (Uncrustify's rule to enforce that doesn't work).</font>
* 'Opening curly bracket must be on new line' for the 'finally' statement (Uncrustify's rule to enforce that doesn't work).


=White Space=
=White Space=
Line 655: Line 624:
* Logical sections inside a method to improve readability.
* Logical sections inside a method to improve readability.


Blank lines should be indented to the correct indent level instead of leaving them blank or more worse using another indentation level. This makes the insertion of new statements in these lines much easier.
Blank lines should be indented to the correct indent level instead of leaving them blank or, even worse, using another indentation level. This makes the insertion of new statements in these lines much easier.


==Inter-term spacing==
==Inter-term spacing==
Line 662: Line 631:


For example:
For example:
<pre>
TestMethod(a, b, c);                              <font color="gray">// don't use : TestMethod(a,b,c)</font>
TestMethod(a, b, c);                              <font color="gray">// don't use : TestMethod(a,b,c)</font>
</pre>


Single spaces surround operators (except unary operators like increment (<code>++</code>) or logical not (<code>!</code>)).
Single spaces surround operators (except unary operators like increment (<code>++</code>) or logical not (<code>!</code>)).


For example:
For example:
<pre>
a = b;                                            <font color="gray">// don't use a=b;</font>
a = b;                                            <font color="gray">// don't use a=b;</font>
for (int Counter = 0; Counter < 10; ++Counter)    <font color="gray">// don't use 'for (int i=0; i<10; ++i)' 
                                                    // or 'for(int i=0;i<10;++i)'</font>


for (int Counter = 0; Counter < 10; ++Counter)    <font color="gray">// don't use 'for (int i=0; i<10; ++i)' 
<font color="blue">Enforced by Uncrustify:</font> all rules.
                                                  // or 'for(int i=0;i<10;++i)'</font>
</pre>
 
<font color="blue">Enforced by Uncrustify: all rules</font>




Line 695: Line 660:
===All-Uppercase===
===All-Uppercase===


All-uppercase capitalises all characters of a word. Use all-uppercase only for ''constant identifiers''. (For non-constant identifiers that are commonly used in all-uppercase (eg. URL, PI) use PascalCasing instead.)
All-uppercase capitalises all characters of a word. Use all-uppercase only for ''constant identifiers''. (For non-constant identifiers that are commonly used in all-uppercase (eg. URL, PI) use Pascal Casing instead.)
 


==Naming Guidelines==
==Naming Guidelines==
Line 705: Line 669:
in early Windows programming, but is now obsolete or at least should be considered deprecated. Using Hungarian Notation is not allowed if you follow this guide.
in early Windows programming, but is now obsolete or at least should be considered deprecated. Using Hungarian Notation is not allowed if you follow this guide.


''And remember: a good variable name describes the semantic not the type.''
''Remember: a good variable name describes the semantic not the type.''


An exception to this rule is GUI code. All fields and variable names that contain GUI elements like ''Button'' should be prefixed with their respective [[GUI_controls_prefixes|GUI control prefix]].
An exception to this rule is GUI code. All fields and variable names that contain GUI elements like ''Button'' should be prefixed with their respective [[GUI_controls_prefixes|GUI control prefix]].


For example:
For example:
<pre>
System.Windows.Forms.Button '''btn'''Cancel;
System.Windows.Forms.Button '''btn'''Cancel;
System.Windows.Forms.TextBox '''txt'''Name;
System.Windows.Forms.TextBox '''txt'''Name;
</pre>


===Namespace Naming Guidelines===
===Namespace Naming Guidelines===
* Namespace names should be nouns or noun phrases.
* Namespace names should be nouns or noun phrases.
* Use PascalCasing.
* Use Pascal Casing.
* Name prefix: none.
* Name prefix: none.


Line 723: Line 685:


* Class names should be nouns or noun phrases.
* Class names should be nouns or noun phrases.
* Use PascalCasing.
* Use Pascal Casing.
* Name prefix: 'T' (stands for '''T'''ype). It is to be followed by a capital letter (first character of the class name).  
* Name prefix: '<code>T</code>' (stands for '''T'''ype).
** Classes that are derived from <code>System.Windows.Form</code> should use the prefix <code>TFrm</code> instead.
** Classes that are derived from <code>System.Windows.Form</code> should use the prefix <code>TFrm</code> instead.


For example:
For example:
<pre>
public class TConnection
public class '''TC'''onnection
{
{
    ...
    ...
}
}
 
 
public class TFrmAboutPetra
public class '''TF'''rmAboutPetra
{
{
    ...
    ...
}
}
</pre>


===Interface Naming Guidelines===
===Interface Naming Guidelines===


* Name interfaces with nouns or noun phrases or adjectives describing behavior.
* Name interfaces with nouns or noun phrases or adjectives describing behaviour.
* Use PascalCasing
* Use Pascal Casing.
* Name prefix: 'I' (stands for '''I'''nterface). It is to be followed by a capital letter (first character of the interface name).
* Name prefix: '<code>I</code>' (stands for '''I'''nterface).


For example:
For example:
<pre>
public interface IComponent
public interface '''IC'''omponent
{
{
    ...
    ...
}
}
</pre>


===Exception Naming Guidelines===
===Exception Naming Guidelines===


* Name Exceptions with nouns or noun phrases.
* Name Exceptions with nouns or noun phrases.
* Use PascalCasing
* Use Pascal Casing.
* Name prefix: 'E' (stands for '''E'''xception). It is to be followed by a capital letter (first character of the exception name). Exceptions should also include the word <code>Exception</code> as a suffix to the name.
* Name prefix: '<code>E</code>' (stands for '''E'''xception).
* Name suffix: '<code>Exception</code>'. (The suffix is a recommended convention of Microsoft and considered good style by many C# programmers.)


For example:
For example:
<pre>
public class EDBConnectionNotEstablishedException : EOPDBException
public class '''EC'''onnectionException
{
{
    ...
    ...
}
}
</pre>


===Enum Naming Guidelines===
===Enum Naming Guidelines===


* Name
* Name
** Use singular names for enum ''types''. PascalCasing.
** Use singular names for enum ''types''. Pascal Casing.
** Use singular names for enum ''values''. camelCasing.
** Use singular names for enum ''values''. camelCasing.
* Prefixes
* Prefixes
Line 780: Line 737:


For example:
For example:
<pre>
public enum '''T'''ModuleSwitchEnum
public enum '''T'''ModuleSwitchEnum
{
{
    '''ms'''None, '''ms'''Partner, '''ms'''Personnel, '''ms'''Finance
    '''ms'''None, '''ms'''Partner, '''ms'''Personnel, '''ms'''Finance
}
}
 
 
public enum '''T'''UIConnectorTypeEnum
public enum '''T'''UIConnectorTypeEnum
{  
{  
    '''uict'''PartnerKey, '''uict'''LocationKey, '''uict'''NewPartner
    '''uict'''PartnerKey, '''uict'''LocationKey, '''uict'''NewPartner
}
}
</pre>


===Event Names===
===Event Names===
Line 797: Line 752:
Event Handlers:
Event Handlers:
* Name event handlers with the <code>EventHandler</code> suffix.
* Name event handlers with the <code>EventHandler</code> suffix.
* Name event handlers that have a concept of pre and post using the present and past tense (eg. <code>...Chang'''ing'''EventHandler</code> and <code>...Chang'''ed'''EventHandler</code>).
* Name event handlers that have a timeline concept of pre and post using the present and past tense (eg. <code>...Chang'''ing'''EventHandler</code> and <code>...Chang'''ed'''EventHandler</code>).
* For generic event handlers use two parameters named <code>sender</code> and <code>e</code>.
* For generic event handlers use two parameters named <code>sender</code> and <code>e</code>.
* Use PascalCasing.
* Use Pascal Casing.
* Prefix: 'T'. It is to be followed by a capital letter (first character of the event handler).
* Prefix: 'T' followed with a capital letter (first character of the event handler).


Event Arguments:
Event Arguments:
* Name event argument classes with the <code>EventArgs</code> suffix.
* Name event argument classes with the <code>EventArgs</code> suffix.
* Consider naming events using a verb.
* Consider naming events using a verb.
* Use PascalCasing.
* Use Pascal Casing.
* Prefix: 'T'. It is to be followed by a capital letter (first character of the event argument class).
* Prefix: 'T' followed with a capital letter (first character of the event argument class).


===Property Names===
===Property Names===
Line 812: Line 767:
* Name properties using nouns or noun phrases.
* Name properties using nouns or noun phrases.
* Consider naming a property with the same name as it’s Type.
* Consider naming a property with the same name as it’s Type.
* Use PascalCasing.
* Avoid having two property names that are singular and plural in one Class in order to disambiguate them (also if they are of different Types).
* Prefix: None!
** This good practice helps in preventing the programmer who reads the code from accidentally mixing up those two properties.
** Example: Rather than declaring two string properties '<code>FamilyName</code>' and '<code>FamilyName''s''</code>', which are different by only one letter, declare a string property '<code>FamilyName</code>' and '<code>SeveralFamilyNames</code>', which are more different.
* Use Pascal Casing.
* Prefix: none!


===Method Names===
===Method Names===


* Name methods with verbs or verb phrases.
* Name methods with verbs or verb phrases.
* Use PascalCasing.
* Use Pascal Casing.
* Prefix: None!
* Prefix: none!


===Argument Names===
===Argument Names===
'Arguments' are arguments that are passed to a method. They are used much like private variables of a method.
'Arguments' are parameters that are passed to a method. They are used much like private variables of a method.


* Use descriptive names, which should be enough to determine the argument's meaning and it’s type. But prefer a name that’s based on the argument’s meaning.
* Use accurate and descriptive names that are sufficient to determine the argument's meaning and it’s type.
* Use PascalCasing.
* Use Pascal Casing.
* Prefix: 'A' (stands for '''A'''rgument). It is to be followed by a capital letter (first character of the argument name).
* Prefix: 'A' (stands for '''A'''rgument) followed by a capital letter (first character of the argument name).


===Field Names===
===Field Names===
'Fields' are private variables of a class.
'Fields' are private variables of a class.


* Use descriptive names, which should be enough to determine the field's meaning and it’s type. But prefer a name that’s based on the field's meaning.
* Use accurate and descriptive names that are sufficient to determine the field's meaning and it’s type.
* Use PascalCasing.
* Avoid having two field names that are singular and plural in one Class in order to disambiguate them (also if they are of different Types).
* Prefix: 'F' (stands for '''F'''ield). It is to be followed by a capital letter (first character of the field name).
** This good practice helps in preventing the programmer who reads the code from accidentally mixing up those two fields.
** Example: Rather than declaring two string fields '<code>FFamilyName</code>' and '<code>FFamilyName''s''</code>', which are different by only one letter, declare a string field '<code>FFamilyName</code>' and '<code>FSeveralFamilyNames</code>', which are more different.  
* Use Pascal Casing.
* Prefix: 'F' (stands for '''F'''ield) followed by a capital letter (first character of the field name).


=== Variable Names===
=== Variable Names===
'Variables' are private variables of a method.
'Variables' are private variables of a method.


* Use descriptive names, which should be enough to determine the variable's meaning and it’s type. But prefer a name that’s based on the variable’s meaning.
* Use accurate and descriptive names that should be sufficient to determine the variable's meaning and it’s type.
* Boolean Variables: Prefer using prefixes like 'Is...', 'Has...' or 'Can...'. Generally you should give boolean variables names that imply true or false (eg. 'FileFound', 'Done', 'Success') or with its prefixes: 'IsFileFound', 'IsDone', 'IsSuccess' - but don't try 'Is''Name''' that doesn't make sense at all.
* Boolean variables: use prefixes like 'Is...', 'Has...' or 'Can...'. and names that imply true or false. For example: 'FileFound', 'Done', 'Success' or with their prefixes: 'IsFileFound', 'IsDone', 'IsSuccess'; don't try 'Is''Name''' that doesn't make sense at all.
* Loop counters: These are variables used in loops to serve as counters, indexes, or the like. You should use ''Counter'' as the standard name for these kinds of variables. Whenever you have a nested loop that also uses a counter, add numbers to the end to indicate the level of the counter.
* Loop counters: use ''Counter'' as the standard name for these kinds of variables as they are used in loops to serve as counters, indexes, or the like. Whenever you have a nested loop that also uses a counter, add numbers to the end to indicate the level of the counter.
* Temporary Variables: Many times you need to use a variables with no specific meaning - just a quick place-holder or something that will have but a moment of usage. These variables should be called ''Tmp''. Whenever you need to have more than one temporary variable, it warrants some more thinking on the part of the programmer to find better names for these variables.
* Temporary variables: should be called ''Tmp''. Many times you need to use a variables with no specific meaning - just a quick place-holder or something that will have but a moment of usage. Whenever you need more than one temporary variable in a particular context, you should consider using self-explanatory names for these variables instead.
* Use PascalCasing.
* Avoid having two variable names that are singular and plural in one Method in order to disambiguate them (also if they are of different Types). It is also a good practice do this if one method calls another method and the one handles singular and the other one plural instances of something.
* Prefix: None!
** These good practices help in preventing the programmer who reads the code from accidentally mixing up those two variables.
** Example: Rather than declaring two string variables '<code>FamilyName</code>' and '<code>FamilyName''s''</code>', which are different by only one letter, declare a string variable '<code>FamilyName</code>' and '<code>SeveralFamilyNames</code>', which are more different.  
* Use Pascal Casing.
* Prefix: none!


===Const Names===
===Constant Names===


* Name constant fields with nouns, noun phrases or abbreviations for nouns. If they consist of more than one word, separate the words with underscore characters (<code>_</code>).
* Name constant fields with nouns, noun phrases or abbreviations for nouns. If they consist of more than one word, separate the words with underscore characters (<code>_</code>).
* Use ALL-UPPERCASE
* Use ALL-UPPERCASE
* Prefix: None!
* Prefix: none!


For example:
For example:
<pre>
public class TMath
public class TMath
{
{
    public const string LONG_CONST_NAME = ...
    public const string LONG_CONST_NAME = ...
    public const double PI = 3.14...
    public const double PI = 3.14...
    public double Pi = 3.14...                        <font color="gray">// this is a variable and not a constant,  
    public double Pi = 3.14...                        <font color="gray">// this is a variable and not a constant,  
                                                        // so don't use PI</font>
                                                      // so don't use PI</font>
}
}
</pre>


===Naming and Capitalisation summary===
===Naming and Capitalisation Summary===


{| width="643" border="1" cellpadding="4"
{| width="643" border="1" cellpadding="4"
Line 1,006: Line 968:
   
   
|}
|}


=Programming Practices=
=Programming Practices=
Line 1,028: Line 988:
Instead declare a const which contains the number:
Instead declare a const which contains the number:


<pre>
public class TMyMath
public class TMyMath
{
{
    public const double PI = 3.14159265358979323846264338 <font color="peach">// As a double, will only store to 15 significant digits</font>
    public const double PI = 3.14...
}
}
</pre>


== SQL Queries ==
== SQL Queries ==
Line 1,051: Line 1,009:
<br /> Cumulative examples: <br />
<br /> Cumulative examples: <br />


<pre>
  SELECT a_column_1_i, a_column_2_l,
  SELECT a_column_1_i, a_column_2_l,
          a_column_3_i, a_column_4_n
        a_column_3_i, a_column_4_n
    FROM  a_table
    FROM  a_table
    WHERE a_column_1_i > 5
    WHERE a_column_1_i > 5
      AND a_column_2_l = TRUE
      AND a_column_2_l = TRUE
      OR  a_column_4_n = 10
      OR  a_column_4_n = 10
    ORDER BY a_column_3_i;
    ORDER BY a_column_3_i;
<br />
  SELECT surname, forenames
<br />
    FROM  employee
  SELECT surname, forenames
    WHERE depno =
    FROM  employee
          (SELECT depno
    WHERE depno =
            FROM  employee
          (SELECT depno
            WHERE empno = 16)
            FROM  employee
      AND empno != 16
            WHERE empno = 16)
      AND empno != 16
  DELETE FROM a_whatever
<br />
    WHERE mmm
<br />
      AND mmm
  DELETE FROM a_whatever
      OR  mmm
    WHERE mmm
      AND mmm
  UPDATE a_whatever
      OR  mmm
    SET (mm1 = 'khasg kvjshdfbv jszhdvb kszjhvb ksjvhb asj,f abv,jfhv badfj',
<br />
          mm2 = (SELECT id
<br />
                  FROM  something
  UPDATE a_whatever
                  WHERE something else)
    SET (mm1 = 'khasg kvjshdfbv jszhdvb kszjhvb ksjvhb asj,f abv,jfhv badfj',
          mm3, mm4)
        mm2 = (SELECT id
    WHERE mmm
                  FROM  something
      AND mmm;
                  WHERE something else)
        mm3, mm4)
    WHERE mmm
      AND mmm;
</pre>


<br /> Table aliases can be named by using the first letter of every word in the table name (excluding unnecessary things like prefixes). If the same table is used twice in the query with two aliases, simply add a number at the end of the alias name to distinguish them, or name them in such a way as to separate them logically. <br />
<br /> Table aliases can be named by using the first letter of every word in the table name (excluding unnecessary things like prefixes). If the same table is used twice in the query with two aliases, simply add a number at the end of the alias name to distinguish them, or name them in such a way as to separate them logically. <br />


<span style="font-style: italic;">Never use </span>''SELECT * ''<span style="font-style: italic;">for a query in Petra!</span> This can cause a lot of data transfer! By not using it you can prevent errors, and also make life much easier for things like typeddatasets.
<span style="font-style: italic;">Never use </span>''SELECT * ''<span style="font-style: italic;">for a query in Petra!</span> This can cause a lot of data transfer! By not using it you can prevent errors, and also make life much easier for things like Typed DataSets.


= Use Discretion! =
= Use Discretion! =
Line 1,101: Line 1,054:
==Brace placement example==
==Brace placement example==


<pre>
namespace ShowMeTheBracket
namespace ShowMeTheBracket
{
{
    public enum TTheTestEnum
    public enum TTheTestEnum
    {
    {
        ttOne, ttTwo
        ttOne, ttTwo
    }
    }
 
    public class TTestMeClass
    public class TTestMeClass
    {
    {
        TTheTestEnum FTestVar;
        TTheTestEnum FTestVar;
 
        public TTheTestEnum Test  
        public TTheTestEnum Test  
        {
        {
            get  
            get  
            {
            {
                return FTestVar;
                return FTestVar;
            }
            }
           
           
            set  
            set  
            {
            {
                FTestVar = value;
                FTestVar = value;
            }
            }
        }
        }
 
        void DoSomething()
        void DoSomething()
        {
        {
            if (FTestVar == TTestEnum.ttOne)  
            if (FTestVar == TTestEnum.ttOne)  
            {
            {
                //...stuff gets done
                //...stuff gets done
            }  
            }  
            else  
            else  
            {
            {
                //...other stuff gets done
                //...other stuff gets done
            }
            }
        }
        }
    }
    }
}
}
</pre>


==Variable naming example==
==Variable naming example==
Line 1,148: Line 1,099:
Instead of:
Instead of:


<pre>
for (int i = 1; i < num; ++i)  
for (int i = 1; i < num; ++i)  
{
{
    meetsCriteria[i] = true;  
    meetsCriteria[i] = true;  
}
}
 
 
for (int i = 2; i < num / 2; ++i)  
for (int i = 2; i < num / 2; ++i)  
{
{
    int j = i + i;
    int j = i + i;
 
    while (j <= num)  
    while (j <= num)  
    {
    {
        meetsCriteria[j] = false;
        meetsCriteria[j] = false;
        j += i;
        j += i;
    }
    }
}
}
 
 
for (int i = 0; i < num; ++i)  
for (int i = 0; i < num; ++i)  
{
{
    if (meetsCriteria[i])  
    if (meetsCriteria[i])  
    {
    {
        Console.WriteLine(i + " meets criteria");
        Console.WriteLine(i + " meets criteria");
    }
    }
}
}
</pre>




...do name variables appropriately:
...do name variables appropriately:


<pre>
for (int Counter1 = 1; Counter1 < num; ++Counter1)  
for (int Counter1 = 1; Counter1 < num; ++Counter1)  
{
{
    isPrime[Counter1] = true;  
    isPrime[Counter1] = true;  
}
}
 
 
for (int Counter2 = 2; Counter2 < num / 2; ++Counter2)  
for (int Counter2 = 2; Counter2 < num / 2; ++Counter2)  
{
{
    int factorableNumber = Counter2 + Counter2;
    int factorableNumber = Counter2 + Counter2;
 
    while (factorableNumber <= num)  
    while (factorableNumber <= num)  
    {
    {
        isPrime[factorableNumber] = false;
        isPrime[factorableNumber] = false;
        factorableNumber += Counter2;
        factorableNumber += Counter2;
    }
    }
}
}
 
 
for (int Counter3 = 0; Counter3 < num; ++Counter3)  
for (int Counter3 = 0; Counter3 < num; ++Counter3)  
{
{
    if (isPrime[Counter3])  
    if (isPrime[Counter3])  
    {
    {
        Console.WriteLine(Counter3 + " is prime.");
        Console.WriteLine(Counter3 + " is prime.");
    }
    }
}
}
</pre>


'''Note:''' Indexer variables should generally be called Counter1, Counter2, etc. But in cases like this where it isn't quickly obvious what is going on with those loops, it may make sense to reconsider this rule: for instance, <code>Counter1</code> and <code>Counter3</code> could be renamed to <code>PrimeCandidate</code>, and <code>Counter2</code> to <code>Factor</code> to make the code more 'self-documenting'.
'''Note:''' indexer variables should generally be called Counter1, Counter2, etc. But in cases like this where it isn't quickly obvious what is going on with those loops, it may make sense to reconsider this rule: for instance, <code>Counter1</code> and <code>Counter3</code> could be renamed to <code>PrimeCandidate</code>, and <code>Counter2</code> to <code>Factor</code> to make the code more 'self-documenting'.

Latest revision as of 10:19, 17 August 2016

About the C# Coding Style Guide

This document may be read as a guide to writing robust and reliable C# programs.

Notes:

  1. Many of the rules in this document can be applied automatically to source code using the 'Uncrustify' tool that we use (make uncrustify)
    1. Those rules are marked with 'Enforced by Uncrustify.'
  2. Many of the rules in this document can be checked automatically with the 'StyleCop' tool that we use (make stylecop)!
    1. Those rules are marked with 'Checked by StyleCop.' TODO
  3. 'Uncrustify' and 'StyleCop' and how we use them with Petra are described in Coding Standards Tools: 'Uncrustify' and 'StyleCop'.

This 'C# Coding Style Guide' was inspired by the C# Coding Style Guide written by Mike Krüger. This is used by the SharpDevelop programmers who work on the SharpDevelop IDE.

File Organization

C# Sourcefiles

  • Keep your classes/files short: try hard not to exceed 3.000 lines of code and never go beyond 4.000 lines of code.
    • Exception to that:
      • Auto-generated code can ignore that rule if the generated file doesn't need to be looked at/touched by developers.
  • Divide your code up and make structures clearer.
  • Every class should go in a separate file.
    • Exceptions to that:
      • Helper classes for the main class in the same file are allowed, but they must be private classes!
      • Auto-generated code can ignore that rule if the generated file doesn't need to be looked at/touched by developers.
  • The file name should reflect the name of the class in the file (.cs as extension of course).
    • Exception to that:
      • The file name of a source file can have the last part of a Namespace in it if the Namespace is nested quite deeply and

the directory structure doesn't reflect that deep nesting anymore (see 'Directory Layout' below). Example: DataAggregates.PPartnerAddress.cs in Namespace 'Ict.Petra.Server.MPartner.DataAggregates' in directory 'U:\openpetraorg\csharp\ICT\Petra\Server\lib\MPartner'.


These conventions makes things much easier to read and find.

Directory Layout

  • Create a directory for every namespace. Example: for Namespace 'Ict.Petra.Server.App.Core' use 'U:\delphi.net\ICT\Petra\Server\app\' as the path (do not use the Namespace name with dots for directory names).
    • Exceptions to that:
      • Additional directories might be placed inbetween parts of the Namespace if that benefits the directory structure and an agreed rule when to do that is followed. Example: Namespace 'Ict.Petra.Server.MPartner.DataAggregates' resides in directory 'U:\delphi.net\ICT\Petra\Server\lib\MPartner'. Note the 'lib' directory, which is inserted.
      • If a Namespace is nested quite deeply, we can opt to have the directory structure not reflecting that deep nesting. In that case, the last part of a Namespace should then be part of the file name of a Class (see 'C# Sourcefiles' above).


See also 'Explanation of Directory Structure and Rules' for more detailed information!


These conventions make it easier to map namespaces to the directory layout.

Indentation

White Spaces

For code indentation, two standards exist in the world of programming: indendation with spaces and indendation with tabs. Some programmers prefer spaces, others prefer tabs.

Here, we define the space character as the standard indentation character. Specifically, we indent everything with four spaces - Enforced by Uncrustify. This applies for the indendation from column 1 to the indendation level of the current code and also to any further indendations from there.

By using spaces, not tabs, we can ensure that our code is indented identically for every developer and in every editor. If we used tabs, the indentation could vary.

Don't use tabs for indentation - use spaces! Enforced by Uncrustify.

Wrapping Lines

When an expression will not fit on a single line, break it up before it reaches more than 150 characters. Enforced by Uncrustify. You might want to break it up before that for readability.

Follow these general principles when breaking up a line:

  • Break after a comma.
  • Break after an operator.
  • Prefer higher-level breaks to lower-level breaks.
  • Indent the new line at the standard indentation level, or align the new line with the beginning of the expression at the same level on the previous line.

Example of breaking up method calls:

LongMethodCall(expr1, expr2,

     expr3, expr4, expr5);  // indented at the standard indentation level

or

LongMethodCall(expr1, expr2,

                expr3, expr4, expr5);  // aligned with the beginning of the expression on the previous line

The first is preferred because it results in uniformly formatted code, but if indenting with the second method makes for better reading in a specific case then use the second method.


Examples of breaking an arithmetic expression:

PREFER:

var = a * b / (c - g + f) + 

    4 * z;

BAD STYLE – AVOID:

var = a * b / (c - g + 

    f) + 4 * z;

The first is preferred, since the break occurs outside the paranthesized expression (higher level rule).


Comments

All comments must be written in English.

Block Comments

Block comments for the purpose of describing Classes, Methods, etc. should be avoided. Instead, use of the /// comments to give C# standard descriptions is recommended (see 'Documentation Comments' below).

If you wish to use block comments inside Methods, Classes, etc. you should use the following style:

/* The following Algorithm does bla bla bla

 * and is adapted from the well-known blah blah Algorithm.

 * An example of this Algorithm can be found on http://www.blahalgorithms.org

 */

...as this will set off the block visually from code for the (human) reader.

Block comments may be useful in rare cases, refer to the TechNote 'The fine Art of Commenting' for an example.

As a general rule of thumb, the length of a comment should not overly exceed the length of the code it explains as this is an indication of too complicated (and potentially buggy) code.

For commenting out sections of code, use the 'Single Line Comments' (despite their name) to distinguish better between code that has comments attached and code that is commented out.

Single Line Comments

Developers should use the // (two forward slahes) comment style to "comment out" code (SharpDevelop has a shotcut key for it, Alt+/). It may be used for commenting out sections of code too.

Note on using StyleCop: because we will use StyleCop, you should rather use //// (four forward slashes) instead of // when commenting out single lines of code. This helps the tool to not confuse it with a single line comment (which is not commented out code). (Refers to StyleCop Rule SA1512: SingleLineCommentsMustNotBeFollowedByBlankLine.)


Single line code comments must be indented to the indent level when they are used for code documentation. Commented out code should be commented out so that the // (two slashes) start in column 1. This is to enhance the visibility of commented out code.

Documentation Comments

In the .NET framework, Microsoft has introduced a documentation generation system based on XML comments. These comments are formally single line C# comments containing XML tags. They follow this pattern for single line comments:

/// <summary>

/// This class...

/// </summary>

Multiline XML comments follow this pattern:

/// <exception cref=”BogusException”>

/// This exception gets thrown as soon as a

/// Bogus flag gets set.

/// </exception>

All lines must be preceded by /// (three slashes) to be accepted as XML comment lines.

Tags fall into two categories:

  • Documentation items
  • Formatting/Referencing

The first category contains tags like <summary>, <param> or <exception>. These tags represent the elements of a program's API which must be documented for the program to be useful to other programmers. They usually have attributes such as name or cref (as demonstrated in the multi line example above) and are checked by the compiler, so they should be valid.

The latter category governs the layout of the documentation, using tags such as <code>, <list> or <para>.

For a fuller explanation of XML comments see 'CSharp In-Code Documentation with MS XML Tags'. For information on how to produce API-style documentation for C# Projects whose .cs files contain XML Comment Tags, see 'How to produce CSharp API Documentation'.

For information on commenting best practice and further issues related to commenting, see the TechNote 'The fine Art of Commenting'.

End Comments

By 'End Comments' we mean adding a single-line comment after the closing curly brace "}" of a code block to explain what section of code the closing curly braces ends.

We decided this is unnecessary if this information is obvious. In other words, use 'End Comments' only when the meaning of the closing curly brace "}" of a code block is not immediately obvious due to either a very long block, or in the case of many nested blocks.

Declarations

Number of Declarations per Line

Only one declaration per line is allowed. This greatly enhances readabiliy and it encourages commenting.

GOOD STYLE:

int Level;   // indentation level
int Size;    // size of table

Do not put more than one variable or variables of different types on the same line when declaring them.

BAD STYLE - AVOID:

int Var1, Var2;   // What is 'Var1'? What does 'Var2' stand for?

Declarations should be followed by an empty line so that they are visually set apart from the rest of the source code. Enforced by Uncrustify.

The above example also demonstrates the drawbacks of non-obvious variable names.

Be clear when naming variables. Using self-explanatory variable names such as IndentLevel eradicates the need for making explanatory comments.

Initialization

Try to initialize local variables as soon as they are declared.

For example:

string Name = myObject.Name;
int Val = time.Hours;

Initialisations should be followed by an empty line so that they are visually set apart from the rest of the source code. Enforced by Uncrustify if the initialisations are part of declarations.

Note: when initializing a Dialog/Modal Form (by using .ShowDialog instead of .Show), use the following construct to be sure the Form is released from memory when it is closed:

using (TOpenFileDialog openFileDialog = new TOpenFileDialog()) 
{
   openFileDialog.ShowDialog();
    ...
}   // .NET will release openFileDialog automatically, so we can't forget about it!

Background: forms shown with .ShowDialog are not released from memory, but kept in memory so the caller can call methods after the Form is closed to retrieve parameters. Therefore, you can forget to release the form from memory later.

Class, Interface and Namespace Declarations

For C# classes, interfaces and namespaces, the following formatting rules should be followed:

  • Braces
    • The opening brace "{" appears in the next line after the declaration statement.
    • The closing brace "}" starts a line by itself indented to match its corresponding opening brace.
    • The opening brace "{" and the closing brace "}" should be on the same indentation level as the code block construct that owns it.
  • Spacing
    • A single space character should be placed on each side of the colon that follows the class name.
    • If there is a list of types/interfaces that the class inherits from, the items should be separated by a comma followed by a space character.
  • Code block separation
    • An empty line should preceed and succeed each class, interface or namespace block.
      • Exceptions:
        • if a class, interface or namespace block begins immediately after another class, interface or namespace block has been started with an opening brace "{": then no empty line should be inserted.
        • if a class, interface or namespace block ends and another enclosing code block also ends immediately after the closing brace "}": then no empty line should be inserted.

For example:

namespace MyNamespace
{                                                     // no empty line
    class TMySample : TMyClass, IMyInterface
    {
        void DoSomething()
        {
        
        }
        
        void DoAnotherThing()
        {
        
        }
    }
                                                       // empty line goes here
    class TMyOtherSample : TMySample, IMyOtherInterface
    {
        void DoSomething()
        {
        
        }
        
        void DoAnotherThing()
        {
        
        }
    }                                                  // no empty line
}

For another brace placement example look at section 'Code Examples - Brace placement example'.

Enforced by Uncrustify: all rules

Method Declarations

For method declarations the following formatting rules should be followed:

  • Braces
    • Class braces placement rules should be applied.
  • Spacing
    • No space should be put between a method name and the opening parenthesis "(" that starts its parameter list.
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).

For example:

                                                       // empty line goes here
public MySample(int AMyInt)
{
    this.FMyInt = AMyInt;
}
                                                       // empty line goes here
void Inc()
{
    ++FMyInt;
}
                                                       // empty line goes here

Enforced by Uncrustify: all rules

Property, Indexer and Event Declarations

For properties, indexers and events, the following formatting rules should be followed:

  • Braces
    • Class braces placement rules should be applied. Enforced by Uncrustify: all rules, except for 'opening curly bracket must be on a new line' (Uncrustify can't enforce that for EventHandlers).
  • Spacing
    • For properties where both 'get' and 'set' blocks are present, an empty line should be placed between the 'get' block and the 'set' block.
    • For event handlers where both 'add' and 'remove' blocks are present, an empty line should be placed between the 'add' block and the 'remove' block.
    • For indexers, use no space between 'this' and '['. Enforced by Uncrustify.
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
  • No one-liners
    • Always use braces "{" and "}" on their own code lines even if there is only one statement in the getter/setter or adder/remover!

For example:

                                                       // empty line goes here
public int Amount 
{
    get 
    {
        ...
    }
                                                       // empty line goes here    
    set 
    {
        ... 

    }
}
                                                       // empty line goes here
public EventHandler MyCustomEventHandler
{
    add 
    {
        ...
    }
                                                       // empty line goes here
    remove 
    {
        ...
    }
}
                                                       // empty line goes here
public this[string index]
{
    get;
                                                       // empty line goes here    
    set;
}
                                                       // empty line goes here

Simple Statements

Each code line should contain only one statement.

Return Statements

A return statement should not use outermost parentheses. Enforced by Uncrustify.

GOOD STYLE :

return (n * (n + 1)) / 2;

BAD STYLE - AVOID:

return ((n * (n + 1)) / 2);


Statements With Multiple Conditions

In a situation where more than one condition is specified (eg. in if, for or do-while-statments), please follow these guidelines:

  • Place each condition on a separate line.
  • Place the && and || that connects the conditions on the same line as the next condition. (See example.)
  • If you have a very complicated condition statement, try to align the different conditions. The goal is to make the condition more readable in the end, so you may use your discretion here as well.

Example:

if (((condition1)
     && (condition2)
     || (condition3
         && condition4))
    (&& !condition5))
{
   ...
}

If, if-else, if else-if else Statements

if, if-else and if else-if else statements should follow the following formatting rules:

  • Braces
    • Class braces placement rules should be applied.
  • Spacing
    • A space character should be put between "if" and the opening parenthesis "(".
    • No space character should be put between the opening bracket "(" and the ensuing code statement(s), or between the code statement(s) and the closing bracket ")".
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
  • No one-liners
    • Always use braces "{" and "}" on their own code lines even if there is only one statement in the condition!

For example:

                        // empty line goes here
if (condition)
{
    DoSomething();
    ...
}
                        // empty line goes here
if (condition) 
{
    DoSomething();
    ...
} 
else 
{
    DoSomethingOther();
    ...
}
                        // empty line goes here
if (condition)
{
    DoSomething();
    ...
} 
else if (condition)
{
    DoSomethingOther();
    ...
} 
else 
{
    DoSomethingOtherAgain();
    ...
}
                        // empty line goes here

Enforced by Uncrustify: all rules

For / Foreach Statements

For and foreach statements should follow the following formatting rules:

  • Braces
    • Class braces placement rules should be applied.
  • Spacing
    • A space character should be put between "for"/"foreach" and the opening parenthesis "(".
    • No space character should be put between the opening bracket "(" and the ensuing code statement(s), or between the code statement(s) and the closing bracket ")".
    • for only
      • Space characters should be put after the semicolon ";" which separates the initialisation, condition and execution code parts (contained inside the brackets).
      • Inter-term spacing rules should be applied (see 'Inter-term spacing' below).
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
  • No one-liners
    • Always use braces "{" and "}" on their own code lines even if there is only one statement in the loop!


For example:

                                                       // empty line goes here
for (int Counter = 0; Counter < 5; ++Counter) 
{
    ...
}
                                                       // empty line goes here
foreach (int MyIterator in IntList) 
{
    ...
}
                                                       // empty line goes here

Enforced by Uncrustify: all rules

While/Do-While Statements

while/do statements should follow the following formatting rules:

  • Braces
    • Class braces placement rules should be applied.
  • Spacing
    • A space character should be put between "while" and the opening parenthesis "(".
    • No space character should be put between the opening bracket "(" and the condition, or between the condition and the closing bracket ")".
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
  • No one-liners
    • Always use braces "{" and "}" on their own code lines even if there is only one statement in the loop!

For example:

                                                       // empty line goes here
while (condition)
{
    ...
}
                                                       // empty line goes here

An empty while should have the following form:

while (condition)
{
    ;
}

A do-while statement should have the following form:

                                                       // empty line goes here
do 
{
    ...
} while (condition);
                                                       // empty line goes here

Enforced by Uncrustify: all rules

Switch Statements

A switch statement should follow the following formatting rules:

  • Braces
    • Class braces placement rules should be applied.
  • Spacing
    • A space character should be put between "switch" and the opening parenthesis "(".
    • No space character should be put between the opening bracket "(" and the condition, or between the condition and the closing bracket ")".
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
    • An empty line should succeed each 'break;' statement.
      • Exception: no empty line after the 'break;' statement in the 'default' block.
  • Other line breaks:
    • the case x: condition and its ensuing statement(s), as well as the default: line and its statement(s), should be separated by a line break.

For example:

                                                       // empty line goes here
switch (condition)
{
    case A:                                            // line break here
        ...
        break;
                                                       // empty line goes here
    case B:                                            // line break here
        ...
        break;
                                                       // empty line goes here
    default:                                           // line break here
        ...
        break;                                         // NO empty line to follow!
}
                                                       // empty line goes here

Enforced by Uncrustify: all rules

Try-Catch Statements

try-catch statements should follow these formatting rules:

  • Braces
    • Class braces placement rules should be applied.
  • Code block separation
    • An empty line should preceed and succeed the statement block (the same applies to other statements that appear as blocks of code).
  • No one-liners
    • Always use braces "{" and "}" on their own code lines even if there is only one statement in the respective try/except/finally section!

For example:

                                                       // empty line goes here
try 
{
    ...
} 
catch (Exception) 
{
    ...
}
                                                       // empty line goes here

or

                                                       // empty line goes here
try 
{
    ...
} 
catch (ApplicationException ae) 
{
    ...
}
catch (Exception e) 
{
    ...
} 
finally 
{
    ...
}
                                                       // empty line goes here

Enforced by Uncrustify - all rules, except for:

  • 'Code block separation' (Uncrustify can't enforce that);
  • 'Opening curly bracket must be on new line' for the 'finally' statement (Uncrustify's rule to enforce that doesn't work).

White Space

Blank Lines

Blank lines improve readability by setting off blocks of code which are in themselves logically related.

Two blank lines should always be used between:

  • Logical sections of a source file.
  • Class and interface definitions (try one class/interface per file to prevent this case).

One blank line should always be used between:

  • Methods. Enforced by Uncrustify
  • Properties.
  • Code blocks (if statements, for/foreach loops and while loops, switch blocks and try/catch blocks). Enforced by Uncrustify
  • Local variables in a method and the first statement in the method. Enforced by Uncrustify (although not always reliable)
  • Logical sections inside a method to improve readability.

Blank lines should be indented to the correct indent level instead of leaving them blank or, even worse, using another indentation level. This makes the insertion of new statements in these lines much easier.

Inter-term spacing

There should be a single space after a comma or a semicolon.

For example:

TestMethod(a, b, c);                              // don't use : TestMethod(a,b,c)

Single spaces surround operators (except unary operators like increment (++) or logical not (!)).

For example:

a = b;                                            // don't use a=b;

for (int Counter = 0; Counter < 10; ++Counter)    // don't use 'for (int i=0; i<10; ++i)'   
                                                   // or 'for(int i=0;i<10;++i)'

Enforced by Uncrustify: all rules.


Naming Conventions

All names of all code elements must be written in English.

Capitalization Styles

Pascal Casing

This convention capitalises the first character of each word (as in TestCounter).

Camel Casing

This convention capitalises the first character of each word except the first word (as in testCounter).

All-Uppercase

All-uppercase capitalises all characters of a word. Use all-uppercase only for constant identifiers. (For non-constant identifiers that are commonly used in all-uppercase (eg. URL, PI) use Pascal Casing instead.)

Naming Guidelines

Naming according to the guidelines for 'Hungarian Notation' is considered bad practice.

Hungarian Notation is a defined set of prefixes and postfixes which are applied to names to reflect the type of the variable. This style of naming was widely used in early Windows programming, but is now obsolete or at least should be considered deprecated. Using Hungarian Notation is not allowed if you follow this guide.

Remember: a good variable name describes the semantic not the type.

An exception to this rule is GUI code. All fields and variable names that contain GUI elements like Button should be prefixed with their respective GUI control prefix.

For example:

System.Windows.Forms.Button btnCancel;
System.Windows.Forms.TextBox txtName;

Namespace Naming Guidelines

  • Namespace names should be nouns or noun phrases.
  • Use Pascal Casing.
  • Name prefix: none.

Class Naming Guidelines

  • Class names should be nouns or noun phrases.
  • Use Pascal Casing.
  • Name prefix: 'T' (stands for Type).
    • Classes that are derived from System.Windows.Form should use the prefix TFrm instead.

For example:

public class TConnection
{
    ...
}


public class TFrmAboutPetra
{
    ...
}

Interface Naming Guidelines

  • Name interfaces with nouns or noun phrases or adjectives describing behaviour.
  • Use Pascal Casing.
  • Name prefix: 'I' (stands for Interface).

For example:

public interface IComponent
{
    ...
}

Exception Naming Guidelines

  • Name Exceptions with nouns or noun phrases.
  • Use Pascal Casing.
  • Name prefix: 'E' (stands for Exception).
  • Name suffix: 'Exception'. (The suffix is a recommended convention of Microsoft and considered good style by many C# programmers.)

For example:

public class EDBConnectionNotEstablishedException : EOPDBException
{
    ...
}

Enum Naming Guidelines

  • Name
    • Use singular names for enum types. Pascal Casing.
    • Use singular names for enum values. camelCasing.
  • Prefixes
    • Enum type name: 'T'. It is to be followed by a capital letter (first character of the enum name). Enum types should also include the word Enum as a suffix to the name.
    • Enum values: concatenate the letters of each word that make up the enum type name and prefix those in lower case to the enum value.


For example:

public enum TModuleSwitchEnum
{
    msNone, msPartner, msPersonnel, msFinance
}


public enum TUIConnectorTypeEnum
{ 
    uictPartnerKey, uictLocationKey, uictNewPartner
}

Event Names

Event Handlers:

  • Name event handlers with the EventHandler suffix.
  • Name event handlers that have a timeline concept of pre and post using the present and past tense (eg. ...ChangingEventHandler and ...ChangedEventHandler).
  • For generic event handlers use two parameters named sender and e.
  • Use Pascal Casing.
  • Prefix: 'T' followed with a capital letter (first character of the event handler).

Event Arguments:

  • Name event argument classes with the EventArgs suffix.
  • Consider naming events using a verb.
  • Use Pascal Casing.
  • Prefix: 'T' followed with a capital letter (first character of the event argument class).

Property Names

  • Name properties using nouns or noun phrases.
  • Consider naming a property with the same name as it’s Type.
  • Avoid having two property names that are singular and plural in one Class in order to disambiguate them (also if they are of different Types).
    • This good practice helps in preventing the programmer who reads the code from accidentally mixing up those two properties.
    • Example: Rather than declaring two string properties 'FamilyName' and 'FamilyNames', which are different by only one letter, declare a string property 'FamilyName' and 'SeveralFamilyNames', which are more different.
  • Use Pascal Casing.
  • Prefix: none!

Method Names

  • Name methods with verbs or verb phrases.
  • Use Pascal Casing.
  • Prefix: none!

Argument Names

'Arguments' are parameters that are passed to a method. They are used much like private variables of a method.

  • Use accurate and descriptive names that are sufficient to determine the argument's meaning and it’s type.
  • Use Pascal Casing.
  • Prefix: 'A' (stands for Argument) followed by a capital letter (first character of the argument name).

Field Names

'Fields' are private variables of a class.

  • Use accurate and descriptive names that are sufficient to determine the field's meaning and it’s type.
  • Avoid having two field names that are singular and plural in one Class in order to disambiguate them (also if they are of different Types).
    • This good practice helps in preventing the programmer who reads the code from accidentally mixing up those two fields.
    • Example: Rather than declaring two string fields 'FFamilyName' and 'FFamilyNames', which are different by only one letter, declare a string field 'FFamilyName' and 'FSeveralFamilyNames', which are more different.
  • Use Pascal Casing.
  • Prefix: 'F' (stands for Field) followed by a capital letter (first character of the field name).

Variable Names

'Variables' are private variables of a method.

  • Use accurate and descriptive names that should be sufficient to determine the variable's meaning and it’s type.
  • Boolean variables: use prefixes like 'Is...', 'Has...' or 'Can...'. and names that imply true or false. For example: 'FileFound', 'Done', 'Success' or with their prefixes: 'IsFileFound', 'IsDone', 'IsSuccess'; don't try 'IsName' that doesn't make sense at all.
  • Loop counters: use Counter as the standard name for these kinds of variables as they are used in loops to serve as counters, indexes, or the like. Whenever you have a nested loop that also uses a counter, add numbers to the end to indicate the level of the counter.
  • Temporary variables: should be called Tmp. Many times you need to use a variables with no specific meaning - just a quick place-holder or something that will have but a moment of usage. Whenever you need more than one temporary variable in a particular context, you should consider using self-explanatory names for these variables instead.
  • Avoid having two variable names that are singular and plural in one Method in order to disambiguate them (also if they are of different Types). It is also a good practice do this if one method calls another method and the one handles singular and the other one plural instances of something.
    • These good practices help in preventing the programmer who reads the code from accidentally mixing up those two variables.
    • Example: Rather than declaring two string variables 'FamilyName' and 'FamilyNames', which are different by only one letter, declare a string variable 'FamilyName' and 'SeveralFamilyNames', which are more different.
  • Use Pascal Casing.
  • Prefix: none!

Constant Names

  • Name constant fields with nouns, noun phrases or abbreviations for nouns. If they consist of more than one word, separate the words with underscore characters (_).
  • Use ALL-UPPERCASE
  • Prefix: none!

For example:

public class TMath
{
    public const string LONG_CONST_NAME = ...
    public const double PI = 3.14...
    public double Pi = 3.14...                         // this is a variable and not a constant, 
                                                       // so don't use PI
}

Naming and Capitalisation Summary

Type

Prefix

Case

Notes

Namespaces

none

Pascal Casing

Classes / Structs

T

Pascal Casing

Special prefix: TFrm if derived from System.Windows.Form.

Interfaces I

Pascal Casing

Exception Classes

E

Pascal Casing

Suffix: Exception.

Enum Types

T

Pascal Casing

Suffix: Enum

Enum Values

see Notes

Camel Casing

Prefix: Concatenate the letters of each word that make up the enum type name and prefix those in lower case to the enum value.

Event Handlers / Event Arguments

T

Pascal Casing

Suffix for Event Handlers: EventHandler. Suffix for Event Arguments: EventArgs.

Properties

none

Pascal Casing

Methods

none

Pascal Casing

Arguments

A

Pascal Casing

Fields

F

Pascal Casing

Local variables

none

Pascal Casing

Global Variables

G

Pascal Casing

Constants

none

All-Uppercase

Programming Practices

Visibility

Generally

Give a class, interface, event handler, method, field always the least possible visibility. This means that you should consider giving it private visibility, and only if that is not enough increase the visibility - but only as much as is needed.

Fields

Do not make fields public - always make them private. Create properties for fields instead. You may use public static fields (or consts) as an exception to this rule, but be very careful with it.

Having appropriate visibility ensures proper use of classes by every programmer and is kind of 'self-documenting' in the way that it tells how the class can be used.

No 'Magic' Numbers

Do not use 'magic' numbers, i.e. place constant numerical values directly into the source code. Replacing these lateron in case of changes (say, your application can now handle 3540 users instead of the 427 users hardcoded into your code in 50 lines scattered troughout your 25000 lines of code) is error-prone and unproductive. Instead declare a const which contains the number:

public class TMyMath
{
    public const double PI = 3.14159265358979323846264338 // As a double, will only store to 15 significant digits
}

SQL Queries

All SQL keywords should be in capital letters.

The main query command keyword (e.g. SELECT, UPDATE, INSERT, etc.) should be on the indentation base, and the rest of the text belonging to that query should be indented.

Indentation for SQL queries should be four spaces (like for the rest of the source code).

If the list of columns or tables become to long, it should be split over more than one line. If this is done, the lists should be aligned.

Every keyword that signifies a new 'section' of the query should be on a new line, with everything belonging to that section indented. (See example.)

The keywords AND and OR should also be on a new line, and indented. It is also recommended to try and align the conditions. To do this, simply add a few spaces after the AND and OR keywords until the condition is aligned to the one in the previous line.


Cumulative examples:

  SELECT a_column_1_i, a_column_2_l,
         a_column_3_i, a_column_4_n
    FROM  a_table
    WHERE a_column_1_i > 5
      AND a_column_2_l = TRUE
      OR  a_column_4_n = 10
    ORDER BY a_column_3_i;

  SELECT surname, forenames
    FROM  employee
    WHERE depno =
          (SELECT depno
            FROM  employee
            WHERE empno = 16)
      AND empno != 16

  DELETE FROM a_whatever
    WHERE mmm
      AND mmm
      OR  mmm

  UPDATE a_whatever
    SET (mm1 = 'khasg kvjshdfbv jszhdvb kszjhvb ksjvhb asj,f abv,jfhv badfj',
         mm2 = (SELECT id
                  FROM  something
                  WHERE something else)
         mm3, mm4)
    WHERE mmm
      AND mmm;


Table aliases can be named by using the first letter of every word in the table name (excluding unnecessary things like prefixes). If the same table is used twice in the query with two aliases, simply add a number at the end of the alias name to distinguish them, or name them in such a way as to separate them logically.

Never use SELECT * for a query in Petra! This can cause a lot of data transfer! By not using it you can prevent errors, and also make life much easier for things like Typed DataSets.

Use Discretion!

These standards were set up to help us as programmers to better maintain the code. Please try to comply to these standards.

We realise that there are times when the standards would actually have a negative effect, or maybe where the standards are not entirely clear. In these situations, please use your discretion to come up with a suitable alternative, and discuss it with the rest of the team before you use it.


Code Examples

Brace placement example

namespace ShowMeTheBracket
{
    public enum TTheTestEnum
    {
        ttOne, ttTwo
    }

	
    public class TTestMeClass
    {
        TTheTestEnum FTestVar;

		
        public TTheTestEnum Test 
        {
            get 
            {
                return FTestVar;
            }
            
            set 
            {
                FTestVar = value;
            }
        }

		
        void DoSomething()
        {
            if (FTestVar == TTestEnum.ttOne) 
            {
                //...stuff gets done
            } 
            else 
            {
                //...other stuff gets done
            }
        }
    }
}

Variable naming example

Instead of:

for (int i = 1; i < num; ++i) 
{
    meetsCriteria[i] = true; 
}


for (int i = 2; i < num / 2; ++i) 
{
    int j = i + i;
	

    while (j <= num) 
    {
        meetsCriteria[j] = false;
        j += i;
    }
}


for (int i = 0; i < num; ++i) 
{
    if (meetsCriteria[i]) 
    {
        Console.WriteLine(i + " meets criteria");
    }
}


...do name variables appropriately:

for (int Counter1 = 1; Counter1 < num; ++Counter1) 
{
    isPrime[Counter1] = true; 
}


for (int Counter2 = 2; Counter2 < num / 2; ++Counter2) 
{
    int factorableNumber = Counter2 + Counter2;

	
    while (factorableNumber <= num) 
    {
        isPrime[factorableNumber] = false;
        factorableNumber += Counter2;
    }
}


for (int Counter3 = 0; Counter3 < num; ++Counter3) 
{
    if (isPrime[Counter3]) 
    {
        Console.WriteLine(Counter3 + " is prime.");
    }
}

Note: indexer variables should generally be called Counter1, Counter2, etc. But in cases like this where it isn't quickly obvious what is going on with those loops, it may make sense to reconsider this rule: for instance, Counter1 and Counter3 could be renamed to PrimeCandidate, and Counter2 to Factor to make the code more 'self-documenting'.