Maintainability includes code organization. Understanding modularity helps us organize code modules for maintenance purpose. Understanding cohesion helps us decide how to organize modules to help us locate reusable components and avoid reinventing the wheel on something we cannot find. Understanding coupling helps us structure modules to create resilient code that are less likely to break when changes are made to the code.
An independent component that can be combined with other independent components (modules) to produce a more complex component.
The concept of modularity revolves around two principles: high cohesion and low coupling.
Codes are desired to be as cohesive (logical and consistent) as possible. Cohesion from low to highest:
Components are grouped into modules in a haphazard way. There is no significant relation between the components.
Components realize tasks that are logically related. One example is a module that contains all input routines. These routines do not call one another and they do not pass information to each other. Their function is just very similar.
A typical example of this type of cohesion is an initialization module. The various components of it are independent but they are activated at about the same point in time.
A module exhibits procedural cohesion if it consists of a number of components that have to be executed in some given order. For instance a module may have to first read some datum, then search a table, and finally print a result.
This type of cohesion occurs if the components of a module operate on the same (external) data. For instance, a module may read some data from a disk, perform certain computations on those data, and print the result.
Sequential cohesion occurs if the module consists of a sequence of components where the output of one component serves as input to the next component.
In a module exhibiting functional cohesion all components contribute to the one single function of the module. Such a module often transforms a single input datum into a single output datum. The well-known mathematical subroutines are a typical example of this. Less trivial examples are modules like 'execute the next edit command' and 'translate the program given.'
Coupling is the dependency of each module on other modules. Low coupling (modules should be as independent as possible) is desired. Coupling from highest to lowest:
With content coupling, one module directly affects the working of another module. Content coupling occurs when a module changes another module's data or when control is passed from one module to the middle of another (as in a jump). This type of coupling can, and should, always be avoided.
With common coupling, two modules have shared data. The name originates from the use of COMMON blocks in FORTRAN. Its equivalent in block-structured languages is the use of global variables.
With external coupling, modules communicate through an external medium, such as a file.
With control coupling, one module directs the execution of another module by passing the necessary control information. This is usually accomplished by means of flags that are set by one module and reacted upon by the dependent module.
Stamp coupling occurs when complete data structures are passed from one module to another. With stamp coupling, the precise format of the data structures is a common property of those modules.
With data coupling, only simple data is passed between modules.