Home User Manual Discussion Forum Search

Coding Style 

The code for Open Dental has a coding style which should be followed by all programmers.

Strict Rules

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.

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

Boilerplate Code
See the Boilerplate Code page. Use it.

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 Boilerplate Code when creating grids.

If there's text that is guaranteed to only be used by users of a single language, such as e-claims, 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, all 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
If you are using any SQL, then you must take the time to learn the Oracle compatibility rules. Failure to follow those rules will cause the program to crash in Oracle even though it runs well in MySQL.  You probably won't be able to test it in Oracle, but it should still be written so that it has a very high chance of running successfully the first time an Oracle user tries it.

Suggested Guidelines
These are not strictly enforced, and are only meant to provide consistency. Try to learn the preferred coding style, and try to use it wherever possible. But it's not critical enough that we will force you to rewrite. Speed of programming is more important..

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 rare to omit braces, but it is sometimes done when there is only one line within the braces, and the code is unlikely to change.  But beware that this can cause bugs that are hard to spot if you later add a second line and forget to also add 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 reformats when pasting, and eliminates our spaces. So while we would prefer to use spaces to form columns, it's not feasible until MS fixes that "bug".

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>
It should all be on one line with no wasted whitespace. If it's 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.  Use correct capitalization, spelling, and punctuation including a period on the end. A summary is not required, but is generally 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 1600 pixels and a toolbar docked on the right.  This results in a workspace of about 130 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.  If a method declaration extends past this due to a long argument list, then usually a manual break is inserted near the 130th column, tabs are entered to get to the position one indent from above, and the declaration is continued.  In conclusion, it's a bad idea to let anything except summaries extend past 130 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-866-239-0469