FORCES Programming Conventions
The following programming have been adopted in JFORCES over the years:
1) All code should be written in JFORCES Pseudocode
2) All code files SHOULD have:
Header defining the purpose of the file
3) Each code procedure SHOULD have
4) Variable name convention
5) Introduction to Code Autogeneration
What is JFORCES Pseudocode?
FORCES Pseudocode is a simple form of pseudocode that incorporates only the following four constructs:
1) Sequential processing
2) Conditional Programming Via If/Then/Else/elseif branches
Note that the words of each line are indented to the same level. That is the "i" of the if statement is aligned with the t of the then statement, which is aligned with the e of the else statement, and so forth. This greatly aids reading the logic later. All lines of an if/then/else construct MUST start with "if", "then", "and", "else", "else if" or "end if". If the comments are indented (as are those starting with the word "do") they are understood to all be part of the component of the statement that's currently being evaluated (i.e. part of the "then" statement in this case.)
Note that ONLY 2 asterisks are allowed within this construct - one at the beginning of the constuct and one at the end. The purpose behind this is that the asterisks indicate the beginning and end of a self-contained code segment and that if all code is removed from between the lines indicated by asterisks (including these lines) then the code should still be functional and compilable, though probably not giving correct results. It is OK (and probably required) to have asterisks within subsegments, as illustrated above with the conditional statement starting "* if the asset is an aircraft", but these subsegments should be indenting accordingly.
Also note that sequential processing and embedded conditional & loop processing is supported within the
3) Conditional Programming Via Case Statements
Note the similarity in indentation and use of asterisks to the if-then-else structure, as described above. See the description of these in the above comments. Notice also the the case condition (and the if condition in the above example) is repeated at the close of the code segment. While this is not required by the JFORCES pseudocode standard, and is often omited for short segments, it can be very useful to programmers maintaining the code later and so is highly recommended for long segment.s
4) Loops (this includes loop while, loop until and so forth)
At this point there's so much code written with embedded
pseudocode that we would want to preserve this approach just for
consistency. But we've also found this pseudocode to be excellent at
incorporating reasonable comments within our code at the point most
helpful for future programmers. Basically we've found that from these
four constructs we can specify all programming methods within a
structured language or structured code snippet. Furthermore, by
incorporating the pseudocode directly into the code we:
Pseudocode Extraction Procedure
The princple reason that the pseudocode was selected as the documentation standard in early in FORCES development is that pseudocode satisfied the C-spec programmer's documentation requirement. But it could do this only if the pseudocode could readily be extracted and delivered to the customer. Therefore the "countlines" procedure was developed. The reason for naming this procedure "countlines" is that it provided lines-of-code counts for review by managers. Editorial comments withheld. Work was being performed across multiple operating systems, so of necessity the countlines program was kept very naïve.
Countlines primary weakness at this time is that it only works on Fortran. We believe it will be extended to C and TCL in the future, and this is one of the reasons that programmers should always keep the beginning of their pseudocode comments on column 1.
To use countlines a file named "codelist" needs to be created. It will consist of this files that you want to extract the code from. For example, to extract code from all of the fortran files in the ~sim/c2 directory type and start the extraction process type:
cd c2; \ls -l *.F > codelist; countlines
You'll be notified that the following will be extracted:
The first output is the only output we care about here. For every filename in codelist an output file named (original_name)d will be created and will contain the embedded pseudocode. For example, if the original name is addc2asset.F the embedded pseudocode will be put in addc2asset.Fd. A file named addc2asset.Fp will also be generated - this is a "Beautiful" version of the original code. In this version all comments are in uppercase and all non-literal codelines are in lower case. We no longer use this file (and it does not correspond to our current capitalization standard) so please discard these files.
Assuming that you don't ask for more information about these options, you'll be asked whether any lines over 72 characters should be echoed to the screen. This is useful only if youre converting Fortran code to a machine that can't handle extended lines. Generally you should answer "n". At this point the program should output lines-of-code information to the screen, for example:
Filename Executable LOC LOC over 72 char
The documentation files are automatically created. To see the documentation file that was extracted from the Fortran example click here .
Information headers in Fortran and C Code
All code files should incorporate the following information:
1) The purpose of the file. This should be the unifying theme that caused the programmer to combine all of the embedded procedures into a single file. Click here for an example.
2) The data and definitions section. If the data and definitions are used only in one file I tend to incorporate them directly into the file instead of creating a stand-alone header file. If the data and/or definitions are used by multiple files then a header file is created in the ~/common directory. For example, the route structures defined in route_struct.h is included by both ~/sim/objutil/route.c and ~/sim/objutil/motion.c. So a single header named "route_struct.h" was created in the ~/common directory. All applications link to files in this directory. By convention, when the data embedded in the header file is used in a number of source files we just include the header in the application header file (e.g. sim.h, wn.h or rcvr.h). There is at least one file that is included in all of the application headers named common_prototypes.h. Put function prototypes for functions that might be used in any of these applications in this file.
At the top of every procedure within a file always specify the purpose for the procedure. See the C source code example . Note that these key components of the documentation are separated from the major code components by comment lines. These are:
These separators should only be used for the major structural elements (the file purpose, the common data & definition section, and the purpose for every procedure in the file). By limiting these separators to these sections code can quickly be scanned for individual procedures.
When writing Fortran we've found that it's simplest if each file contains only one routine. Thus the file purpose and the procedure functionality description can be collapsed - see example .
The inputs and outputs of every file should be documented. Typically we use the procedure header to document the output in C and use inline documentation for any arguments, as follows:
For Fortran this won't work, so instead we document the variables on comment lines, as follows:
The size would be the array size where appropriate.
Finally, TCL does not permit inline commenting, so we should use a system like we use for Fortran, as follows:
In practice only the most heavily used TCL routines follow this practice, but it's the task of every programmer to update this information as the code in maintained and to document all new routines to this standard.
Make them long and readible. It's much easier to maintain code with variable names like "SECONDS_PER_DAY" than variables like spd.
The current stardards on capitalization that we're aiming for is:
We're still plagued by conventions set when we were using a Fortran compiler that could not handle capitalization. Many (possibly most) of our defined variables are lower case and the names are shorter than 8 characters. E.G. nmtoft instead of NAUTICAL_MILES_TO_FEET. All programmers are requested to:
Make all new variables follow the new standard
Update old variables to the new standard as time permits and while maintaining the code.
In addition, we are still using an old convention that the define statement for a message number is in lower case while the structure name is capitalized. For example, you'll find the following define in msgdefs.h:
and the following structure definition in icd.h
These standards are enforced by the autogeneration utilities, specifically the genStructs and the genMsgdefs utilities. While it would be easy to change these utilities ferreting out all the problems that might result from changing to the new standard does not seem worthwhile at this time.
Indentation rules are: