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:
- Each Fortran module provides a single, primary class named
Namespace_Foo
.
- The class
Namespace_Foo
can be located in your source tree as Namespace/Foo_M.f90
.
- Class variables are nouns with descriptive, lower case names like
bar
or bar_baz
.
- Class methods are verbs with descriptive (but short if possible) names and use a rename
search => Namespace_Foo_search
.
- Instances of class
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.