I'd like to optimize the readability of my codes in Fortran by using OOP. I thus use derived types. what is the best practice to name the types and derived types?
For example, is it better to:
type a
real :: var
end type
type(a) :: mya
or always begin type names by type_
like in type_a
? I like this one but maybe better ideas can be foud.
Also, is it better (then why) to use short names that are less readable or longer names that end up quite difficult to read if the type has too many "levels". For example, in a%b%c%d%e
, if a, b, c, d and e are 8 or more letters long as in country%hospital%service%patient%name
, then once again readability seems to be a concern.
Advices from experts are really welcome.
This not anything special to Fortran. You can use coding recommendation for other languages. Usually, type names are not designated by any prefix or suffix. In many languages class names start with a capital letter. You can use this in Fortran also, even if it is not case sensitive. Just be sure not to reuse the name with a small letter as a variable name.
One example of a good coding guideline is this and you can adapt it for Fortran very easily. Also, have a look on some Fortran examples in books like MRC or RXX. OS can be also useful.
I would recommend not to use too short component names, if the letter is not the same as used in the written equation. In that case it can be used.
Use the associate
construct or pointers to make aliases to nested names like country%hospital%service%patient%name
.
In my experience, naming issues come up in OO Fortran more than other languages (e.g. C++) because of Fortran's named modules, lack of namespaces, and case-insensitivity, among other things. Case-insensitivity hurts because if you name a type Foo
, you cannot have a variable named foo
or you will get a compiler error (tested with gfortran 4.9).
The rules I have settled on are:
Namespace_Foo
.Namespace_Foo
can be located in your source tree as Namespace/Foo_M.f90
.bar
or bar_baz
.search => Namespace_Foo_search
.Namespace_Foo
can be named foo
(without namespace) when there is no easy alternative.These rules make it particularly easy to mirror a C/C++ class Namespace::Foo
in Fortran or bind (using BIND(C)
) a C++ class to Fortran. They also avoid all of the common name collisions I've run into.
Here's a working example (tested with gfortran 4.9).
module Namespace_Foo_M
implicit none
type :: Namespace_Foo
integer :: bar
real :: bar_baz
contains
procedure, pass(this) :: search => Namespace_Foo_search
end type
contains
function Namespace_Foo_search(this, offset) result(index)
class(Namespace_Foo) :: this
integer,intent(in) :: offset !input
integer :: index !return value
index = this%bar + int(this%bar_baz) + offset
end function
end module
program main
use Namespace_Foo_M !src/Namespace/Foo_M.f90
type(Namespace_Foo) :: foo
foo % bar = 1
foo % bar_baz = 7.3
print *, foo % search(3) !should print 11
end program
Note that for the purpose of running the example, you can copy/paste everything above into a single file.
Final Thoughts
I have found the lack of namespaces extremely frustrating in Fortran and the only way to hack it is to just include it in the names themselves. We have some nested "namespaces", e.g. in C++ Utils::IO::PrettyPrinter
and in Fortran Utils_IO_PrettyPrinter
. One reason I use CamelCase for classes, e.g. PrettyPrinter
instead of Pretty_Printer
, is to disambiguate what is a namespace. It does not really matter to me if namespaces are upper or lower case, but the same case should be used in the name and file path, e.g. class utils_io_PrettyPrinter
should live at utils/io/PrettyPrinter_M.f90
. In large/unfamiliar projects, you will spend a lot of time searching the source tree for where specific modules live and developing a convention between module name and file path can be a major time saver.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With