Previous: Appendix I: The full code for the Listview example
Next: Acknowledgements
FTN95 has debugging and optimisation options, but I have never really found the need for either of them, as I tend to write code in small increments, including developing dialogs independently of the application and only incorporating them when they are fully developed. Anyway, even the slowest computer capable of running recent versions of Windows will execute the GUI part of your program many times faster than the user can possibly interact with it. Both options, particularly the optimisation option, may well prove useful when implementing the computational core of a program.
Starting with Kreitzberg and Schneiderman’s advice on optimisation, especially to remove subroutine calls from within nested loops, I had originally found that advice to be very effective in reducing run times of my programs. However, it came at a cost, and that cost was in readability. While there is no doubt that each subroutine call carries an overhead, my experience with FTN95 is that the overhead is nowhere near as great as it was with low memory capacity mainframes a half-century ago, and my recommendation is that you go for readability rather than taking the K&S advice.
Another bit of modern advice is not to remove common subexpressions from a sequence of assignment statements, but rather to let the compiler do it for you, as FTN95 certainly can. K&S said that it was beneficial to do it, because for the compilers of the time it was – they said – more efficient. The modern advice is counter to that. However, those common subexpressions do take up space in the source code and do affect overall readability, so on balance, I have found it better to identify them, and then store their results in a local variable. It helps if such local variables are readily identifiable. One program I read25 used the word ‘GASH’ (which in informal UK English also has the meaning of spare – but also rubbish or waste) to denote such a local variable, and when more than one local variable was used the programmer cycled through the remaining vowels. I have opted for COEF1 to COEF9 as appropriate names in one of my programs. Again, readability trumps optimisation, certainly in the user interface but also quite possibly elsewhere, and readability improves with short statements and appropriate naming. Re-using local variable names in the same subprogram is a recipe for confusion, and on modern PCs a handful of local variables doesn’t cause problems.
Subroutine names are fairly obvious when you come across them in source code, either because they crop up in a CALL statement, or at the start of a SUBROUTINE. What may not be obvious, however, is where to find the source code of the subroutine if the complete program is spread out across numerous files. There is obviously a place for comments, especially inline comments, to help in this. FUNCTIONs are more difficult to recognise at a glance, and that is why I like to use mechanisms such as the KB_ prefix for callback functions. As far as possible, I like to have such callback functions in the relevant source code files, close to where they are called, but that isn’t always possible, and again, it is a good use of comments to provide information on where to look. If you don’t like the idea of such prefixes, then what about a postfix such as _FN? Back in the early days of mainframes and the first generation of PCs, memory was very restricted. This often meant that the early Fortran need to declare the length of every array was not a very great problem: you declared arrays as big as you could get away with, and that was that. It may still be a satisfactory solution. Indeed, in one of my student surveying programs, there is space for 5,000 readings. A diligent student group might take 50, and a group with one or more mature members with some industrial experience might even get that up to 100. If I used the program for my own work, I doubt it I would take 200 readings. And yet, the space taken for 5,000 readings of degrees, minutes, seconds, and distances takes only 100k bytes when the first 3 items are INTEGER*4!
Other workarounds in the past included overlaying program executable code (which FTN95 doesn’t do), or using an array X declared usually in blank common as X(1) or X(*), which was then expandable into whatever free memory there is by simply ignoring the length declared and pretending that it was longer. FTN95 still supports that nasty (but formerly useful) approach, although for those with the appropriate needs, it is worth pointing out that there are now facilities for dynamically allocating arrays and deallocating them to free up space when it is no longer used.
My advice to programmers putting a Windows wrapper round an existing program is to stick with whatever original memory management there was until you have the ClearWin+ code sorted out and treat updating the computational core as something to follow on with.
Footnotes:
25. It was a finite element code from Swansea University in a thesis.
FORTRAN and the ART of Windows Programming, Copyright © Eddie Bromhead, 2023.