Edward Yourdon and Larry L. Constantine.compiled by Tom Verhoeff in July 2000. Bold face emphasis is mine.
Structured Design: Fundamentals of a Discipline of Computer Program and System Design
Prentice-Hall, 1979 (Facsimile edition 1986).
ISBN 0-13-854471-9 [See this book at Amazon.com]
|1||Toward Program Engineering||3|
|2||Basic Concepts of Structured Design||17|
|3||The Structure of Computer Programs||30|
|4||Structure and Procedure||48|
|5||Human Information Processing and Program Simplicity||67|
|8||The Morphology of Simple Systems||145|
|12||Alternative Design Strategies||245|
|13||Communication in Modular Systems||259|
|15||Optimization of Modular Systems||290|
|16||A Typology of Systems Components||307|
|18||Homologous and Incremental Structures||331|
|Section VI||THE REAL WORLD||351|
|19||Structure and Program Quality||353|
|20||Implementation of Modular Systems||375|
|21||The Management Milieu||395|
|A.||Structure Charts: A Guide||409|
|B.||Summary of Standard Graphics for Program Structure Charts||437|
Structured design is the process of deciding which components interconnected in which way will solve some well-specified problem.
``Design'' means to plan or mark out the form and method of a solution.
By partitioning we mean the division of the problem into smaller subproblems, so that each subproblem will eventually correspond to a piece of the system. The questions are: Where and how should we divide the problem? Which aspects of the problem belong in the same part of the system, and which aspects belong in different parts? Structured design answers these questions with two basic principles:
The other major aspect of structured design is organization of the system. That is, we must decide how to interrelate the parts of the system, and we must decide which parts belong where in relation to each other.
Black boxes have numerous interesting properties, the most important of which is that we can use them. A true black box is a system which can be fully exploited [by knowing the interface and] without knowledge of what is inside it.
Whenever a function or capability is seen as being required during the design of a system, define it as a black box and make use of it in the system without concern for its structural or methodological realization.Eventually, of course, each such invoked black box must in turn be designed, a process which may give rise to more black boxes and so on.
[I]t is all but impossible to simplify significantly the structure of an existing program or system through after-the-fact modularization. Once reduced to code, the structural complexity of a system is essentially fixed. It is, thus, clear, that simple structures must be designed that way from the beginning.
The data-oriented technique that we will use is called data flow graph. The same model is also known as a data flow diagram [DFD], or a program graph or even a ``bubble chart.'' The elements of the data flow graph are called transforms and are represented graphically by small circles (or ``bubbles'' ...). ... [T]he transforms represent transformations of data ... from one form to another form. The data elements are represented by labeled arrows connecting one transform bubble to another.
Every computer system has structure --- that is, it is made up of components that are interconnected. ... Regardless of how a system was developed, whether its structure was designed or determined by accident, we can document the modular structure.
That most of the cost of systems development today is due to errors is not something to be denied, but rather an insight to be traded upon. Indeed, this is so vital that no theory of programming or programs, no technique or practice for programming or systems design, which does not give central recognition to the role of bugs and debugging, can be of much value in the practical amelioration of the pains in the field.
The psychologist-mathematician George Miller, in a summary of a very large body of research, first described the human information processing limitations that give rise to this effect. It appears that people can metnally juggle, deal with, or keep track of only about seven objects, entities, or concepts at a time. In effect, the immediate recirculating memory needed for problem-solving with multiple elements has a capacity of about 7±2 entities. Above that number, errors in the process increase disproportionately.
The measure that we are seeking is known as coupling; it is a measure of the strength of interconnection. ... Obviously, what we are striving for is loosely coupled systems --- that is, systems in which one can study (or debug, or maintain) any one module without having to know very much about any other modules in the system.
Coupling as an abstract concept --- the degree of interdependence between modules --- may be operationalized as the probability that in coding, debugging, or modifying one module, a programmer will have to take into account something about another module.
``Intramodular functional relatedness'' is a clumsy term. What we are considering is the cohesion of each module in isolation --- how tightly bound or related its internal elements are to one another.
Clearly, cohesion and coupling are interrelated. The greater the cohesion of individual modules in the system, the lower the coupling between modules will be. ...
Both coupling and cohesion are powerful tools in the design of modular structures, but of the two, cohesion emerges from extenisve practice as more important.
... Note that the mosque shape characteristically has a higher fan-out in the high-level modules, and higher fan-in in the bottom-level modules.
... It was derived empirically from a careful review of the morphology of systems, comparing systems that had proven to be cheap to implement, to maintain, and to modify with ones that had been expensive. ... The study ... produced what came to be called the transform-centered model. Most of the cheap systems had it; none of the costly systems did! Since then, of course, support for highly factored transform-centered design has become widespread, and is based on both experience and numerous studies.
Now we can state a design heuristic that involves both scope of control and scope of effect:
For any given decision, the scope of effect should be a subset of the scope of control of the module in which the decision is located.In other words, all of the modules that are affected, or influenced, by a decision should be subordinate ultimately to the module that makes the decision.
Transform analysis, or transform-centered design, is a strategy for deriving initial structural designs that are quite good (with respect to modularity) and generally require only a modest restructuring to arrive at a final design.
The transform analysis strategy consists of the following four major steps:
Afferent data elements are those high-level elements of data that are furthest removed from physical input, yet still constitute inputs to the system.
Thus, afferent data elements are the highest level of abstraction to the term ``input to the system.''
Transaction analysis is suggested by data flow graphs ... where a transform splits an input data stream into several discrete output substreams.
A transaction is any element of data, control, signal, event, or change of state that causes, triggers, or initiates some action or sequence of actions.
However, these two strategies are not the only way of deriving good designs in a systematic manner.
Implicit in the data-structure approach is the fact that most ... applications deal with hierarchies of data --- e.g., fields within records within files. Thus, this approach develops a hierarchy of modules that, in some sense, is a mirror image of the hierarchy of data associated with the problem.
Since the highly modular approach of structured design has been proved to reduce programming, it is extremely unlikely that a central feature --- namely normal subroutine calling --- should increase programming over all.
We should point out, however, that the cost of normal communication is not so terribly excessive in most high-level programming languages.
If the designer feels that every minute of coding time is precious, that nary a microsecond of CPU time can be wasted, and that future modifications to the system are unlikely, so be it! We concerned only with the fact that many pathological communications are designed unconsciously or casually --- or they result from a long-standing prejudice that all normal communications are bad because they require too much CPU time.
The term packing refers to the assignment of the modules of a total system into sections handled as distinct physical units for execution on a machine. ... For some systems, programs are the load units; in others, we see the terms ``overlays,'' ``load module,'' ``job step,'' and so forth.
[O]ptimization should be discussed from a rational point of view: Not every microsecond of computer time has to be optimized! The following [15.1.1 -- 15.1.6] philosophies are important to keep in mind ...
There is not much point in talking about efficient systems or optimization if the system is being designed and/or programmed by people of only mediocre talent. Of course, this is a rather sensitive issue. One's ego makes it difficult to deal with one's own mediocrity, and one's manners make it difficult to accuse colleagues of mediocrity. Nevertheless, it is a fact that shoud be faced squarely: A surprisingly large number of analyst / designers design stupid systems, and an even larger number of programmers write horribly stupid code.
These are blunt words, to be sure. However, a classic study by Sackman et al. pointed out that, among experienced programmers, we can find a 25:1 difference in design time and debugging time. Equally disturbing is the fact that the resulting code can vary in speed and size by a factor ten. The most depressing fact of all was that Sackman's study indicated that there was no correlation between programming performance and scores on programming aptitude tests. H. L. Mencken observed that nobody ever went broke underestimating the intelligence of the American public. After visiting programming organizations around the country, the authors have concluded, somewhat sadly, that a similar statement could be made about programmers and designers.
Our point is simple: There is no substitute for competence. If you want a system designed and implemented efficiently, make sure it is done by people who know what they are doing --- which, by the way, has very little to do with the number of years they have been working in the computer field!
Knuth's classic study indicates that approximately 5 percent of the code in a typical program consumes approximately 50 percent of its execution time. [cf. Amdahl's Law]
15.1.4 Simple modular systems can be optimized easily
15.1.6 Optimization is irrelevant if the program doesn't work
The specific techniques for optimizing code within a module are largely outside the scope of this book. We know that optimizing compilers are becoming increasingly significant. ...
However, we can suggest an organized plan of attack ... for optimizing the code within modules of a large system. ...:
Fortunately there is only a small set of structural modifications that make noticeable improvements in execution speed (and perhaps, in memory).
Homologous, or non-hierarchical, systems arise from any control relationship that does not define a hierarchy of control responsibility.
However, there are additional qualities that usually are associated with good systems; among the common ones are generality, flexibility, and reliability.
The most persistent myth of generality and generalization is that most general systems --- by religious principle --- cost more to design and more to build.
The techniques for developing reliable computer hardware --- redundancy, self-checking data and computations, majority voting logic, duplicated systems, fall-back and switchover, and the like --- are such that hardware can now be made arbitrary reliable. Similar concepts in software have been almost totally absent until recently ...
No software system of any realistic size is ever completely ... error-free.
Consider what happens when we execute two copies of the same program (or the same program twice). If the results disagree, it is indicative of a hardware failure, not a software failure. ... Thus, it is clear that software redundancy must be achieved through non-identical components, implying a comparatively larger development cost.
It is an almost universal rule of thumb that faults should be detected as early as possible --- that is, close to the source at some interface.
The design philosophy that yields greater reliability is the one that requires every function to protect itself, validating its own data.
The preferred way to build a general-purpose system is not to build one computer program that will do all things for all people. Instead, what one should do is build a large number of small, single-purpose modules that are flexible and that have extremely clean interfaces. The generality comes from the almost infinite number of combinations of such modules ...
In contrast, ... an incremental approach can be paraphrased in the following manner:
The concept of a dummy module, or stub, is an important aspect of top-down implementation.
The structure of a system reflects the structure of the organization that built it.Conway's Law has been stated even more strongly:
The structure of any system designed by an organization is isomorphic to the structure of the organization.
[W]e ... suggest, for the sake of management, that a complete (or nearly complete) structural design be accomplished first, using all of the principles of coupling, cohesion, transform-centered design, and others previously discussed. When this has been accomplished, we suggest that coding and testing be accomplished in an incremental fashion...
21.2.1 Reliable cost estimating
21.2.3 Parallel development of acceptance and validation criteria
coroutine: a module whose point of activation is always the next sequential statement following the last point at which the module deactivated itself by activating another coroutine.
coupling: a measure of the strength of interconnection between one module and another.