44 MODULARITY $3.I This criterion,like the others,applies to the modules of a system description at any level:analysis,design,implementation. Counter-example:sequential dependencies.Assume some modules have been so designed that they will only function correctly if activated in a certain prescribed order,for example,B can only work properly if you execute it after 4 and before C, perhaps because they are meant for use in"piped"form as in the Unix notation encountered earlier: ABIC Then it is probably hard to understand B without understanding 4 and C too. In later chapters,the modular understandability criterion will help us address two See also,later in this important questions:how to document reusable components;and how to index reusable chapter,.“Sel Documentation”, components so that software developers can retrieve them conveniently through queries. page 54. The criterion suggests that information about a component,useful for documentation or for retrieval,should whenever possible appear in the text of the component itself,tools for documentation,indexing or retrieval can then process the component to extract the needed pieces of information.Having the information included in each component is preferable to storing it elsewhere,for example in a database of information about components. Modular continuity A method satisfies Modular Continuity if,in the software architectures that it yields,a small change in a problem specification will trigger a change of just one module,or a small number of modules. This criterion is directly connected to the general goal of extendibility.As emphasized in See "Extendibiliny". an earlier chapter,change is an integral part of the software construction process.The page 6. requirements will almost inevitably change as the project progresses.Continuity means that small changes should affect individual modules in the structure of the system,rather than the structure itself. The term "continuity"is drawn from an analogy with the notion of a continuous function in mathematical analysis.A mathematical function is continuous if(informally) a small change in the argument will yield a proportionally small change in the result.Here the function considered is the software construction method,which you can view as a mechanism for obtaining systems from specifications: software construction method:Specification System
44 MODULARITY §3.1 This criterion, like the others, applies to the modules of a system description at any level: analysis, design, implementation. • Counter-example: sequential dependencies. Assume some modules have been so designed that they will only function correctly if activated in a certain prescribed order; for example, B can only work properly if you execute it after A and before C, perhaps because they are meant for use in “piped” form as in the Unix notation encountered earlier: A | B | C Then it is probably hard to understand B without understanding A and C too. In later chapters, the modular understandability criterion will help us address two important questions: how to document reusable components; and how to index reusable components so that software developers can retrieve them conveniently through queries. The criterion suggests that information about a component, useful for documentation or for retrieval, should whenever possible appear in the text of the component itself; tools for documentation, indexing or retrieval can then process the component to extract the needed pieces of information. Having the information included in each component is preferable to storing it elsewhere, for example in a database of information about components. Modular continuity This criterion is directly connected to the general goal of extendibility. As emphasized in an earlier chapter, change is an integral part of the software construction process. The requirements will almost inevitably change as the project progresses. Continuity means that small changes should affect individual modules in the structure of the system, rather than the structure itself. The term “continuity” is drawn from an analogy with the notion of a continuous function in mathematical analysis. A mathematical function is continuous if (informally) a small change in the argument will yield a proportionally small change in the result. Here the function considered is the software construction method, which you can view as a mechanism for obtaining systems from specifications: software_construction_method: Specification → System A method satisfies Modular Continuity if, in the software architectures that it yields, a small change in a problem specification will trigger a change of just one module, or a small number of modules. See also, later in this chapter, “SelfDocumentation”, page 54. See “Extendibility”, page 6
$3.1 FIVE CRITERIA 45 Continuity This mathematical term only provides an analogy,since we lack formal notions of size for software.More precisely,it would be possible to define a generally acceptable measure of what constitutes a "small"or"large"change to a program;but doing the same for the specifications is more ofa challenge.If we make no pretense of full rigor,however, the concepts should be intuitively clear and correspond to an essential requirement on any modular method. This will be one of Example 1:symbolic constants.A sound style rule bars the instructions of a program our principles of from using any numerical or textual constant directly;instead,they rely on symbolic style:Symbolic names,and the actual values only appear in a constant definition (constant in Pascal Constant Principle, page 884. or Ada,preprocessor macros in C,PARAMETER in Fortran 77,constant attributes in the notation of this book).If the value changes,the only thing to update is the constant definition.This small but important rule is a wise precaution for continuity since constants,in spite of their name,are remarkably prone to change. See"Uniform Example 2:the Uniform Access principle.Another rule states that a single notation Access",page 55. should be available to obtain the features of an object,whether they are represented as data fields or computed on demand.This property is sufficiently important to warrant a separate discussion later in this chapter. Counter-example 1:using physical representations.A method in which program designs are patterned after the physical implementation of data will yield designs that are very sensitive to slight changes in the environment. Counter-example 2:static arrays.Languages such as Fortran or standard Pascal, which do not allow the declaration ofarrays whose bounds will only be known at run time,make program evolution much harder. Modular protection A method satisfies Modular Protection if it yields architectures in which the effect of an abnormal condition occurring at run time in a module will remain confined to that module,or at worst will only propagate to a few neighboring modules
§3.1 FIVE CRITERIA 45 This mathematical term only provides an analogy, since we lack formal notions of size for software. More precisely, it would be possible to define a generally acceptable measure of what constitutes a “small” or “large” change to a program; but doing the same for the specifications is more of a challenge. If we make no pretense of full rigor, however, the concepts should be intuitively clear and correspond to an essential requirement on any modular method. • Example 1: symbolic constants. A sound style rule bars the instructions of a program from using any numerical or textual constant directly; instead, they rely on symbolic names, and the actual values only appear in a constant definition (constant in Pascal or Ada, preprocessor macros in C, PARAMETER in Fortran 77, constant attributes in the notation of this book). If the value changes, the only thing to update is the constant definition. This small but important rule is a wise precaution for continuity since constants, in spite of their name, are remarkably prone to change. • Example 2: the Uniform Access principle. Another rule states that a single notation should be available to obtain the features of an object, whether they are represented as data fields or computed on demand. This property is sufficiently important to warrant a separate discussion later in this chapter. • Counter-example 1: using physical representations. A method in which program designs are patterned after the physical implementation of data will yield designs that are very sensitive to slight changes in the environment. • Counter-example 2: static arrays. Languages such as Fortran or standard Pascal, which do not allow the declaration of arrays whose bounds will only be known at run time, make program evolution much harder. Modular protection A method satisfies Modular Protection if it yields architectures in which the effect of an abnormal condition occurring at run time in a module will remain confined to that module, or at worst will only propagate to a few neighboring modules. Continuity This will be one of our principles of style: Symbolic Constant Principle, page 884. See “Uniform Access”, page 55
46 MODULARITY $3.2 The underlying issue,that of failures and errors,is central to software engineering.The The guestion ofhow errors considered here are run-time errors,resulting from hardware failures,erroneous to handle abnormal input or exhaustion ofneeded resources(for example memory storage).The criterion does cases is discussed in not address the avoidance or correction oferrors,but the aspect that is directly relevant to detail in chapter 12. modularity:their propagation. Protection violation Example:validating input at the source.A method requiring that you make every More on this topic in module that inputs data also responsible for checking their validity is good for "Assertions are not an input checking mech- modular protection. anism"page 346 Counter-example:undisciplined exceptions.Languages such as PL/I,CLU,Ada, On exception han- C++and Java support the notion of exception.An exception is a special signal that dling,see chapter 12. may be"raised"by a certain instruction and "handled"in another,possibly remote part of the system.When the exception is raised,control is transferred to the handler. (Details of the mechanism vary between languages;Ada or CLU are more disciplined in this respect than PL/I.)Such facilities make it possible to decouple the algorithms for normal cases from the processing of erroneous cases.But they must be used carefully to avoid hindering modular protection.The chapter on exceptions will investigate how to design a disciplined exception mechanism satisfying the criterion. 3.2 FIVE RULES From the preceding criteria,five rules follow which we must observe to ensure modularity: ·Direct Mapping ·Few Interfaces. Small interfaces (weak coupling). Explicit Interfaces. ·Information Hiding The first rule addresses the connection between a software system and the external systems with which it is connected;the next four all address a common issue-how modules will communicate.Obtaining good modular architectures requires that communication occur in a controlled and disciplined way
46 MODULARITY §3.2 The underlying issue, that of failures and errors, is central to software engineering. The errors considered here are run-time errors, resulting from hardware failures, erroneous input or exhaustion of needed resources (for example memory storage). The criterion does not address the avoidance or correction of errors, but the aspect that is directly relevant to modularity: their propagation. • Example: validating input at the source. A method requiring that you make every module that inputs data also responsible for checking their validity is good for modular protection. • Counter-example: undisciplined exceptions. Languages such as PL/I, CLU, Ada, C++ and Java support the notion of exception. An exception is a special signal that may be “raised” by a certain instruction and “handled” in another, possibly remote part of the system. When the exception is raised, control is transferred to the handler. (Details of the mechanism vary between languages; Ada or CLU are more disciplined in this respect than PL/I.) Such facilities make it possible to decouple the algorithms for normal cases from the processing of erroneous cases. But they must be used carefully to avoid hindering modular protection. The chapter on exceptions will investigate how to design a disciplined exception mechanism satisfying the criterion. 3.2 FIVE RULES From the preceding criteria, five rules follow which we must observe to ensure modularity: • Direct Mapping. • Few Interfaces. • Small interfaces (weak coupling). • Explicit Interfaces. • Information Hiding. The first rule addresses the connection between a software system and the external systems with which it is connected; the next four all address a common issue — how modules will communicate. Obtaining good modular architectures requires that communication occur in a controlled and disciplined way. The question of how to handle abnormal cases is discussed in detail in chapter 12. Protection violation More on this topic in “Assertions are not an input checking mechanism”, page 346 On exception handling, see chapter 12
$3.2 FIVE RULES 47 Direct Mapping Any software system attempts to address the needs of some problem domain.If you have a good model for describing that domain,you will find it desirable to keep a clear correspondence (mapping)between the structure of the solution,as provided by the software,and the structure of the problem,as described by the model.Hence the first rule: The modular structure devised in the process of building a software system should remain compatible with any modular structure devised in the process of modeling the problem domain. This advice follows in particular from two of the modularity criteria: Continuity:keeping a trace of the problem's modular structure in the solution's structure will make it easier to assess and limit the impact of changes Decomposability:if some work has already been done to analyze the modular structure of the problem domain,it may provide a good starting point for the modular decomposition of the software. Few Interfaces The Few Interfaces rule restricts the overall number of communication channels between modules in a software architecture: Every module should communicate with as few others as possible. Communication may occur between modules in a variety of ways.Modules may call each other(if they are procedures),share data structures etc.The Few Interfaces rule limits the number of such connections. T①ypes of module interconnection structures (4) (B) (C) More precisely,if a system is composed of n modules,then the number of intermodule connections should remain much closer to the minimum,n-/,shown as (A) in the figure,than to the maximum,n (n-/)/2,shown as (B). This rule follows in particular from the criteria of continuity and protection:if there are too many relations between modules,then the effect of a change or of an error may
§3.2 FIVE RULES 47 Direct Mapping Any software system attempts to address the needs of some problem domain. If you have a good model for describing that domain, you will find it desirable to keep a clear correspondence (mapping) between the structure of the solution, as provided by the software, and the structure of the problem, as described by the model. Hence the first rule: This advice follows in particular from two of the modularity criteria: • Continuity: keeping a trace of the problem’s modular structure in the solution’s structure will make it easier to assess and limit the impact of changes. • Decomposability: if some work has already been done to analyze the modular structure of the problem domain, it may provide a good starting point for the modular decomposition of the software. Few Interfaces The Few Interfaces rule restricts the overall number of communication channels between modules in a software architecture: Communication may occur between modules in a variety of ways. Modules may call each other (if they are procedures), share data structures etc. The Few Interfaces rule limits the number of such connections. More precisely, if a system is composed of n modules, then the number of intermodule connections should remain much closer to the minimum, n–1, shown as (A) in the figure, than to the maximum, n (n – 1) /2, shown as (B). This rule follows in particular from the criteria of continuity and protection: if there are too many relations between modules, then the effect of a change or of an error may The modular structure devised in the process of building a software system should remain compatible with any modular structure devised in the process of modeling the problem domain. Every module should communicate with as few others as possible. Types of module interconnection structures (A) (B) (C)
48 MODULARITY $3.2 propagate to a large number of modules.It is also connected to composability (if you want a module to be usable by itself in a new environment,then it should not depend on too many others),understandability and decomposability. Case (A)on the last figure shows a way to reach the minimum number of links,n 1,through an extremely centralized structure:one master module;everybody else talks to it and to it only.But there are also much more"egalitarian"structures,such as (C)which has almost the same number of links.In this scheme,every module just talks to its two immediate neighbors,but there is no central authority.Such a style of design is a little surprising at first since it does not conform to the traditional model of functional,top-down design.But it can yield robust,extendible architectures;this is the kind of structure that object-oriented techniques,properly applied,will tend to yield. Small Interfaces The Small Interfaces or "Weak Coupling"rule relates to the size of intermodule connections rather than to their number: If two modules communicate,they should exchange as little information as possible An electrical engineer would say that the channels of communication between modules must be of limited bandwidth: Communication X.V bandwidth between modules The Small Interfaces requirement follows in particular from the criteria of continuity and protection. An extreme counter-example is a Fortran practice which some readers will recognize: the "garbage common block".A common block in Fortran is a directive of the form COMMON Icommon_namel variablej...variable indicating that the variables listed are accessible not just to the enclosing module but also to any other module which includes a COMMON directive with the same common name. It is not infrequent to see Fortran systems whose every module includes an identical gigantic COMMON directive,listing all significant variables and arrays so that every module may directly use every piece of data
48 MODULARITY §3.2 propagate to a large number of modules. It is also connected to composability (if you want a module to be usable by itself in a new environment, then it should not depend on too many others), understandability and decomposability. Case (A) on the last figure shows a way to reach the minimum number of links, n – 1, through an extremely centralized structure: one master module; everybody else talks to it and to it only. But there are also much more “egalitarian” structures, such as (C) which has almost the same number of links. In this scheme, every module just talks to its two immediate neighbors, but there is no central authority. Such a style of design is a little surprising at first since it does not conform to the traditional model of functional, top-down design. But it can yield robust, extendible architectures; this is the kind of structure that object-oriented techniques, properly applied, will tend to yield. Small Interfaces The Small Interfaces or “Weak Coupling” rule relates to the size of intermodule connections rather than to their number: An electrical engineer would say that the channels of communication between modules must be of limited bandwidth: The Small Interfaces requirement follows in particular from the criteria of continuity and protection. An extreme counter-example is a Fortran practice which some readers will recognize: the “garbage common block”. A common block in Fortran is a directive of the form COMMON /common_name/ variable1,… variablen indicating that the variables listed are accessible not just to the enclosing module but also to any other module which includes a COMMON directive with the same common_name. It is not infrequent to see Fortran systems whose every module includes an identical gigantic COMMON directive, listing all significant variables and arrays so that every module may directly use every piece of data. If two modules communicate, they should exchange as little information as possible Communication bandwidth between z modules x, y