From: Paul Van Delst on 7 Mar 2006 17:57 beliavsky(a)aol.com wrote: > Paul Van Delst wrote: > >>Hello, >> >>I'm putting together some coding guidelines for review by folks here and I'm gathering >>input from a bunch of sources. I want to get some other people's opinions on a particular >>item. >> >>In one set of guidelines regarding USE satements I came across the recommendation to keep >>USE statements local and not to put them in the module header. >> >>This behaviour is the total opposite of what I do - I put all USE statements as the very >>first statements in modules and /none/ in the module procedures. > > > I follow your practice. > > >>I do so because, in my >>mind at least if not in practice, each procedure in that module cannot logically reside >>anywhere else but in that module so it makes no sense to repeat the exact same USE >>statements throughout. Additionally, I like being able to determine all the module's USE >>dependencies by looking in one place. >> >>So, without trying to start a "my way is better than your way" to-and-fro, do other folks >>have an opinion? Is there an accepted reason for doing something like keeping USE >>statements local to procedures? > > > If only one procedure in a module USEs something called "foo" from > another module, putting the USE inside that procedure would make clear > that that is the only place "foo" is referenced. If many procedures use > foo, it is convenient to put the USE at the beginning of the module. Yes, I thought about that case, but in the end I tend towards consistency. I know that all the required USE statements will be at the top of the module, evne if only one module procedure in that module actually uses stuff from the USE modules. It's one less thing for me to remember. > On a separate topic, I think USE statements should usually have the > ONLY clause to clarify dependencies. Have you considered this matter in > your guidelines? Yes. Well, ONLY clauses are addressed in several of the sources I'm cribbing from. :o) And that makes me think of something else. A typical thing to do is read data from file. The way I generally approach this is to read the file data into a derived type. The derived type definition (MyType_type) and associated procedures to allocate, destroy, assign, etc the structure are placed in a module named MyType_Define.f90 All the I/O routines are placed in a module named, e.g. MyType_netCDF_IO.f90 for netCDF format file I/O. The I/O module USEs the Define module. In both modules I use the PRIVATE statement followed by explicit declaration of all public entities. Now typically, when my code needs to read and play with the MyType data, I do the following: USE MyType_Define USE MyType_netCDF_IO What do people think of making all the public entities of MyType_Define available via MyType_netCDF_IO so all I would have to do would be USE MyType_netCDF_IO to get access to the type definition/procedures along with the I/O functions? That is, I explicitly declare all the public entities of MyType_Define as public in MyType_netCDF_IO. It seems silly, but when I do the latter, I feel unclean.... :o) I would prefer a more module-structure-related reason arguing for the former method (or disabusing me of it). cheers, paulv -- Paul van Delst CIMSS @ NOAA/NCEP/EMC
From: Richard Edgar on 7 Mar 2006 18:32 Paul Van Delst wrote: > In one set of guidelines regarding USE satements I came across the > recommendation to keep USE statements local and not to put them in the > module header. > > This behaviour is the total opposite of what I do - I put all USE > statements as the very first statements in modules and /none/ in the > module procedures. I do so because, in my mind at least if not in > practice, each procedure in that module cannot logically reside anywhere > else but in that module so it makes no sense to repeat the exact same > USE statements throughout. Additionally, I like being able to determine > all the module's USE dependencies by looking in one place. I follow your way, unless I'm interfacing onto another code (and then, I usually just have little wrappers which call into code written to my usual style). If you're going to repeat the same information in each subprogram, then IMO the 'grouping' idea of modules is being negated. And you don't even get out of the recompile cascade (currently being debated elsewhere today). To help guard against namespace pollution, I make everything PRIVATE by default. And I really should make more use of ONLY clauses. Richard
From: Joe Krahn on 7 Mar 2006 18:54 Paul Van Delst wrote: > Hello, > > I'm putting together some coding guidelines for review by folks here and > I'm gathering input from a bunch of sources. I want to get some other > people's opinions on a particular item. > > In one set of guidelines regarding USE satements I came across the > recommendation to keep USE statements local and not to put them in the > module header. > > This behaviour is the total opposite of what I do - I put all USE > statements as the very first statements in modules and /none/ in the > module procedures. I do so because, in my mind at least if not in > practice, each procedure in that module cannot logically reside anywhere > else but in that module so it makes no sense to repeat the exact same > USE statements throughout. Additionally, I like being able to determine > all the module's USE dependencies by looking in one place. > > So, without trying to start a "my way is better than your way" > to-and-fro, do other folks have an opinion? Is there an accepted reason > for doing something like keeping USE statements local to procedures? > Should the localisation of USE statements relate somehow to the module > structure? > > cheers, > > paulv > I am guessing that the suggestion of individual USE statements goes with the idea of limiting every name space to the minimum required in every procedure. I generally think of a module as sharing a common name space. If procedures vary too much, it could become a bit confusing, and maybe they don't really belong in the same module. Another reason (I just thought of) is that people who favor USE within every procedure probably want to be able to look at the beginning of every procedure and see a complete list of all entities accessible to that procedure. If you want to satisfy both classes of people in the case of code shared among a group, maybe you can do both. For example, you could require every USEd module to be listed at the beginning of every module, but also require procedures to list each individual USE item. (Just an idea -- the problem is, what to do with a module-level USE statement if no part is accessed in the modules specification part?) One thing I think would be nice is to be able to access members of a module through the module's name without bringing the individual items into your name space, such as MODULE_NAME%PROCEDURE_NAME(...). Since MODULE_NAME uses the same name space as variables, that syntax won't case a conflict (right?). One can then bring commonly used items into your namespace, but still get at the remaining items. For now, it might be a reasonable idea to rename less-used module items by prefixing the module's name, especially if the procedure name is not very unique. Joe
From: Keith Refson on 8 Mar 2006 04:56 Paul Van Delst wrote: > In one set of guidelines regarding USE satements I came across the > recommendation to keep USE statements local and not to put them in the > module header. > > This behaviour is the total opposite of what I do - I put all USE > statements as the very first statements in modules and /none/ in the > module procedures. I do so because, in my mind at least if not in > practice, each procedure in that module cannot logically reside anywhere > else but in that module so it makes no sense to repeat the exact same > USE statements throughout. Additionally, I like being able to determine > all the module's USE dependencies by looking in one place. > All the responses to your post concentrate on the programmer efficiency and maintainability aspects of this choice. Unfortunately there is another, more practical consideration, which I didn't see mentioned. In the context of a large multi-module development project it has been my experience that unshielded USE statements in module headers can cause compilers to break or misbehave. I have seen several examples with more than one compiler - one fresh in my memory is that compiling one of our modules with Intel Fortran 9.0 uses 1.7GB of memory for the compiler process without optimization. This drops to just over 1GB when a module lower down the chain is modified, moving unqualified USE statements from the module level into the subroutine blocks. I have seen worse behaviour with other compilers -- frequently internal compiler errors, resource limit exhaustion and other various crashes, which are alleviated by avoiding module-level USE statements. I'm not 100% sure why this practice should stress a compiler so severely. One possibility is the sheer size of the namespace. In a project with a compilation cascade, the upper level modules can end up associating a very large number of variables. There's also the case as happens in our project when A uses B and C, but B also uses C. In that case all the public variables in C are USE associated to A via two separate routes, the direct and the indirect one. In the general case of multiple USE associations, especially when some have ONLY qualifications and others do not my guess is that this may cause difficulty for the compiler in disentangling the web of associations. Now much of the above explanation is guesswork, and I'd appreciate comments from those with experience of F95 compiler writing on the accuracy or otherwise of this guesswork. Keith Refson -- Dr Keith Refson, Building R3 Rutherford Appleton Laboratory Chilton Didcot kr AT Oxfordshire OX11 0QX isise D@T rl D.T ac D?T uk
From: Pierre Asselin on 8 Mar 2006 10:15
Paul Van Delst <Paul.vanDelst(a)noaa.gov> wrote: > beliavsky(a)aol.com wrote: > > > > If only one procedure in a module USEs something called "foo" from > > another module, putting the USE inside that procedure would make clear > > that that is the only place "foo" is referenced. If many procedures use > > foo, it is convenient to put the USE at the beginning of the module. > Yes, I thought about that case, but in the end I tend towards consistency. I know that all > the required USE statements will be at the top of the module, evne if only one module > procedure in that module actually uses stuff from the USE modules. It's one less thing for > me to remember. On the contrary, you now have to remember what procedures do *not* use what modules and you have no easy way of cribbing that from the sources. What happens if one of the lower-level modules is redesigned ? How do you know what higher-level code needs to be updated ? > > On a separate topic, I think USE statements should usually have the > > ONLY clause to clarify dependencies. Have you considered this matter in > > your guidelines? > Yes. Well, ONLY clauses are addressed in several of the sources I'm cribbing from. :o) If you put the use statements at the top of the module, your ONLY clauses have to be the union of all the ONLYs of individual procedures. Done the other way, the ONLY clauses are narrow. Which way conveys the most information ? I would put the use statements in individual procedures, but I would allow them at module scope if the individual statements would otherwise be close to identical and more of a PITA than they're worth. Since you are writing coding standards, you could also mandate a comment at module level, warning that there are USEs after the CONTAINS. > And that makes me think of something else. > [ ... ] > Now typically, when my code needs to read and play with the MyType data, I do the following: > USE MyType_Define > USE MyType_netCDF_IO > > What do people think of making all the public entities of MyType_Define available via > MyType_netCDF_IO so all I would have to do would be > USE MyType_netCDF_IO > to get access to the type definition/procedures along with the I/O functions? The latter, if it logically makes sense to do so. Not sure what to do if there are several modules that operate on MyType, for example ! do we require USE MyType_Define ? USE MyType_netCDF_IO USE MyType_XML_IO ! just an example, okay ? USE MyType_Operations but then you should probably USE MyType_Wrapper_module_for_everything The rationale is to keep client code from having to USE too many obscure modules. Playing Devil's Advocate, in C the tradition is to #include all headers at file scope and to #include needed headers from headers. Transliterated to Fortran, that would mean USE at module scope (contrary to what I said) and single-module wrappers (as I said). -- pa at panix dot com |