Let's look at an example. Suppose we have a source file called stuff.c containing the following code:
int index = 0;
void inc(void) { ++index; }
void dec(void) { --index; }
int show(void) { return index; }
int addtwo(int a, int b) { return a+b; }
int addthree(int a, int b, int c) { return a+b+c; }
In the first part of the file, the goal is to have index hidden from
the outside and accessible only via the functions inc()
,
dec()
, and show()
. As written, when this file is
compiled into an object, index will NOT be hidden from other
sources. For example, we could write a source named cheat.c
containing the following code:
void main(void) { index = 100; }
and compile it with cc -o cheat cheat.c stuff.c
. This program
will change index to 100 without any problems. How do we prevent this?
A common misunderstanding about objects is the belief that you need an
object-oriented language to hide things like index
. This is not
true. In C, data and functions can be declared as
static
, which means they are only visible within
their declared scope. In the case of index, this means it is only
visible to things within the file stuff.c. Each of the
functions inc()
, dec()
, and show()
have
to have access to the variable index, but the other functions in
stuff.c do not.
Okay, so we'll rewrite the file making index static, but before we
do, note that the functions addtwo()
and addthree()
are not related to the other parts of the source at all. If fact, they aren't
actually related to each other, so let's break stuff.c into
the three files index.c:
static int index = 0;
void inc(void) { ++index; }
void dec(void) { --index; }
int show(void) { return index; }
addtwo.c:
int addtwo(int a, int b) { return a+b; }
and addthree.c:
int addthree(int a, int b, int c) { return a+b+c; }
Now, when we compile, we'll have three objects which are small, self-contained, and hide their internal workings from other sources. This is the goal of modularity. If we want to improve any of these pieces, we can do so without rewriting other sources; we only need to recompile them. If we choose to rewrite index.c to not use the variable index, we can do this without changing the interface to the outside world.
Speaking of interfaces, what are the interfaces that these modules present?
As far as the outside world knows, index.c contains only the
functions inc()
, dec()
, and show()
.
It is only inside that index is known. Each of the other
two sources present just the one function they contain.
So we see that modular coding is not about what language you use, but about designing your code around small pieces with specific interfaces that can be combined to form larger pieces and applications. THIS is what modular coding is about.