HowTo: LMDZ code guidelines : Différence entre versions

De LMDZPedia
Aller à : navigation, rechercher
m
Ligne 7 : Ligne 7 :
 
''Note: of course, there's always exceptions to "Always", but they should '''systematically''' documented by a comment, with a proper explanation.''
 
''Note: of course, there's always exceptions to "Always", but they should '''systematically''' documented by a comment, with a proper explanation.''
  
 +
<syntaxhighlight lang="fortran" line>
 +
!! File: lmdz_mymodule.f90
 +
!!        ^ all module files should start with their component name, (e.g. "lmdz")
 +
!!                      ^ use ".f90" for all free-form files, unless they contain preprocessor directives (then use ".F90").
  
!! File: lmdz_mymodule.f90
+
!! At the top of the file, we provide a comment to explain what this modules does
!!        ^ all module files should start with their component name, (e.g. "lmdz")
+
! implementation of my_useful_stuff.
!!                      ^ use ".f90" for all free-form files, unless they contain preprocessor directives (then use ".F90").
+
! ----------------------------------
 
!! At the top of the file, we provide a comment to explain what this modules does
 
! implementation of my_useful_stuff.
 
! ----------------------------------
 
 
!! Unless specified otherwise, all files should contain a single module which encapsulates all their content
 
MODULE my_module
 
!!  ^ all Fortran keywords are in CAPS, everything else is in lowercase.
 
  USE my_other_module, ONLY: function_a, function_b
 
  !!                    ^ Always specify explicitely which functions you use from a module.
 
!!^ use indentation (2 spaces) to provide visual clarity
 
  IMPLICIT NONE; PRIVATE
 
  !!                ^ Always make your module private, and expose explicitely which functions are public
 
  !!    ^ Always use IMPLICIT NONE at the module-level
 
  PUBLIC my_var, my_subroutine
 
 
  REAL, PARAMETER :: my_var
 
  REAL            :: a, b, c, d, e, f
 
  !!              ^ use "::" even if it's not strictly necessary
 
  !!      ^ 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)
 
       
 
CONTAINS
 
 
 
  !! Put at least a blank line before/after each function/subroutine
 
  SUBROUTINE my_subroutine(arg1, arg2, arg3) ! handle event xxxx
 
  !!                            ^ comments should always be right before, or on the same line as what they're commenting
 
  !!                            ^ as for modules, all functions should be documented in a comment
 
    INTEGER, INTENT(IN) :: arg1
 
    !!          ^ Always provide intent
 
    REAL, INTENT(IN)    :: arg2
 
 
 
    INTEGER, INTENT(INOUT) :: arg3
 
 
    REAl, INTENT(OUT) :: out1
 
    !!^ Group together IN, then INOUT, then OUT
 
 
    ! ... body of my_subroutine
 
    IF (arg2 > arg1) THEN
 
    !!      ^ .ge., .le., etc are deprecated. Use >, < ==, etc instead
 
      ! ...
 
    END IF
 
    !! ^ Use END IF, END DO rather than ENDIF, ENDDO (coherence with fortran-lang.org)
 
  END SUBROUTINE my_subroutine
 
!!        ^ always use named blocks for END
 
 
 
 
END MODULE my_module
 
!!      ^ always use named blocks for END
 
  
 +
!! Unless specified otherwise, all files should contain a single module which encapsulates all their content
 +
MODULE my_module
 +
!!  ^ all Fortran keywords are in CAPS, everything else is in lowercase.
 +
  USE my_other_module, ONLY: function_a, function_b
 +
  !!                    ^ Always specify explicitely which functions you use from a module.
 +
!!^ use indentation (2 spaces) to provide visual clarity
 +
  IMPLICIT NONE; PRIVATE
 +
  !!                ^ Always make your module private, and expose explicitely which functions are public
 +
  !!    ^ Always use IMPLICIT NONE at the module-level
 +
  PUBLIC my_var, my_subroutine
 +
 +
  REAL, PARAMETER :: my_var
 +
  REAL            :: a, b, c, d, e, f
 +
  !!              ^ use "::" even if it's not strictly necessary
 +
  !!      ^ 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)
 +
       
 +
CONTAINS
 +
 
 +
!! Put at least a blank line before/after each function/subroutine
 +
  SUBROUTINE my_subroutine(arg1, arg2, arg3) ! handle event xxxx
 +
  !!                            ^ comments should always be right before, or on the same line as what they're commenting
 +
  !!                            ^ as for modules, all functions should be documented in a comment
 +
    INTEGER, INTENT(IN) :: arg1
 +
    !!          ^ Always provide intent
 +
    REAL, INTENT(IN)    :: arg2
 +
 +
    INTEGER, INTENT(INOUT) :: arg3
 +
 +
    REAl, INTENT(OUT) :: out1
 +
    !!^ Group together IN, then INOUT, then OUT
 +
 +
    IF (arg2 > arg1) THEN
 +
    !!      ^ .ge., .le., etc are deprecated. Use >, <, ==, etc instead
 +
      ! ...
 +
    END IF
 +
    !! ^ Use END IF, END DO rather than ENDIF, ENDDO (coherence with fortran-lang.org)
 +
  END SUBROUTINE my_subroutine
 +
!!        ^ always use named blocks for END
 +
 
 +
 +
END MODULE my_module
 +
!!      ^ always use named blocks for END
 +
</syntaxhighlight>
  
  

Version du 18 juillet 2024 à 13:16

 /!\ 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 my_module
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: ....