I assume you are familiar with the vague term “module” from Structured Design. This is not to be confused with the module from Modula-2. Our modules are basically small functions or procedures from other languages. Everything that would be “put in a box” in a Structure Chart would be a module.
There are generally two types of modules: Control Modules and Work Modules, both subsumed under the term “Module”.
A Control Module should only be able to call other modules and perform comparisons, for instance “if a=2 then call module X else call module Y” but should not be able to perform actual program modifications or calculations in itself.
A Work Module on the other hand has the complete feature set of the language available in order to perform all sorts of calculations or operations, but it is NOT allowed to call other Modules.
This may look strange at first glance. For instance, if a module processes a number of records from a datafile, say to print out a list of records which are due for payments, shouldn’t it be able to open the datafile, read one record after the other and close the file? Surely, the OpenFile or ReadRecord functionality are pretty complex and need to be encoded with a hierarchy of “modules” themselves?
Well that is true but in this case, perhaps the complete “module” that does the printing should itself be split up in a hierarchy of Control Modules and Work Modules in the first place with only small functionality like “Check if this record needs to be printed” or “Calculate number of days before due date” and so on. When you believe, that your Work Module should be able to call other modules in order to perform it’s duty, chances are, you have not dissected the problem well enough and that your “Module” is really a Frankenstein module that should be split up into a hierarchy of modules.
Clearly, I advertise for very small Work Modules and the reason is, the smaller a module is, the easier it is to test.
What about Functions? As in “a := root( 10,2)”? Functions should be just a specialized form of a Work Module which happens to return a value. Other than that, they should obey the same rules as Work Modules, with the exception that they can call other functions as well, since especially mathematical functions often need to use other mathematical functions. Furthermore, Work Modules can call Functions, but the return value of a function can not be tossed as in C where a function can be called without using the return value. And yes, this softens up the rule the Work Modules must not call other modules, but I believe this is necessary for mathematical or other expressions to be coded in a reasonable manner.
The syntax for modules should be created in such a way, that these rules can be enforced by the compiler easily. Furthermore it should be made thus, that multiple modules can be placed in one source file in order to make writing the program, or coding, easier. I would advise against this though and place each module into it’s own sourcefile, but I realize that many programmers would take this as too great a restriction. However, should there ever be an IDE that supports this type of workflow, it would also be prudent to enforce each module to have it’s own sourcefile.
It may not be necessary to split modules into two files, like a Definition and an Implementation file as in Modula-2 or .H and .CPP files as in C++ since the compiler can extract the calling convention from the module and store them into a binary file which will later be imported by those modules that use the called module.
This also implies, that binding of modules is done with a binary interface, not with an include system like in C++ where each definition part of a function is compiled whenever the .H file is included
A hierarchy of Control and Work Modules with one Control Module at the top, a tree of Modules, can be combined into a form of package called a “Subprogram”. This Subprogram can thus be compiled and linked into one binary or rather two binary files (the OBJ file for the linker and one with the binary link information for the compiler) and then handed out to other programmers or put into a library of Subprograms.