Skip to main content
Fortran, despite being one of the oldest programming languages still in active use, has several common anti-patterns that can lead to performance issues, maintainability problems, and bugs. Here are the most important anti-patterns to avoid when writing Fortran code.
Avoid using GOTO statements, which make code difficult to understand and maintain. Use structured control flow constructs like DO loops, IF-THEN-ELSE, and SELECT CASE instead.
Always use IMPLICIT NONE to disable implicit typing. This helps catch typos and undeclared variables at compile time, making your code more robust.
Avoid using COMMON blocks for sharing data between program units. Use modules instead, which provide better type checking, encapsulation, and maintainability.
Use free-form source format (introduced in Fortran 90) instead of the older fixed-form format. Free-form is more readable, flexible, and doesn’t have column restrictions.
Avoid using obsolete features like labeled DO loops, arithmetic IF statements, and computed GOTO. Use modern control structures that are more readable and maintainable.
Use modules to encapsulate data and related procedures. This improves code organization, maintainability, and helps prevent unintended modifications to data.
Avoid using the EQUIVALENCE statement, which can lead to undefined behavior and makes code hard to understand and maintain. Use explicit type conversions or derived types instead.
Use Fortran’s array operations instead of explicit loops for element-by-element operations. Array operations are more concise, often more efficient, and can be automatically parallelized by the compiler.
Use allocatable arrays instead of fixed-size arrays when the size is not known at compile time. This avoids wasting memory and potential buffer overflows.
Always use INTENT attributes (IN, OUT, INOUT) for subroutine and function arguments. This documents how arguments are used, helps prevent bugs, and enables compiler optimizations.
Avoid using the ENTRY statement, which creates multiple entry points in a single subroutine or function. This makes code hard to understand and maintain. Use separate subroutines or functions instead.
Use proper error handling for I/O operations and other potential sources of errors. Check status codes (IOSTAT) and provide meaningful error messages (IOMSG).
Use KIND parameters to specify precision requirements in a portable way. This makes your code more maintainable and portable across different platforms.
Use NEWUNIT to get a unique unit number instead of hardcoding unit numbers. Also, always check for I/O errors and handle them appropriately.
Always initialize variables before using them. Uninitialized variables can contain unpredictable values, leading to bugs that are hard to track down.
Use derived types to group related data together. This makes code more organized, readable, and maintainable, especially for complex data structures.
Document your code with comments that explain the purpose, parameters, return values, and any important details or assumptions. This makes your code more maintainable and easier for others (including your future self) to understand.
Write automated tests for your code to verify that it works correctly. This helps catch bugs early and ensures that your code continues to work as expected when you make changes.