MOFIA 2.0
E614 Analysis Code


VIII. Coding Conventions

The software code for the E614 experiment will be developed over many years by many members of the collaboration. It is therefore necessary to have code that is well written, easy to debug, and easy to understand. To achieve this purpose, the E614 software group adopted a set of coding conventions that all software developers should adhere to. While many of these conventions are qualitative, it is up to the good judgement of the developer to employ these conventions in the best possible way that achieves the intended purpose.

1. Choose clear and descriptive variable names. Clear and descriptive subroutine, function and module names.

It is always easier to read code that has descriptive variable names. This allows the reader to go through the code without having to go back to a comment line to remind themselves what the variable stands for. The same is true for procedure and module names.

2. Provide detailed comments throughout the code.

People with different computer skills and physics backgrounds will be reading the code (graduate students, summer students, etc). It is important to provide enough comments to make the code understandable to everyone. A well-documented program would allow the reader to go through the comments and understand the code without even being familiar with the syntax!

3. Always use implicit none to force declarations of all variables.

This allows the compiler to detect a typing error, provides a documentation of all variables used in a subroutine, and avoids misusing a variable due to FORTRAN defaults for variable names. All procedures should contain an "IMPLICIT NONE" statement at the top.

4. Modules should be used instead of common blocks and parameter files.

Modules provide greater flexibility than parameter files and common blocks. Variable initializations inside modules as well as module functions and subroutines allow a nicer organization of the code. The only parameter files and common blocks used in MOFIA 2.0 are the ones inherited from the E787 code, or the ones common to both the analysis and Monte Carlo code.

5. Modules should have a complete documentation of all variables.

Variables declared in modules should always be described inside the module so that the reader would know where to find the documentation, rather than having to search through the code where they are used to find their description.

6. Subroutine, function and module names should always be specified on the end statement.

This is a nice feature that FORTRAN 90 provides, although it was not made mandatory to allow for backward compatibility with FORTRAN 77.

7. Control structure names should be used with all long structures that are not likely to fit on one screen. The same should be done with do loops.

This would improve the readability of the code since long control structures (particularly multiply nested structures) are often hard to follow. This applies to all "do loops", "select case", "do while", and "if" control structures. Again, FORTRAN 90 provides the option of naming these structures, but does not make it mandatory.

8. The "intent" attribute should be used in all functions and subroutines.

This provides a nice way of telling the reader whether a subroutine's argument is an input, an output, or both. It also protects from mistakes such as changing the value of an argument in a subroutine where it is intended to be an input only. FORTRAN 90 provides this option but does not make it mandatory.

9. Interface blocks should be supplied for all external functions/subroutines.

