Abstract
It has been recognized since the late sixties that the major source of difficulty and expense in the creation of large computer systems has been the construction and maintenance of the software, while hardware costs have shrunk dramatically in comparison with hardware power. One obvious difference between the software and hardware worlds is in the methodology of design: The hardware designer has a long history of applying well-developed engineering methods to his problem, while the software designer is still in the grip of a pre-industrial, cottage-industry tradition. Where the hardware designer can call on, off-the-shelf modules with well-defined characteristics and standardized interfaces, the programmer usually finds himself constructing his modules and designing the interfaces anew for each problem he encounters. Where new machines are often composed of many parts from their predecessors, new programming systems usually contain only very few pieces of their ancestors, and these almost always modified on an ad hoc basis. In, short, where hardware is engineering, software is art. With the growth of machine capability, there has naturally followed a growth of the problems to which these can be applied, but where the difficulty of building stronger machines grows rather slowly, that of building larger and stronger software seems to grow at a much faster rate. A two-thousand line program is a good deal more than twice, as hard to construct as an one-thousand line program. Where the probability of correct operation of a large computer is constrained largely by the probability of correct operation of its most elementary components, that of a large program is dependent not only on its elementary components, but on interactions between them. These probabilities generally manifest themselves, not as numerical estimates, but in very subjective ways, as difficulties of understanding and coordination. Thus we have the spectacle of a group of programmers attempting to work together, often without any clear understanding of each other's problems, constructing modules of code that work "correctly", only to find that the program fails in subtle and often inexplicable ways when these modules are brought together. The evolution of programming into "software engineering" must be accelerated if the promise of the computer revolution is to be realized. The production of large-scale software systems must somehow be achievable without exponential rates of growth of costs. Although we are still only at the beginning of this evolution, we can already see glimmerings of progress in some areas, namely those involved in the creation and interaction of modules of code, and in the construction of programs, which must utilize these modules. These are the areas that have come to be known as "structured programming" and "top-down programming", respectively. In this paper we will review some of the principles and techniques of structured programming. Section 1 describes a restricted set of control structures whose systematic use allows for easier writing and reading of programs. In Section 2 we present the principles of replacement of the rather rigid syntactic constructions of such structures by simpler lexical ones.