Home User Manual Discussion Forum Search

Coding Style 

This coding style is followed by our programmers.  It's mostly an internal document, but others may find it interesting.

Indentation
Use tabs, not spaces.  If spaces are used, it's very inconventient if later editing the code.  Be very precise about all indentations.  The only exception to proper indentation is when using a procedural language like OpenGL from within C#.  In that case, it's ok to indent the logical sections even though it's not technically correct. Within lines of code, use spaces rather than tabs.

To set VS to use tabs rather than spaces, go to Tools | Options.  Go to the Text Editor category, C#, Tabs.  Make sure that the Tab groups has Keep Tabs checked instead of Insert Spaces.  If you are using C# Express Edition, and you don't see the "Tabs" group under Text Editor, C#, look down a little bit and find the checkbox to show all groups. The "Tabs" group will then be visible.

Other options to change in VS:
* Windows Forms Designer, General, Refactoring, EnableRefactoringOnRename: false. This is because if you make a copy of a form, and then rename it, it will also rename the original form.
* Text Editor, C#, Formatting, New Lines: Only else,catch, and finally should be on new lines.
* Text Editor, C#, Formatting, Spacing: Uncheck all boxes. At the bottom, select "ignore spaces around binary operators".

You may use this settings file if you would like to quickly set VS to the preferred settings. DefaultODSettings.zip Save it to your computer and extract. Then import the file inside from Tools, Options, Environment, Import and Export settings.

Patterns
See the Patterns page. ALWAYS USE PATTERNS IF AVAILABLE.

