wiki:standards

Programming Standards

This page is meant to document programming standards for the UTHSCSA Ultrascan systems. It applies to C, C++, html, php, javascript, and other similar procedural programming languages. In some cases, the standards below may not apply to specific languages, but programmers should try to follow the standards when practicable.

When coding, always remember that the audience of the code is twofold. The first audience is the compiler or interpreter of your code. That tool will tell you when you make an error when you test it. The second audience is the maintenance programmer who is trying to fix a problem or create an enhancement. It may be you as the original coder six months form now or it may be someone else that is not familiar with the application at all. Unfortunately, there is very little feedback from that person who works with your code some time in the future. Each programmer must pay attention to the style of the code as well as the function to create robust and maintainable software.

Source Files

All source files names shall be 16 characters or less in length to ensure compatibility with older UNIX file systems. Source files containing functions shall have an extension of ".c" for ANSI C and ".cpp" for C++ source files. All other "include" files shall have an extension of ".h". php files must have an extension of ".php'.

The top of each source file shall contain a header giving the name of the file, the purpose or nature of the source file, the copyright and licensing notice, and the functions contained in the file. The file name and revision information is provided by the Subversion "$Id$" tag:

/*
 * "$Id$"
 *
 *   Description of file contents.
 *
 *   Copyright 2007 by Apple Inc.
 *
 *   These coded instructions, statements, and computer programs are the
 *   property of Apple Inc. and are protected by Federal copyright
 *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
 *   which should have been included with this file.  If this file is
 *   file is missing or damaged, see the license at "http://www.cups.org/".
 *
 * Contents:
 *
 *   function1() - Description 1.
 *   function2() - Description 2.
 *   function3() - Description 3.
 */

The bottom of each source file shall contain a trailer giving the name of the file using the Subversion "$Id$" tag. The primary purpose of this is to mark the end of a source file; if the trailer is missing it is possible that code has been lost near the end of the file:

/*
 * End of "$Id$".
*/

Functions

Functions with a global scope shall have a lowercase prefix followed by capitalized words ("usDoThis", "usDoThat", "uDoSomethingElse", etc.) Private global functions shall begin with a leading underscore ("_usDoThis", "_usDoThat", etc.)

Functions with a local scope shall be declared "static" and be lowercase with underscores between words ("do_this", "do_that", "do_something_else", etc.)

Each function shall begin with a comment header describing what the function does, the possible input limits (if any), and the possible output values (if any), and any special information needed:

/*
 * 'do_this()' - Compute y = this(x).
 *
 * Notes: none.
 */

static float                            /* O - Inverse power value, 0.0 <= y <= 1.1 */
do_this(float x)                        /* I - Power value (0.0 <= x <= 1.1) */
{
  ...
  return (y);
}

Return/output values are indicated using an "O" prefix, input values are indicated using the "I" prefix, and values that are both input and output use the "IO" prefix for the corresponding in-line comment.

Functions should be limited to 100 lines or less. In some cases, very linear, repetitive code can exceed this guideline, but factoring to shorter functions would always be preferable.

Files should be kept to less than 1000 total lines.

Variables

Variables with a global scope shall be capitalized ("ThisVariable", "ThatVariable", "ThisStateVariable", etc.) Global variables shall be replaced by function arguments whenever possible.

Variables with a local scope shall be lowercase with underscores between words ("this_variable", "that_variable", etc.) Any local variables shared by functions within a source file shall be declared "static".

Each variable shall be declared on a separate line and shall be immediately followed by a comment block describing the variable:

int this_variable;   /* The current state of this */
int that_variable;   /* The current state of that */

Definitions of pointer variables shall have the asterisk adjacent to the type and not the variable name. This is to group the definition components, type and name, properly. The asterisk is a part of the type, not a part of the name. For example use

char* string; /* Temporary string */

and not

char *string; /* Temporary string */

As an aside, the unfortunate use of the 'char *var' structure is an artifact of the K&R C book where the development of C was done on a printing terminal and the use of vertical space and scrolling up was awkward. The modern use is demonstrated in Stroustrup's C++ book.

Variable names should generally be limited to 12 characters or less. This is to aid the visual comprehension of the code as the variable name expresses a thought and the eye is required to move more than once on wide words when viewed at common font sizes.

Types

