\space 20
\CENTER on
TURBO PASCAL CODING CONVENTIONS

(mine 12/24/93)
\space 20

\CENTER off

                                           Howard Richoux
                                           6721 Shamrock Rd.
                                           Lincoln, NE  68506-2821
                                           (402) 488-5867
\new
\footer1 '@date|Turbo Pascal Coding|Page @page'
General
\join 72

     I have been programming for close to 25 years, on a variety
of machines in a variety of languages.  Programmer support tools seem
to lag far behind the language, appearing only when the machine or language
is about obsolete.  I am particularly peeved with text editors.  The
needs have changed little over the years, but command names and syntaxes
require constant retraining of fingers.

     I am not fanatic about coding standards, although, I find it
very difficult to study code which doesn't conform to my own conventions.
I am willing to be persuaded to adopt any or all standards IF:
\join off

     1. It doesn't require a lot of extra typing.
     2. A utility is provided to convert non-conforming code to
          the standard. (Not just a pretty listing).

\join on
     Pascal coding conventions can be divided into (at least) two groups.
General program construction practices and formatting rules.  The program
construction practices include file naming, directory organization,
code library/unit use and use of global variables.  Formatting rules would
cover comments, indentation, capitalization and the layout of
procedures within a file.

     Many conventions are historical in nature, based on earlier
limitations of hardware or compilers.  Sometimes it is easier to maintain
the standard than to recognize that it is no longer needed.  A few things
to consider are:
\join off

1. TURBO Pascal has been around since the days of the 8088 and the 10 Mbyte
     disk.  Between the improvements in the compiler and the hardware,
     compile speed has increased by at least a factor of 100.

2. The invention of the Unit is one of the great contributions to programming.
     They can be compiled separately and linked intelligently, allowing code
     to be placed in logical groupings with almost no penalties in compile
     time or program size.

3. Borland's implementation of Objects is another major step forward, but
     I have not adapted fully to the paradigm shift.  I use them frequently,
     but probably not completely correctly.  I view them more as extensions
     to the Unit concept rather than as a religious experience.

4. Code was meant to be shared.  There are enough programming jobs left to be
     done that we shouldn't need to hoard our resources.  All of the general
     work I am doing is placed in the PUBLIC DOMAIN.  Feel free to borrow,
     modify, plagerize and utilize it.  All I would request is a footnote
     in your documentation and/or the placing of some of your code into
     the public domain.

\new
Program Construction - General
\join on

     Some of the programming conventions are forced on us by the
limitations of the language/compiler.  Variables and Procedures need to be
declared before they are referenced.  Some are imposed by the operating system.
Fiel names can only be 8 chars with a 3 char extension, 'pas' means
pascal source file, etc.

     In no particular order, here are some thoughts (Remember, I don't
claim I follow all of them to the letter):
\join off

1. Minimize the use of global variables.  It is too easy to reference them
     or modify them in another part of the code.  The penalty of stack use
     and hence execution time is normally minimal, and is dwarfed by
     improvements in hardware.  If globals are needed, hide them in Units
     or objects where the scope is at least limited.

2. *CONTROVERSIAL*  Minimize the use of COMMENTS in code.  Contrary to
     conventional wisdom, I have found that commenting the obvious is
     of no help later on, and the sheer mass of characters obscures the
     code structure.  I have found that a large block of comments near
     the beginning of a unit can document the use of variables without
     obstructing code later on.

3. Instead, Name your variables wisely.  Properly chosen names can make
     the code read well and self-document.  I tend to favor mixed capitals
     for variable names with the capitals at the start of words within
     the names such as "PrintFlag" and "DecodeString".

4. Indentation can drive a stranger crazy.  I can't even read code that
     looks like:
           IF x = 3 then
             begin
               DO WHILE i < 22
                 begin
                   z := 4;
                 end;
             end
           else
             begin
               b := 1;
             end;

      Some people swear by it.  ( I'm not sure I have the bad example right,
      but the main feature is a snakey, constantly changing indentation.)
      I use:
           IF x = 3 then
                begin
                DO WHILE i < 22
                     begin
                     z := 4;
                     end;
                end
           else begin
                b := 1;
                end;

      With a level change of 4 or 5 spaces, code on the same lexical level
      stands out, making it easier to spot unmatched begin/ends and other
      syntactical problems. The objection I've heard to 5 char indentation
      is that you run out of room on the right side of the line.  My answer
      is that in most cases, if you have to indent 4 or 5 levels, the
      procedure should probably have been broken down into multiple procedures
      anyway.