This allows the compiler to check that the function/subroutine is being called properly (that all arguments match in type). If not, this will be detected at compile time, therefore, avoiding possible crashes due to improper usage of a subroutine. FORTRAN 90 does not make this mandatory in all cases to allow for backward compatibility with FORTRAN 77. In MOFIA 2.0 interface blocks are included in the code using a cpp include statement and given names with extensions ".ifb" (ex. #include kerror.ifb).

10.Internal (rather than external) functions and subroutines should be used if they are only intended to be used in the subroutine that calls them.

11.Comments on separate lines and on a statement line are allowed.

12.Keyword arguments should always be used when calling any procedure containing optional arguments (unless all arguments are used).

This avoids the confusion as to which variables are being omitted from the call.

13.Use "STATUS=replace" rather than "STATUS=unknown" when opening a file.

"STATUS=replace" is standard FORTRAN 90 that is not implementation dependent. If the file does not exist it is created, otherwise the existing file is deleted and a new file is created. "STATUS=unknown", however is implementation dependent.

14.Use whole array operations whenever possible rather than element by element assignments. However, element by element assignment could be more efficiency if several other calculations are needed in a do loop.

FORTRAN 90 supports a large number of array features not present in FORTRAN 77. In particular, whole array operations are a nice feature that makes the code more readable. Element by element assignments through do loops should be avoided whenever possible as long as it's not at the cost of efficiency.

15.The kind attribute should be used to specify all variables.

To make sure that the kind variable is used in a platform independent way the intrensic functions SELECTED_INTEGER_KIND, and SELECTED_REAL_KIND should be used to specify the precision and the range. This is already done in the module precisions_mod.f90, The statement "USE precisions.f90" should be present in every module. The types defined in precisions_mod are shown in table 7.
 

Definition
Function Call Usage
i2
SELECTED_INTEGER_KIND INTEGER (i2) ::
i4
SELECTED_INTEGER_KIND INTEGER (i4) ::
i8
SELECTED_INTEGER_KIND INTEGER (i8) ::
r4
SELECTED_INTEGER_KIND REAL (r4) ::
r8
SELECTED_INTEGER_KIND REAL (r8) ::

Table 7. The kind attribute definitions in precisions_mod.

16.Variables will not be case sensitive.

17.Lines up to 80 characters are allowed.

Although the compiler allows for up to 132 characters, lines longer than 80 characters are inconvenient for editing and printing.

18.Variable names can have up to a max of 31 characters (standard FORTRAN 90).

19.Make sure that variable names used are not cpp reserved names (ex. UNIX, MIPS, ALPHA, etc).

20.Always use the "ACTION" specifier in the open statement to specify if the file is "READ" "WRITE" or "READWRITE".

This provides a nice documentation for the reader to know how the I/O file is intended to be used, and avoids mistakes of writing output to an input file and vice versa.

21.GOTO statements and statement labels should be avoided as much as possible, in favor of the many nice control structures that FORTRAN 90 provides.

Redirecting the flow in a program is often confusing, and almost always time consuming for the reader. Using a GOTO statement forces the reader to: find the line in the code where the GOTO statement is pointing, figure out what that section of the code is doing and how it relates to where the GOTO statement is, and then go back and find where the GOTO statement that transfered the flow is to continue reading the code! Contrast this to a "cycle" or an "exit" statement in a "do loop" (for example) where you know then and there where the flow is redirected and how it relates to the rest of the code. "Do While" statements are another good example, where you know immediately upon entering the loop the condition for exiting. Short FORMATs should be included in the READ/WRITE statement. Long FORMATs, or FORMAT statements that are used more than once should be done in a separate FORMAT statement, and put as close to where they are being used as possible.

22.All features of FORTRAN 77 identified as obsolescent in FORTRAN 90 should not be used.

These features are marked for deletion in future FORTRAN standards, and have only been kept for backward compatibility with FORTRAN 77. These include a set of features that most programmers agree are not good programming techniques. For a list of obsolescent features see Appendix F in "Upgrading to FORTRAN 90" by Cooper Redwine, for example.

23.Free source format should be used. Indentations of 2 or 3 spaces should be used for statements inside do loops, if structures etc., and nested loops. However, only one statement per line should be used.

This is important for readability purposes. The indentation rule of (2 or 3 spaces) is consistent with emacs/xemacs defaults (i.e. emacs will do it for you if you hit tab on that line, as long as the program name has extension ".f90").

24.Pointer names should always end with an upper case "P".

Example: planeP, wireP.

25.All modules should have "_mod.f90" appended to the name.

Example: chambers_mod.f90, hists_mod.f90.

26.Contents of all modules should be made private by using the "PRIVATE" statement in the module. Variables and procedures that need to be accessed from outside the module should be explicitly declared public.

Making the contents of a module private protects the variables in that module from being accessed and changed by other modules that don't need them. It also prevents the use of module subroutines that are intended for internal use only. In addition, it has the advantage of blocking nested USE statements, and thereby making the module dependencies easier to sort out. For example, suppose that module B uses module A, and module C needs to use both modules A and B. If no PRIVATE statement is present in module B, module C can only contain the statement "USE B", since module A is already used by module B. If both modules A and B are used explicitly in module C (i.e. through the statements . USE A and USE B) this will cause an error on some compilers (ALPHA) and a warning on others (ABSOFT). This module "nesting" becomes more complicated when many modules are present. The PRIVATE statement blocks nesting so that a module that is needed by another module would have to be used explicitly. In the above example, when a PRIVATE statement is inserted in module B, module C would have to explicitly contain a USE statement for both modules A and B.

27. Modules should be organized as is shown in the sample module sample_mod.f90 below. This module is included in the code for convenience.

MODULE sample_mod
   ! ========================================================
   ! Author:
   ! Date:
   ! ------------------------------------------------------------------------------
   ! Description:
   !========================================================
   ! USE statements
   USE
   IMPLICIT NONE
   PRIVATE
   ! Public Procedures
   PUBLIC ::
   ! Global variables
   PUBLIC ::
   ! Include statements
#include ""
   ! Interface blocks
   INTERFACE
   #include "xx.ifb"
   END INTERFACE
   ! Variable declarations
CONTAINS
    SUBROUTINE yy
    END SUBROUTINE yy
END MODULE sample_mod