The concept of modularity in computer software has been espoused for almost five decades. Software architecture embodies modularity; that ...
The concept of modularity in computer software has been espoused for almost five decades. Software architecture embodies modularity; that is, software is divided into separately named and addressable components, often called modules, that are integrated to satisfy problem requirements.
It has been stated that "modularity is the single attribute of software that allows a program to be intellectually manageable". Monolithic software (i.e., a large program composed of a single module) cannot be easily grasped by a reader. The number of control paths, span of reference, number of variables, and overall complexity would make understanding close to impossible. To illustrate this point, consider the following argument based on observations of human problem solving.
Let C(x) be a function that defines the perceived complexity of a problem x, and E(x) be a function that defines the effort (in time) required to solve a problem x. For two problems, p1 and p2, if
C(p1) > C(p2) 1
it follows that
E(p1) > E(p2) (13-1b) 2
As a general case, this result is intuitively obvious. It does take more time to solve a difficult problem.
Another interesting characteristic has been uncovered through experimentation in human problem solving. That is,
C(p1 + p2) > C(p1) + C(p2) 3
Expression 3 implies that the perceived complexity of a problem that combines p1 and p2 is greater than the perceived complexity when each problem is considered separately. Considering Expression (13-2) and the condition implied by Expressions 1, it follows that
E(p1 + p2) > E(p1) + E(p2) 4
This leads to a "divide and conquer" conclusion—it's easier to solve a complex problem when you break it into manageable pieces. The result expressed in Expression 4 has important implications with regard to modularity and software. It is, in fact, an argument for modularity.
It is possible to conclude from Expression 4 that, if we subdivide software indefinitely, the effort required to develop it will become negligibly small! Unfortunately, other forces come into play, causing this conclusion to be (sadly) invalid. Referring to thew figure, the effort (cost) to develop an individual software module does decrease as the total number of modules increases. Given the same set of requirements, more modules means smaller individual size. However, as the number of modules grows, the effort (cost) associated with integrating the modules also grows.
These characteristics lead to a total cost or effort curve shown in the figure. There is a number, M, of modules that would result in minimum development cost, but we do not have the necessary sophistication to predict M with assurance.
The curves shown in figure provide useful guidance when modularity is considered. We should modularize, but care should be taken to stay in the vicinity of M. Undermodularity or overmodularity should be avoided. But how do we know "the vicinity of M"? How modular should we make software?
Another important question arises when modularity is considered. How do we define an appropriate module of a given size? The answer lies in the method(s) used to define modules within a system. Meyer defines five criteria that enable us to evaluate a design method with respect to its ability to define an effective modular system:
Modular decomposability. If a design method provides a systematic mechanism for decomposing the problem into subproblems, it will reduce the complexity of the overall problem, thereby achieving an effective modular solution.
Modular composability. If a design method enables existing (reusable) design components to be assembled into a new system, it will yield a modular solution that does not reinvent the wheel.
Modular understandability. If a module can be understood as a standalone unit (without reference to other modules), it will be easier to build and easier to change.
Modular continuity. If small changes to the system requirements result in changes to individual modules, rather than systemwide changes, the impact of change-induced side effects will be minimized.
Modular protection. If an aberrant condition occurs within a module and its effects are constrained within that module, the impact of error-induced side effects will be minimized.
Finally, it is important to note that a system may be designed modularly, even if its implementation must be "monolithic." There are situations (e.g., real-time software,embedded software) in which relatively minimal speed and memory overhead introduced by subprograms (i.e., subroutines, procedures) is unacceptable. In such situations, software can and should be designed with modularity as an overriding
philosophy. Code may be developed "in-line." Although the program source code may not look modular at first glance, the philosophy has been maintained and the program will provide the benefits of a modular system.