|
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.
|