Language Enabling
It's absolutely essential that every single bit of displayed text be enabled for language translation by getting routed through the Lan class before display. For almost all static text on a form, this is handled by adding this line
Lan.F(this);
in the form constructor, usually right after InitializeComponent(). Lan.F handles Form.Text (title), labels, buttons, groupboxes, checkboxes, and radiobuttons. But it does not include textboxes with static text in them, menus, etc.  Those all need to be handled by manually calling Lan for each one.  MessageBox's are handled one of two ways.  If the text is static, then you can use MsgBox, which is a class we built to simplify things.
MsgBox.Show(this,"Hello World.");
But if the message is dynamic in any way, then it needs to be done without MsgBox, more like this:
MessageBox.Show(Lan.g(this,"Your name is ")+patient.LName);
In the example above, only the first part of the phrase gets sent for translation. It's very important to understand why it's done like this, and that you would never send dynamic text to get translated. In the example above, there is also a space between the translatable portion of the phrase and the dynamic text.  This is commonly handled by sending it off for translation, just like in the example.  But you probably don't want to send off too many spaces to translate, especially if they are initial spaces.  So it's also common to chain text together without sending the spaces.  Like this:
MessageBox.Show(Lan.g(this,"Your name is")+" "+patient.LName);
Or like this
MessageBox.Show(String.Format(Lan.g(this,"Hi {0}, how are you?"), patient.FName);

Grids of type ODGrid must have their TranslationName property set so that the grid title can be automatically translated. Each column in a grid must also be manually enabled for translation. Use the Pattern when creating grids.

If there's text that is guaranteed to only be used by users of a single language, such as e-claims or forms, then it's not necessary to worry about translation.  Also, the tables and columns in the database all use English naming.  So for some reporting purposes, they will not be able to see the words in their language.  This is currently a problem in letter merge and the patient report, where the user must select fields in English.

The category of each phrase is either the name of the form (that's why we pass in 'this'), or a manually assigned string.  We try to keep these categories very consistent and not change them over time.  So for historical reasons, many grids have TranslationNames starting with Table... 

You also have to make space on each form for translations, many of which will be longer than the English version.  All buttons are special OD buttons.  Never use a standard System button anywhere.  The OD buttons automatically expand to the right when the text is too long to fit.  If the button is right anchored, it will expand to the left instead.  You have to anticipate this and leave space for every button to expand.  You also have to make labels about twice as large as needed so that they can hold longer text.  The AutoSize property of all labels, radiobuttons, and checkboxes must be set to false.  The text alignment must be carefully considered so that it will still be aligned nicely if the text is longer.

Oracle Compatibility
No longer applies.  If you are curious, you can see the old Oracle compatibility rules. They are so convoluted that we were eventually forced to abandon them.

General
Blank lines: Never leave blank lines within a method. Always leave one blank line between each method.
Braces: Opening braces should almost always be on the same line as the method name.  Closing braces are usually on a line all by themselves.  It would be very rare to omit braces, even if there is only one line between the braces.
Get-Set: Within properties, these can be real space wasters.  This is one situation where it's just fine to put it all on one line, like this:
///<summary></summary>
public bool Autosize{
  get{return autosize;}
  set{autosize=value;}
}

Columns: It is sometimes useful when using a courier font to create virtual columns for better readability of repetitive code. We made heavy use of this technique in VS2003, but VS2005 always reformatted when pasting, and eliminated our spaces. So the use of columns fell into disuse.  If columns are intentionally created, you must use spaces instead of tabs (except the leading tabs, of course).

Comments
Make good succinct comments.  Most comments will be in the summary above each method so that it can be seen when using intellisense.
///<summary>Used when jumping here from another module.  Make sure not to pass in a value of 0.</summary>
In the past, we required it to be all on one line with no wasted whitespace.  We now also allow the summary style that is auto-generated summary when typing a triple slash.  It looks more like this:
/// <summary>
///
Used when jumping here from another module.  Make sure not to pass in a value of 0.
/// </summary>

If the comment is very long, it will just wrap around, and that's fine. In table and table.field comments, do not use any other XML tags other than summary because they will not be picked up for documentation.  It's ok to leave extra XML tags, but preferrable to remove them.  Use correct capitalization, spelling, and punctuation including a period on the end. A summary is not required, but is sometimes very useful, especially for public methods.  Even if no summary is needed, an empty summary is frequently included to help visually identify where the method starts.  Ordinary comments that start with // within a method should be placed to minimize whitespace.  A short comment should go on the same line as the code, while a longer comment should go on a separate line.

Very Long Methods
Try not to write a method that is too long, more than a few pages tall. It becomes very difficult to keep track of where you are in the method, and to quickly navigate to the section you are looking for. If you end up with a very long method you have three options:
1. Break it down into a series of smaller methods, each performing a single task of limited scope.
2. Use #region tags to surround sections that are not used very often. These will start out collapsed, so they are useful for tucking away rarely used code.
3. If it doesn't make sense to collapse a procedure with #regions, and it's more orderly and logical to leave it all in one procedure, then use comment lines to create subsections, like this:
//Paint the horizontal lines------------------------------------------------------------------------------------
Notice the heavy use of dashes. They should extend nearly all the way to the right margin.  There should be approximately 2 of these subsections for every page of code.  Of course, this will vary.

Width and Wrap
Use as much horizontal width as possible. Most code over the last few years has been written on a monitor with a width of 1920 pixels and a toolbar docked on the right.  This results in a workspace of about 150 columns.  As much of this space as possible should be used.   Comments (except ///summaries) extending past this are usually manually broken down into two lines.  Method declarations with a long argument list can extend past 150 and automatically wrap.  But anything other than summaries and method declarations should not extend past 150 columns because the resulting wrap is distracting.

SQL
If an SQL statement within the C# code is more than a couple of lines, it is common to start it with @" so that you can use multiple lines without each line having to be surrouned with +"...".  Regardless of where SQL statements are found, there is a common style that needs to be followed.  There should be no blank lines, except possibly between statements in a batch command (after a semicolon).  All tablenames are always lowercase so that they will function properly on a default Linux installation.  All column names should be mixed case, just like they are in the documentation.   All SQL functions and keywords should be all caps.  AND should be used instead of &.  There should be no indentation except in a CREATE TABLE statement, where many of the lines get indented by two spaces.  Each clause of the statement (FROM, WHERE, etc) should start on its own line even though this is not the most efficient use of whitespace.

 

Open Dental Software 1-971-239-1150