5. I can live with most combinations of upper and lower case letters, as long
      as it is reasonably consistant.  I have seen good use of capitalization
      of language elements, lower case variables and also the opposite.  I
      came from the punch-card all capitals world, went to a religiously
      all lower-case shop and wound up muddled.  Over-use of upper case is
      hard on the eyes without contributing much information.

6. One of the most useful and hardest conventions to do well is to name
      variables, functions and procedures in such a way as to have the
      name imply its origin and/or use.  If all of your global boolean
      flag variables are named xxxxFlag then it is much easier to
      read " If PrintFlag then ...".  I tend to make symmetric functions
      and procedures, even when I don't need the reverse operation at present,
      just so it will be there later.  So, if I convert integer to string
      with IntegerString, I will code, or at least mentally reserve procedures
      for RealString, StringInteger for later.  This also allows me to see
      if the syntax is obvious, or at least straight-forward.

7. The single hardest coding function is CHANGE.  When libraries have
      been built up and 20 or 30 programs are using them, how can you
      rename a low level procedure?  This is a problem with no easy
      solution.  Some of it can be avoided by naming well early.  Some
      can be avoided by hiding functions inside units and objects.  Some
      can be fixed by good coding tools search and replace text processors
      and the like.   The problem is magnified greatly with multiple sites.

\new
Program Construction - Detail

     The following is a list of recommended procedures.  I will try
to use them in my code.  They may not be good for all people, but
they work for me.

\join off
Variables.

  1. Use as few global variables as possible.

  2. Reserve one and two character names for temporary type variables
      A procedure should declare them locally.  Global temporaries cause
      no end of trouble because the contents are uncertain.
       var s,s1,s2 ... : string;
           i,j,k       : integer;     { an old FORTRAN hold-over}
           b           : byte;

  3. Except for very specific uses, don't bother with specific length
      strings.  Var ext : string;  for holding file extensions is a
      waste of 250+ bytes of data space, but the alternatives of
      creating a   type ext_string = string[3]; causes pains in
      parameter passing and declarations(what did I name that file
      extension type? "extstring"? "type_ext"? ...)  Simply declaring
      variables string[3] is a real disaster when you want to change it
      to string[4].

      It is worth noting that use of objects tends to move a lot of data
      space onto the heap which is much more plentiful.

  4. Choose variable names such that the code which uses them can be
      read out loud.  "DO PlaceStringOnHeap(s) until ...;" Reads better
      than "DO HeapString(s) until ..."

  5. Conversely, use of 3 or 4 descriptive names in a single statement
      can be very hard to follow, even though technically correct.
        "If (IndexMaximum > NumberofDataItems) then IncreaseSizeofDataArea;"
      reads like a ton of bricks.   "NdxMax", "DataCnt",  and other frequently
      used shortcuts are no less readable, and save typing and spelling
      errors.  The trick is to always use the same shortcut for the same
      word.

  6. The world needs to agree on the meaning of a few terms, then use
      them appropriately.  One man's "indent" is another woman's "offset"
      or "margin" or "leftmargin" or "pad" ...  This winds up being critical
      for providing run-time options for utility programs.  One way to
      solve this is to have the library provide "free" decoding for
      a host of standard options.  It then becomes much easier to use
      the provided options rather than code your own support.

  7. Write your code such that 50+% of it is re-useable.  EVERY program
      should contribute at least one routine to your library.  Primarily
      this breaks down to taking one step back when coding and separating
      the exact problem you are attempting to solve from the more general
      methods you are using to solve it.  For example, if you need to
      decode a string which looks like "xxxxx(yyy)" into the x and y pieces,
      write the routine to pass the delimiter pair as arguments (or
      global variables, or compile time constants), and name the routine
      such that you know that the function is general.  Spend an extra 10%
      of time adding error checking code and then the next program will
      have a "free" component.

      The cost of this (there is ALWAYS a cost) is most probably run-time
      efficiency.  Generalized code will not be quite as tight as code
      which solves exactly the one specific problem.  It has been 15-20
      years since the cost of hardware was more important than programming/
      debugging costs.  Hardware seems to improve by a factor of 2 every
      year, programmers pick up maybe 10% per year from better tools and
      experience.  My vote is - when given a choice between ease of coding
      and speed of running, take the coding and go back and optimize later.
      Chances are, you won't need to.