HowTo: LMDZ code guidelines : Différence entre versions

De LMDZPedia
Aller à : navigation, rechercher
m
m
Ligne 16 : Ligne 16 :
 
! ----------------------------------
 
! ----------------------------------
  
!! Unless specified otherwise, all files should contain a single module which encapsulates all their content
+
!! Unless specified otherwise, all files should contain a single module with the same name which encapsulates all their content
 
MODULE lmdz_mymodule
 
MODULE lmdz_mymodule
 
!!  ^ all Fortran keywords are in CAPS, everything else is in lowercase.
 
!!  ^ all Fortran keywords are in CAPS, everything else is in lowercase.

Version du 24 juillet 2024 à 16:47

 /!\ 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 with the same name 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 using ONLY: ....