Modular programming in C

M

Ever since its appearance in the early 1970s, C has become an unchallenged leader in system programming. The latter includes a large class of programs that interact very closely with the computer and whose performance affects everyone else. A typical example of such a program is the operating system.

C has several qualities that make it so much appreciated by system programmers (and not only). One of them, which we will deal with in this article, is the support it provides for the development of large, possibly team-based programs. We will see that this support is offered through extremely simple mechanisms, but whose existence often has a very important impact on language itself. Now let’s see what conditions must be met by a language that allows us to write large programs. Let us call these conditions premise. In order for a program to be written by several programmers, it must be able to be split into independent parts – as much as possible – which can be designed, compiled, tested separately.

Even when a single programmer is involved, dividing a program into parts that are slightly dependent on each other is very helpful for writing, but especially troubleshooting the result. Experimental studies have shown that the difficulty of writing a program increases exponentially with its length. That means writing a 2000 line program is much harder than writing two of 1000 lines.

It is therefore very useful to divide a program into multiple texts, each – perhaps – in a separate file. This division can be done in many ways; preferably all functions/variables/procedures, that do something related and must be put into the same file. The name of such a file is the mode. We can now state the prerequisite first of all necessary for writing great programs:

1. The text of a program can be divided into several modules. To be able to test the correctness – at least syntactically – of each module, it must be able to compile it separately from the others. We recall that during compilation all syntactic errors are detected (and sometimes possible conceptual errors – for example uninitialized variables). Separate compilation allows for the correction of each module independently.

2. Each module can be compiled separately. On the other hand, modules are part of a whole; it is expected that some objects (functions, procedures, variables, etc.) in a module will somehow be used by others in another module. Because the modules can be compiled separately to make it possible to verify the syntactic correctness of each, somehow the insights of the objects in a module that are accessible and from others must be described in the user modules. Let us call an object (variable, function) of a module that can be used by other modules exported by the module to which it belongs. He is, by symmetry, imported by the modules that use it. The premise that follows is necessary for easy maintenance of the information that needs to be used in several places.

3. Executed objects declarations exported by each module must be centralized (segregated in one place). The statement is an instruction that describes some of the attributes of an object;

4. There must be a method by which the declarations of an exporter module are taken over by the importing modules. In order to end, we still need a premise. Someone has to combine the results of the compilations of the different separate modules into a single program that can be executed.

5. We need to be able to put together multiple compiled modules separately to get an executable. Basically, to get the program we could have a new compilation of all the modules together. But since each module is probably already compiled, it would be time if we could use it.

Recent Posts

Archives

Categories