ACS Documentation : ACS Engineering Standards : General Coding Standards
Experience shows that it is easier to develop code in large teams if people all follow a few standardized practices when writing code. Standards make code easier to read, and in general make a system easier to maintain because you don't have to spend time fighting with the strange coding ticks of 100 different people.
The tradeoff is that any given set of coding standards usually reflect the strange coding ticks of the single person or the small group of people who actually write the standards. People may complain that this will limit their own creativity, but this isn't really the case. Coding standards deal with the mechanical aspects of programming as opposed to anything that is really important. Therefore, it's not so important that the standards be "right" as much as it is that they be standard.
Here are some example coding standards documents I found on the net. While they seem to be specific to certain languages or environments, they all contain general ideas that are applicable anywhere. I include them here to give you an idea of the level at which standards are specified and applied.
The first rule for all code, and everything else, is that it be in CVS. Nothing that you work on, no matter how temporary, should be a plain file just sitting somewhere that is not version controlled in some way. Here are some basic guidelines:
Again, everything you touch should be in CVS. Go read this tutorial to know why.
Every file should have a CVS Id tag, like this:
$Id: foo.java,v 1.6 2000/11/20 18:36:00 psu Exp $
This is the most compact and most convenient way for people to know who last changed the file and when they did it. Standards for how to get this string into a source file depend on what kind of file it is. See the specific standards docs for Tcl, HTML, SQL and Java code for more details.
Never use ftp, copy, cp, tar, unzip or scp to copy file trees to a CVS
work area. Always make your own private work area using cvs
checkout and put the files there, then add them, then commit
and update.
Try to leave behind nice commit log messages so people know what you are doing. Commit log messages like this are pretty useless:
fixed bugs
Commit log message like this are better:
Fixed bug #5067 in the SDM. Had to change how the package logs user activity with some extra fields in the data model to store more information that we didn't realize we needed.
Making CVS send mail to you whenever people check in is insanely useful. Here are some things it does for you:
The incoming mail stream gives you an instant snapshot of who is
changing what in the code. It's hard to get this from cvs
log because it only provides you with a file by file view.
All ACS 4.0 related checkins are logged
to a bboard. Take a look at it to get an idea what you can learn.
If you make a lot of branches for releases or daily builds, the mail alert will tell you instantly when people are commiting code to the wrong place. This saves a lot of integration time later.
When people check in code that they weren't supposed to touch, or commit changes to major subsystems without notifying people or appropriate reviews, you find out and can yell at them.
If you archive the e-mail, this is as close as you will come to a real transaction log on the CVS repository. Changes that are all part of a single commit tend to be grouped together and have similar log messages. This is handy when doing release integration.
If you do a checkout and suddenly everything is broken, the checkin log can give you clues as to who the culprit is. You can use cvs log for this too, but it's hard to get good information on a large tree.
Follow the following general rules about file format:
No line of text in any text file containg code, HTML, or anything else meant to be read or edited by a human shall be longer than 78 characters.
This means that you must make sure that your text editor of choice must be configured to drop a newline into the file every 78 characters or so. Paragraphs that are all on a single line with no breaks are no fun to edit.
The reason for this limit is mainly that for whatever reason, windows that are around 75 to 80 characters wide are the most convenient size to use for editing code. Usually, larger windows are too wide to be useful or require that you use fonts that are too small. Also, most screens these days allow you to put two 80 column windows side by side on the screen for convenient comparison. Secondly, lines that wrap gratuitously are hard to read and hard to edit. Therefore, it makes sense to have an explicit standard to limit line width. My experience has shown that it makes life easier for everyone.
(setq-default indent-tabs-mode nil) ; to play nice with the windows editor
This tells emacs to never actually insert tab characters into your file, and to always pad out space to the next tab stop with spaces. This means that the file will be easy to edit no matter how wide a particular editor thinks a tab should be. This is important because while emacs thinks tabs move the cursor to 8 space boundaries, windows and other editors think the width should be 4. Using spaces instead of tabs makes it possible for us not to worry about this, so it's a good thing to do.
if foo {
code; code; code;
} else {
code; code code;
}
I prefer to always use braces even if the code block only contains one line of code. This is a win in most situations, but can be verbose.
This particular style for braces is my own preference. Other people disagree. I find it to be the best compromise between compactness and readability.
For example, in a long if statement:
if (cond1 && cond2 && cond3 &&
cond4 && condition_p(foo, bar, baz, blat,
hello, world)) {
code;
code; ...
}
Naming is important because the basis for all programming is giving a good name to an abstraction to make it easier to use. Try to follow these rules fo thumb for making up names in your code:
foo, bar, and so on. Avoid using any single
letter name for something that is not a loop index. Gratuitously long
names are things like:
ad_check_cybercash_status_and_abort_transaction_if_user_was_rejected
Any time a name is more than three or four words you are probably working too hard.
Avoid useless placeholder names like
MungeStuff. Often, procedures or functions operate on
particular objects. A good rule of thumb for such procedures is to
name them using an "object-verb" format. This is particularly
important in tcl, since the language has no types, and this may be the
only way you have some clue as to what kind of data a particular proc
is expecting.
In Java, this isn't as critical, since methods are generally attached
to the objects they operate on, so calls are automatically in a form
like: Object.method(arg1, arg2, ...).
The language specific coding standards document will cover naming in more detail.
File names for files that are user interface pages should also follow
a "noun-verb" format where appropriate. Often, the noun or the verb
will not be included if they are obvious from the context. So, for
example, the file name of the page that allows a user to erase a
user's portrait from the database is portrait-erase.tcl.
On the other hand, the page that edits a single bookmark might be
called bookmark/www/edit.tcl. It is clear from the
context that this page is in the bookmarks package, so it would only
be dealing with bookmarks. Finally, use the "one" convention for
naming files that display an object whose type is clear from the
context of the file. So the page that displays a single bookmark might
be called bookmark/www/one.tcl.
The packages
tutorial outlines file naming conventions for packages. Right now
this document only specifies conventions for data model and
.tcl files, but the Java conventions will be similar.
Files that form a sequence or flow of pages should be named using an explicit sequence number:
foobar.extension (Step 1)
foobar-2.extension (Step 2)
foobar-N.extension (Step N)
This kind of scheme makes the page flow explicit, and can also give the savvy user a clue as to where she is in a particular work flow by examining the URL.
If you use emacs, consider using M-/ to make
d-abbrev expand long names for you. You can also bind
M-/ to hippie-expand for even more
aggressive auto-completion.
The general rule here is to only use comments to clarify aspects of the code that are not immediately obvious. This is, of course, a subjective matter. Assume that a high level description of how the package is put together is available as a requirements or design document and so you don't have to explain those particulars in your code. On the other hand, if you use some incredibly clever algorithm or coding trick that is not discussed in the design, that would be a good thing to talk about.
Avoid comments that are gratuitously obvious:
int index; /* index variable */
or
create table foo (
id integer,
-- the ID of the foo thing
...
Comments like this just take up space and make the code harder to read without providing any useful information. On the other hand:
context_id integer, -- the default domain from which an object may inherit -- permissions. see the permissions design document -- for details.
is a pretty good comment because it isn't immediately clear what
context_id is for. The name is little bit generic and
could be improved (see above). But lacking that, pointing the reader
of the code to the right place to find a lengthly explanation is a
good thing to do here.
Use short comments to describe particularly clever pieces of code. Good candidates for this sort of thing include:
Use inline comments for short notes, but for longer pieces of exposition, use block comments that are separated from the code by blank lines.
Pete Su Last Modified: coding.html,v 1.1 2001/01/21 01:49:07 bquinn Exp