fortran ではシングルトン型のオブジェクト指向プログラミングを志向すべきであり、
そのクラス=インスタンスにmoduleを使うことになる。
プログラム起動時にすでに、それらのインスタンスは生成されている。
この考え方で言えばモジュールには主に以下の2種類の使い方に限定すること
その1:複数のサブルーチンを取りまとめる。
複数のサブルーチンがcall-caller treeで結びついているときにその親玉(複数ありえる)を中心に一つのモジュールに入れる
publicな関数を指定する。原則的にモジュール変数はつかわない(サブルーチンの間のデータのやり取りが見えなくなる。変数のスコープを重視してコードを書くこと)。useしてcallすることで(基本的に必ずonlyをつける)、コンパイラが呼び出し側との間の変数の整合性チェックができる(optional変数、名前結合などでは必須)。単独のサブルーチンをモジュール化しておくのも、これらのご利益を得るために行うこともありえる。
その2:出力変数をモジュール変数とする。
`サブルーチンを複数含んでいる。同時にモジュール変数も含んでいる。
- サブルーチンの引数はすべて入力引数。入力引数は、指示変数と言えるスカラーや簡単なベクトル(たいていは固定長)だけ。
- モジュール変数に出力する。出力変数はprotectする。
- 他のモジュールの変数を見るときにはuse onlyを書く。
コンセプトとしては、他のモジュール内に格納されているデータ、引数として渡される指示を見て、自分自身の中にデータを作って貯める、ということ。他のモジュールにはそれを変更することはできない。読み出すのみ。アロケートするのもこのモジュール内で行う。
この書き方だとサプルーチン出力を左辺に書けない、などはあるけれど、論理構造としてはクラスを使って書くオブジェクト指向的なコードと同等になる。
「(必要ならば指示的な変数を与えてモジュール初期化。不要な場合も多い)ー>指示的な変数を与えてのモジュール関数呼び出しでモジュール出力変数をセットする」というのがプログラムの流れになる。モジュールへの入力は基本的にはuse,onlyで他のモジュール変数を参照することで行う。モジュール関数を呼び出すとき、その引数として大きなサイズの変数を受け渡さない。
そもそもfortranで書けるのはここまで。大きなプログラムをfortranで書くべきでないと思う。
(その3:typeの取りまとめなど)
そもそもtypeは極力使わないのがよいと考えているが私はpointer arrayを作る方法(原子ごとに長さの違う配列をつくるなど)がtypeの配列を作る以外に思いつかないのでしかたなく用いている。
https://github.com/tkotani/ecalj/blob/master/SRC/subroutines/m_struc_def.f90
(type s_specは消したいがまだ消せてない)。
ただ、プログラミングはどうしても、古い書き方、新しい書き方、試行的な書き方、などが共存するものになる。柔軟対応が必要。syntax sugarのレベルの差異にはこだわりすぎない方がいいーただし場合によれば書き方次第で、論理構造がスッキリとする。人間に読みやすいコードはcopilotにも読みやすい。