Modularity, Cohesion And Coupling
This section deals with considerations when designing functions. As you gain more experience you will need to eventually design and implement your own functions. When you do this, there will be some important things to consider in terms of your design and organization. This section will provide you with some guidelines to working with functions.
Modules
We often think about programs as consisting of independent modules. In large software project you will find that the application is often broken down into many modules that work together to form the entire program. For example, for these course notes, there is a module that renders the mathematical expressions like , a different module handles the glossary and a third module handles the search. Each of these modules were created by different developers who do not know each other. These modules function independently of each other. Other course notes may use all, some or none of these modules.
Multiple Source Files
As your own programs get bigger, you will find that dividing up your code into separate files help you manage and reuse your code. Consider our program where we have 3 functions. 2 of those functions have to do with calculating properties of a sphere... If we separate those 2 functions into a separate file, we would be able to reuse those same functions in other programs that require that sort of calculation. By keeping the functions bundled together with the main() program, we make it impossible to use those functions directly.
Separating Our Functions
A typical setup for a small program is as follows:
- create a header file:
- file contains function prototypes for all your functions
- file is often named based on what the functions are related to and end in a file extension of .h
- create a source file:
- file contains the function definitions
- the name should match the header files that contain those function prototypes and ends in a file extension of .c
- this file will typically have an include statement to include the header.
- take the main() function and put it by itself into a third file
- this file will include the header file
As your programs get bigger you will still have one main file, but you may have multiple header/source file pairs
To compile a program that is separated into multiple files use the command:
gcc source1.c source2.c ... programmain.c
Example:
Here is how we would separate the sphere program into separate files:
sphere.h
// function prototypes
double volumeOfSphere(double);
double surfaceAreaOfSphere(double);
double getRadius(int);
sphere.c
#include "sphere.h"
//function definitions:
double volumeOfSphere(double radius){
return 4.0/3 * 3.14159 * radius * radius * radius;
}
double surfaceAreaOfSphere(double radius){
return 4 * 3.14159 * radius^2
}
double getRadius(int sphereNumber){
double radius;
printf("Please enter the radias of sphere # %d: ",sphereNumber);
scanf("%lf",&radius);
return radius;
}
spheremain.c
#include <stdio.h>
#include "sphere.h"
int main(void){
double radius;
double totalVolume;
double totalArea;
radius = getRadius(1);
totalVolume = volumeOfSphere(radius);
totalArea = surfaceAreaOfSphere(radius);
radius = getRadius(2);
totalVolume += volumeOfSphere(radius);
totalArea += surfaceAreaOfSphere(radius);
radius = getRadius(3);
totalVolume += volumeOfSphere(radius);
totalArea += surfaceAreaOfSphere(radius);
printf("Total volume = %.2lf\n", totalVolume);
printf("Total surface area = %.2lf\n", totalArea);
return 0;
}
You may have noticed that in the code above, the #include "sphere.h"
, is not quite the same as the include for stdio.h. Instead of using angle brackets <>, we use double quotes "". The distinction here has to do with where the compiler expects to find the header file. When you use "", you are suggesting that the header is user defined and the compiler should look for it in the current folder first.
Cohesion and Coupling
Cohesion and Coupling are two terms used to describe two different criterias of function design. Cohesion refers to the relationship of the code within a function. Coupling refers to the relationship of code between functions.
When we write functions we want them to be highly cohesive and loosely coupled. This section looks at these terms and how they apply to program design.
Cohesion
The term cohesion refers to the relation ship of code within a function. A highly cohesive function means that the function performs a single task that is well defined. Note that the task can be both low level (determines if two spheres in 3D space will collide with each other given their size and coordinates) or high level (update all objects on the scene of a video game) . These highly cohesive functions are easy to maintain due to their focus. Everything goes towards the end goal.
Types of Cohesion
- Functional Cohesion: The function performs a single well-defined task.
- Sequential Cohesion: The output from one part of the function serves as input for another part.
- Communicational Cohesion: The function performs tasks that are related by the data they operate on.
- Procedural Cohesion: The function contains multiple tasks that need to be executed in a specific order.
- Temporal Cohesion: The function contains tasks that are related by the timing at which they need to be executed.
- Logical Cohesion: The function contains tasks that are logically related.
- Coincidental Cohesion: The function contains tasks that have little or no meaningful relationship to each other.
Coupling
Coupling refers to the degree of connectivity between functions. Loose coupling is desirable because it means that changes in one function are less likely to affect other functions.
Types of Coupling:
- No Coupling: Functions are completely independent.
- Message Coupling: Functions communicate through message passing.
- Data Coupling: Functions share data through parameters.
- Stamp Coupling: Functions share a composite data structure and use only a part of it.
- Control Coupling: One function controls the flow of another by passing it information on what to do.
- Common Coupling: Multiple functions share the same global data.
- Content Coupling: One function directly modifies or relies on the internal workings of another function.