All type names shall be lowercase with underscores between words and "_t" appended to the end of the name ("us_this_type_t", "us_that_type_t", etc.) Type names must start with a prefix, typically "us" or the name of the program, to avoid conflicts with system types. Private type names must start with an underscore ("_us_this_t", "_us_that_t", etc.)

Each type shall have a comment block immediately after the typedef:

typedef int us_this_type_t; /* This type is for Ultrascan foobar options. */

Structures

All structure names shall be lowercase with underscores between words and "_s" appended to the end of the name ("us_this_s", "us_that_s", etc.) Structure names must start with a prefix, typically "us" or the name of the program, to avoid conflicts with system types. Private structure names must start with an underscore ("_us_this_s", "_us_that_s", etc.)

Each structure shall have a comment block immediately after the struct and each member shall be documented in accordance with the variable naming policy above:

struct us_this_struct_s               /* This structure is for Ultrascan foobar options. */
{
  int this_member;                    /* Current state for this */
  int that_member;                    /* Current state for that */
};

Constants

All constant names shall be uppercase with underscored between words ("US_THIS_CONSTANT", "US_THAT_CONSTANT", etc.) Constants must begin with an uppercase prefix, typically "US" or the program name.

Typed enumerations shall be used whenever possible to allow for type checking by the compiler.

Comment blocks shall immediately follow each constant:

enum
{
  US_THIS_TRAY,                       /* This tray */
  US_THAT_TRAY                        /* That tray */
};

Code

All source code shall utilize block comments within functions to describe the operations being performed by a group of statements; avoid putting a comment per line unless absolutely necessary, and then consider refactoring the code so that it is not necessary:

/*
 * Clear the state array before we begin...
 */

for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
  array[i] = STATE_IDLE;

/*
 * Wait for state changes...
 */

do
{
  for (i = 0; i < (sizeof(array) / sizeof(sizeof(array[0])); i ++)
    if (array[i] != STATE_IDLE)
      break;

  if (i == (sizeof(array) / sizeof(array[0])))
    sleep(1);
} while (i == (sizeof(array) / sizeof(array[0])));

Indentation

All code blocks enclosed by brackets shall begin with the opening brace on a new line. The code then follows starting on a new line after the brace and is indented 2 spaces. The closing brace is then placed on a new line following the code at the original indentation:

{
  int i; /* Looping var */

 /*
  * Process foobar values from 0 to 999...
  */

  for (i = 0; i < 1000; i ++)
  {
    do_this(i);
    do_that(i);
  }
}

Embedded tab characters should never be used in source code. Editors can be set to automatically convert input tab characters to spaces. For example the ~/.vimrc file can have the following:

set expandtab
set tabstop=2
set shiftwidth=2

Single-line statements following "do", "else", "for", "if", and "while" shall be indented 2 spaces as well. Blocks of code in a "switch" block shall be indented 4 spaces after each "case" and "default" case:

switch (array[i])
{
  case STATE_IDLE :
      do_this(i);
      do_that(i);
      break;
  default :
      do_nothing(i);
      break;
}

Spacing

A space shall follow each reserved word ("if", "while", etc.) Spaces shall not be inserted between a function name and the arguments in parenthesis.

Spaces should be used after commas and other punctuations such as equal signs, etc.

Similar structures should be lined up for visual symmetry. For example:

  var1       = 3;
  variable2  = 4;
  other_var  = "A string";
  count     += 2;

Line lengths

Code lines should end at approximately column 80 or less. HTML, including HTML output by languages such as php should also be limited to approximately 80 characters. This standard is to prevent horizontal scrolling in windows like a browser's "Show Source" and to prevent line wrapping in support tools like a2ps that print two or more pages of code on a single sheet of paper.

Return Values

Parentheses shall surround values returned from a function using "return":

return (US_STATE_IDLE);

Loops

Whenever convenient loops should count downward to zero to improve program performance:

for (i = sizeof(array) / sizeof(array[0]) - 1; i >= 0; i --)
  array[i] = US_STATE_IDLE;

HTML Validation

HTML files and HTML code generated by other languages such as php must be validated for proper syntax using the W3C Markup Validation Service at http://validator.w3.org/. In many cases, it will not be possible to test html pages by URL address due to form input requirements. In that case, the results from an output page's 'View Source' must be pasted into the validation service's Direct Input capability.

XHTML 1.0 Strict or XHTML 1.1 is required for all web pages.

Last modified 12 years ago Last modified on Oct 29, 2007 4:45:45 AM