fortran コーディングスタイル(自分用)

ここ数週間のコーディングで考えたこと。第4回 オブジェクト指向の本質:Software is Beautiful|gihyo.jp … 技術評論社を読みながら、fortran に何ができるかをかんがえてみた。

  • 大文字・小文字
    • fortran予約語、組み込み関数等は大文字で綴る。
    • 自作の定数は大文字で書く
    • 自作の識別子はCamelCaseで書く
  • コメント
    • コメントを書く。特に上位、下位とのインターフェースの部分には「利用法」と「依存性」の説明になるコメントを書く。

      SUBROUTINE sub ( !&! サブルーチンの目的(簡単に)
     &  a !&! a の説明 [入力時] => [出力時]
     & ,b !&! b の説明
     & ,c !&! c の説明
     &)

  • 固定形式*1+継続行ルール
    • [スタイル] fortranソースコードは固定形式で書くこと。行の継続は(多少面倒だが)次の2個のルールを用いる:
      1. 継続するの行の6カラム目にアンド記号 & を書く。
      2. 継続される行の行末に「感嘆符+アンド記号」 !& を書く。
      3. 継続される行の行末にコメントを書く場合は「感嘆符+アンド記号+感嘆符+コメント」 !&!comment で書く。
    • [説明]古い fortran 77 コード(例えば BLAS, LAPACKソースコード)を再利用するときに、ソースレベルでひとつの同じファイルに含めた上でfortran 90/95 によるビルドを実行可能にするため。(実行ファイルをビルドする方法を多様にする。逆に固定形式、自由形式が混ざると、それぞれのファイルを別個にコンパイルして、リンクしないといけないという制約になる。)
    • [説明]固定形式の fortran ソースは、行の継続を除いて、そのまま自由形式のソースコードとしても使える。前の行の行末の「感嘆符+アンド記号」の「感嘆符」を消すと fortran 自由形式のソースコードとしても利用可能になる。*2
      [サンプル]
        REAL(KIND(0D0)) ,TARGET ,DIMENSION ( &!
     &    idxSizeField3D(0:0) : idxSizeField3D(1:0) &! comment
     &   ,idxSizeField3D(0:1) : idxSizeField3D(1:1) &!
     &   ,idxSizeField3D(0:2) : idxSizeField3D(1:2) &!
     &  ):: f
    • [都市伝説] 自由形式では行の長さの制限が取れたかのように書いてあるページ(例:Fortran 標準コーディングルール)もあるが、自由形式は「1行は132文字」であり、固定形式のたかだか2倍である。
    • [蛇足] 例えば PHP のライブラリ作成の標準コーディング規約 Manual - Documentation - Zend Framework でも可読性を考えて「1 行の長さを 80 文字までにすることを目指しましょう。」とある。可読性と1行の長さの制約には、おそらく関係がない。
  • 命名(暫定案)
    • [原則]複数のプログラム単位に関わる主要な変数は、なるべく「読めば推測が付く」ように31文字の制限すれすれまで使って書く。
    • [原則]プログラム単位の名前は [動詞][目的・対象の語]([修飾語][修飾語]...)をこころがける
    • [原則]主要な変数の名前は [何らかの属性][目的・対象の語]([修飾語][修飾語]...)をこころがける
    • [原則]以上の命名ルールを主に CamelCase で書き、アンダースコアは定数と紛れないためになるべく使わない。fortran に大文字・小文字の区別はないが、fortranソースコードを読まされる人間は大文字、小文字を勝手に区別して認識するという特性を利用するためである。
    • [原則]主要な定数の名前も [何らかの属性][目的・対象の語]([修飾語][修飾語]...)をこころがけるが、これは「大文字+アンダースコアで区切り」で書く。
    • [補足]小さなプログラム単位内では、意味・文脈上もコード上も局所的な変数(例えば DO ループの変数)は略称みたいな少数の文字列でも構わない。
    • [蛇足]FORTRAN77の「6文字制約」的な暗号のような名前を付けない。たとえば
      module prm_resol
      命名するよりは
      MODULE SetParameterResolutionSpatial ! パラメーターで空間解像度に関するものを設定する
      と書くべきである。読まされる方の身にもなってみろ!(この暗号的な fortran命名カルチャーなんとかならんかな?)
    • fortranのライブラリのインターフェースは FORTRAN77 の「6文字名前」「PASCAL的な引数記述」で提供されることが多いが、これはラッパーを作って呼出側の可読性を上げる方が良いだろう。
  1. MODULE
    • SUBROUTINE, FUNCTION は必ず MODULE に入れる。
    • これによって SUBROUTINE, FUNCTION の利用に対する USE 文の記述が強制され、依存関係をソースコードに明示的に書かざるを得なくなる。
    • これによって SUBROUTINE, FUNCTION のインターフェースの「型」の利用が USE 文の1行で済むようになる。
  • 変数等の宣言
    • [原則] 主要な変数等の宣言にはコメントを付ける。
    • [原則] 他のプログラム単位に依存しているものは必ず明示的に宣言する。
    • [原則] MODULE は USE 文に ,ONLY: を必ず付けて不必要な継承を極力避けること。前提:関数、サブルーチンは依存関係をソースコードに明示するために「 MODULE 化」する。
    • [原則] MODULE 内のたいていのものには必ず PRIVATE 属性を付けて呼出側から隠ぺいする。
    • [原則] 他のプログラム単位に公開する変数、手続きは必ず PUBLIC とともに明示的に宣言する。
    • [説明] 大きなコードでは、個別のプログラム単位よりも、プログラム単位間の依存関係が問題になるので、下位の MODULE の変数の影響を不必要に引きずり込まないこと、その結果として上位に「こっそりとした多段階の継承」を渡さないこと。
      USE DoSomeCalculation ,ONLY: numSizeCalculation
     & ,calculateSomeQuantity
      PRIVATE numSizeCalculation ,calculateSomeQuantity
  • IMPLICIT文
    • [原則] IMPLICIT NONE は使わない
    • [原則] 数値計算なら IMPLICIT REAL(KIND(0D0)) (a-h,o-z), INTEGER (i-n) を使う
    • [説明] 変数をすべて定義することによる、ソースコードの可読性の低下を防ぐ。
      大きなコードの場合、個別のプログラム単位よりも、プログラム単位間の依存関係が問題になるので、宣言文の目的は「他のプログラム単位との依存関係を明示する」ことにシフトするべきである(だからザコ変数は宣言しない)。プログラム開発時に起きる変数の書き間違い等はコンパイラの吐くエラーと警告を丁寧に読むことで対処するので、「コンパイルエラーを防ぐために implicit none」という理屈は近視眼的である。
  • コンマ
    • 「変数の終わり」ではなく「次の変数への継続記号」として、「変数の前」に書く。
  • インデント
    • 「分岐」「繰り返し」というプログラム進行の基礎要素の入れ子構造がはっきりと分かるように書く。
  • …以下、考え中

*1:[2021.8.13] 参照 すべてのソース形式で使用できるソース・コードFortran 95 では,固定形式は廃止されています。参照 https://jp.xlsoft.com/documents/intel/cvf/vf-html/lr/lr02_03_02.htm 旧スタイルのソースコード、古いコンパイラでの利用可能性を考えるのは悩ましい。

*2:Compaq Fortran の文法書を参照jp.xlsoft.com