HowTo: LMDZ code guidelines
De LMDZPedia
Révision de 24 juillet 2024 à 16:46 par Abarral (discussion | contributions)
/!\ This page is a WORK IN PROGRESS. Nothing in this page should be considered correct or consensual for now. /!\
Example code
Note: in this example, we added "meta-comments" indicated by !!
Note: of course, there's always exceptions to "Always", but they should systematically documented by a comment, with a proper explanation.
1 !! File: lmdz_mymodule.f90
2 !! ^ all module files should start with their component name, (e.g. "lmdz")
3 !! ^ use ".f90" for all free-form files, unless they contain preprocessor directives (then use ".F90").
4
5 !! At the top of the file, we provide a comment to explain what this modules does
6 ! implementation of my_useful_stuff.
7 ! ----------------------------------
8
9 !! Unless specified otherwise, all files should contain a single module which encapsulates all their content
10 MODULE lmdz_mymodule
11 !! ^ all Fortran keywords are in CAPS, everything else is in lowercase.
12 USE my_other_module, ONLY: function_a, function_b
13 !! ^ Always specify explicitely which functions you use from a module.
14 !!^ use indentation (2 spaces) to provide visual clarity
15 IMPLICIT NONE; PRIVATE
16 !! ^ Always make your module private, and expose explicitely which functions are public
17 !! ^ Always use IMPLICIT NONE at the module-level
18 PUBLIC my_var, my_subroutine
19
20 REAL, PARAMETER :: my_var
21 REAL :: a, b, c, d, e, f
22 !! ^ use "::" even if it's not strictly necessary
23 !! ^ Alignment of "::" is not necessary, but should be attempted whenever it provides readability and is relevant (e.g. there's some link between the aligned variables)
24
25 CONTAINS
26
27 !! Put at least a blank line before/after each function/subroutine
28 SUBROUTINE my_subroutine(arg1, arg2, arg3) ! handle event xxxx
29 !! ^ comments should always be right before, or on the same line as what they're commenting
30 !! ^ as for modules, all functions should be documented in a comment
31 INTEGER, INTENT(IN) :: arg1
32 !! ^ Always provide intent
33 REAL, INTENT(IN) :: arg2
34
35 INTEGER, INTENT(INOUT) :: arg3
36
37 REAl, INTENT(OUT) :: out1
38 !!^ Group together IN, then INOUT, then OUT
39
40 IF (arg2 > arg1) THEN
41 !! ^ .ge., .le., etc are deprecated. Use >, <, ==, etc instead
42 ! ...
43 END IF
44 !! ^ Use END IF, END DO rather than ENDIF, ENDDO (coherence with fortran-lang.org)
45 END SUBROUTINE my_subroutine
46 !! ^ always use named blocks for END
47
48
49 END MODULE my_module
50 !! ^ always use named blocks for END
Some comments:
- Limit to the bare minimum the use of preprocessor
#ifdef
keys. Those decrease lisibility, disable automatic code analysis, and generally make code a pain to manage and read. Ideally, a given preprocessor key should be used only once, or if not possible, in a single module for the entire codebase. - Limit the use of
include
headers to the bare minimum. Whenever not possible, wrap those include in a module, and import that module instead. This provides much more flexibility, e.g. when usingONLY: ...
.