Tải bản đầy đủ (.pdf) (10 trang)

Software Engineering For Students: A Programming Approach Part 12 pps

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (155.28 KB, 10 trang )

88 Chapter 7 ■ Structured programming
One view of structured programming is that it holds that programs should only be
built from three components: sequences (normally written in the order in which the
statements are to be executed), selections (normally written as
if-then-else), and
repetitions (written as
while-do). The goto statement is, by implication, banned. In
this chapter we begin by examining the controversy about the
goto statement. The
outcome of the argument is that
gotos are an irrelevancy; the argument is about some-
thing else, good program structure. We go on to explore the significant principles of
structured programming.
There are some other principles. We will explore these using flowcharts, which
describe flow of control. A flowchart is read from the top downwards or in the direc-
tion of the arrows. Flowchart decisions (corresponding to
if or while statements in
code) are drawn as diamonds. Flowchart activities are shown as rectangular boxes. A
flowchart is very similar to a UML activity diagram and conveys the same information.
If the three structures of structured programming are diagrammed as flowcharts
(Figure 7.1), the following characteristics become clear:
1. they have only one entry and exit
2. none of the constructs consists of more than three boxes
Figure 7.1 The three structures of structured programming
Figure 7.2 A control structure that is not structured
BELL_C07.QXD 1/30/05 4:19 PM Page 88
7.2 Arguments against goto 89
If we visualize any one of the three constructs as they are used, then a third character-
istic is evident:
3. the entry is at the start and the exit is at the end.
Why is it that these characteristics are important? Why are other constructs that


have the same characteristics (Figure 7.2) ruled out? We now go on to look at these
questions.
SELF-TEST QUESTION
7.1 Write a loop that repeats ten times, first using a while statement, then
using
goto.
gotos are unnecessary
Fortunately there is a mathematical theorem (thanks to Bohm and Jacopini) guaran-
teeing that any program written using
goto statements can be transformed into an
equivalent program that uses only the structured constructs (sequence, selection and
iteration). The converted program will, in general, need additional data items that are
used as flags to control the actions of the program. Indeed the new program may look
rather contrived; nonetheless, it can be done. On the face of it, therefore, there is no
need for programs with
gotos in them.
Note, as an interesting side issue, that the theorem does not tell us how to transform
the unstructured program; only that it can be done.
Experimental evidence
Structured programming is well established and widely regarded as the best approach
to programming. You might think, therefore, that there would be clear evidence from
real software projects that it is beneficial, but this is not so; there are no convincing
results from real projects, largely because a carefully controlled experiment would be
difficult and expensive to mount. It would be necessary to develop a particular piece of
software in two ways: once using structured programming and again using “unstruc-
tured” programming. All other variables, like the expertise of the programmers, would
have to be held constant. The two versions of the software could be compared accord-
ing to criteria like development time and number of errors. Regrettably, there are no
results of this type.
However, experimenters have carried out small-scale studies comparing how easily

people can understand and debug small structured programs compared with unstruc-
tured ones. In a typical experiment, each of a group of subjects is presented with the
7.2

Arguments against goto
BELL_C07.QXD 1/30/05 4:19 PM Page 89
listing of a program that is written in a structured way and asked a series of questions
that are designed to assess their comprehension of it. The accuracy of the replies and
the time taken to reply are both measured. These are measures of the ease with which
the program could be debugged or changed. A second group of subjects are given
copies of the same program rewritten in an unstructured way. The accuracy and
response times of the two groups are compared. The results of these experiments gen-
erally indicate that structured programs are superior to unstructured ones.
The results of empirical studies are reviewed in the literature given at the end of
the chapter. In a review published in 1984, long after the dust had settled on the
structured programming debate, Vessey and Weber concluded that “the evidence
supporting [structured programming] is weak”. This conclusion largely stems from
the difficulty of carrying out experiments that give trustworthy results.
Clarity and expressive power
Compare the following two equivalent program fragments:


label: while a > 0


if a > 0 goto label endwhile


As we read down the first program fragment, we are not immediately sure what the
roles of the label and

goto are. It would take us some time to read and study the pro-
gram in order to discover that they are being used to create the repetition of a piece of
code. This is made immediately obvious by the
while statement in the second pro-
gram. Worse, there is a remaining doubt in the first program that there may be another
goto aimed at this same label from some other point in the program.
The facilities of a programming language should allow people to describe what they
want to do in a meaningful way. If we examine a typical program written using
gotos
we see that the
gotos are used for a variety of purposes, for example:
■ to avoid a piece of code (which is to be executed in different circumstances)
■ to perform repetition
■ to exit from the middle of a loop
■ to invoke a shared piece of code.
When we see a
goto, there are few clues that allow us to decide the purpose for
which the
goto is being used. The alternative is, of course, a unique language con-
struct for use in each of these different circumstances. These are, respectively:
90 Chapter 7 ■ Structured programming
>
>
BELL_C07.QXD 1/30/05 4:19 PM Page 90
7.2 Arguments against goto 91
■ if-then-else
■ while-do or repeat-until
■ exit
■ method call
It is as if the

goto is too primitive an instruction – like a machine instruction to load
a register – that can be used in a whole variety of circumstances, but does not clearly
convey its meaning in any of them.
In summary, the
goto lacks expressive power and it is therefore difficult to under-
stand the logic of a program that is written using a lot of
gotos. When we look at a
piece of coding, words like
while and if give us a strong clue as to what is intended;
gotos do not.
How many pencils?
Suppose we want to read a program in order to understand it by tracing through it as
if we were a computer executing it. Suppose we have available a supply of pencils (or
fingers) to help us. The pencils will be used as markers, and are to be placed on the pro-
gram listing to point to places of interest.
If we are following a simple sequence, then we will only need one pencil to keep
track of our position. If we encounter a method call, we need two pencils, one to leave
at the point of the call (in order to know where to return) and another to proceed into
the method.
If we encounter a
while statement or a for loop, then we need an integer, a counter,
to keep count of the number of times we have repeated the loop.
To summarize, if the program has been written in a structured way, we need:
■ one pencil to point to the current position
■ one pencil to point to each method call that has been executed but not returned from
■ a counter for every uncompleted loop.
This may seem like a lot of equipment, but consider the alternative of a program that
contains a lot of
gotos. As before, we will need to indicate the position of the current
statement. Next, we need a pencil to point at every

goto that has been executed. But
now, whereas in the structured program we can remove a pencil whenever we return
from a method, finish a loop or complete an
if statement, we can never dispense with
pencils; instead we need ever more. The increased number of pencils reflects the
increased complexity of the
goto program.
The real problem becomes evident when we want to refresh our memory about what
happened before we arrived at the current point in the program. In the program with-
out
gotos we simply look back up the program text. In the unstructured program,
when we look backwards we are defeated as soon as we reach a label, because we have
no way of knowing how we reached it.
BELL_C07.QXD 1/30/05 4:19 PM Page 91
92 Chapter 7 ■ Structured programming
Ease of reading (static and dynamic structures)
In the Western world we are used to reading left to right and top to bottom. To have to
begin by reading forwards and then to have to go backwards in the text is rather unnatural;
it is simpler if we can always continue onwards. It is an important feature of a structured pro-
gram that it can always be read from top to bottom – provided it has no methods. The excep-
tion to this rule arises in comprehending a
while loop, during which repeated references
back to the terminating condition at the start of the loop are necessary.
Programs are essentially dynamic beings that exhibit a flow of control, while the pro-
gram listing is a static piece of text. To ease understanding, the problem is to bring the
two into harmony – to have the static text closely reflect the dynamic execution. In a
structured program, the flow of control is always down the page, which exactly corre-
sponds to the way that text is normally read.
Proving programs correct
Formally to prove all programs correct is not a practical proposition with present-day

techniques. Nonetheless there are some lessons that can be learned from proving.
In one technique of program proving, assertions are made at strategic points in the
program. An assertion is a statement of what things are true at that point in the pro-
gram. More exactly, an assertion describes the relationships that hold between data
items that the program acts upon. Assertions at the start and end of a piece of program
are called the input and output assertions respectively. Proving consists of rigorously
demonstrating that if the input assertion is true, then the action of the program will
lead to the output assertion being true.
A structured program consists solely of components that have a single entry and a
single exit point. This considerably aids the process of reasoning about the effect of the
program. In contrast, it is usually impossible to isolate single-entry, single-exit struc-
tures within a program with
gotos in it.
Even when formal proof techniques are not being used, but where an informal study
of the program is being made, the single-entry and single-exit character of programs
aids checking and understanding.
Deskilling
The goto statement is one tool among many provided by the programming language. To
take it away from the programmer is to deprive him or her of a tool that can be validly
used in certain circumstances.
Consider a craftsperson who is an expert at making delicate objects from wood.
Suppose that we remove from that person a tool that we consider to be inappropriate,
say an ax. The skill of making a discriminating selection among the available tools is
reduced, because the choice is narrower. Furthermore, the skill in using the tool is no
7.3

Arguments in favor of goto
BELL_C07.QXD 1/30/05 4:19 PM Page 92
7.3 Arguments in favor of goto 93
longer required. (Remember, however, that there may occasionally be circumstances in

which an ax is the most suitable tool.)
Exceptions
Often a program is required to detect an error and to take some special action to deal
with it. Suppose that such an error is detected many levels down in a chain of method
calls. One way of handling the error is to create an additional parameter associated with
each method call. This approach can become very unwieldy as methods receive and
merely pass on parameters that they do not need to act on.
An alternative is for the method detecting the error to simply
goto a suitable place
in the program where the error can be dealt with. This can result in a significant sim-
plification to the program. The essence of the argument is that an exceptional situation
in the program demands an exceptional solution – a
goto.
Some programming languages, such as Java, have solved this problem using a special
mechanism for handling exceptional situations.
Program performance
On occasions it is possible to write a program that will run more quickly using goto
statements. An example is a program to search an array a for an item x:
for i = 1 to tableSize
if a[i] = x then goto found endif
endfor
notfound:


found:


The nearest we can get to writing this as a structured program is to write:
i = 1
while i <= tableSize and a[i] not = x

i = i+1
endwhile
if i > m then


else
>
>
>
BELL_C07.QXD 1/30/05 4:19 PM Page 93
94 Chapter 7 ■ Structured programming


endif
which requires an additional test. Although both programs achieve the same end – finding
(or not finding) the desired item – the steps taken by the two programs differ. The first
(unstructured) program takes fewer steps, and there is no way of writing a structured pro-
gram that works in the same way. Thus it is possible to write
goto programs that run
more quickly than structured ones.
Naturalness
Consider the table searching program above. Arguably the unstructured solution is the
best in the sense that it is the solution that solves the problem most naturally. Any trans-
formation of this program, or any other solution, is a distortion of the natural solution.
In other words, getting rid of
gotos in existing programs (as can always be done), will
sometimes needlessly destroy a good program.
The trouble is deciding what is natural. It surely differs from person to person,
depending on individual psychology and cultural experiences. So it is a rather subjec-
tive judgment.

Rather than take part in a parochial debate about the merits of a particular control
structure, let us take a constructive approach. If we had a free choice and a blank piece
of paper, what control structures would we choose to use in programming? Perhaps our
first consideration should be to establish the principles that govern the selection. Let us
examine the following criteria:
■ standardization
■ abstraction
■ expressive power
■ orthogonality
■ minimality.
We shall see that some of these conflict with each other. Note also that in our examin-
ation we are confining ourselves to sequential, imperative programming, in contrast to
concurrent or declarative programming (as in logic or functional programming).
Standardization
Domestic appliances exhibit enormous variety and yet all plug into a standard socket.
Similarly, it is desirable to build software from components that all exhibit the same
external interface.
7.4

Selecting control structures
>
BELL_C07.QXD 1/30/05 4:19 PM Page 94
7.4 Selecting control structures 95
The simplest interface comprises one entry point, at the start, and one exit point at
the end. This has the strength of being consistent with the essence of sequential pro-
gramming. It also conforms to the important idea of calling a method. We are used to
the idea of calling a method as a sequential step and returning from it to the next
instruction in sequence. (We do not, for example, expect to supply a label as a param-
eter to which control is returned.)
Abstraction

This is probably the most important idea in structured programming. The human mind
cannot devise or understand the whole of a complex system. Instead we can only under-
stand one part of the system at a time. Nonetheless it is vital to understand the whole
system. The only way to resolve these contradictory statements is to be able to perceive
the overall structure in a digestible way. The solution is to use abstraction, that is, the
system must be described in a notation that allows subsystems to be seen as black boxes
whose task is readily understood but whose detail is invisible. In programming, the
method has long been a mechanism that fulfills this role.
Other constructs that possess the same single-entry at the start, single-exit at the end
property, are
if-then-else and while-do.
Expressive power
In discussing the arguments against the goto statement, we saw that the goto is too
primitive. It has more to do with describing what a machine will do than what a pro-
grammer intends. Instead we look at the range of structures on offer, tempted on the
one hand to seize every mechanism available, while at the same time conscious of the
need for minimality.
Certainly we need some mechanism for repetition, and either a
while statement or
recursion is sufficient to provide this facility. Many languages provide both a
while
statement and a repeat-until statement. Most languages also support recursion.
Arguably we also require a statement to carry out a choice of actions following a test.
The
if-then-else fulfills this requirement, but others are equally valid, including the
case statement. Again, we are torn between expressive power and minimality.
Orthogonality
When designing a set of facilities, a good design principle is to create features that are
each as different from each other as possible. If this is so, we can more easily satisfy the
goal of a minimum number of functions, while at the same time ensuring that the facil-

ities are sufficiently powerful for all our needs.
Minimality
The principle of minimality curbs our tendency to include too many facilities. A conse-
quence of Bohm and Jacopini’s theorem is that we know that the three control structures
BELL_C07.QXD 1/30/05 4:19 PM Page 95
96 Chapter 7 ■ Structured programming
(sequence, selection and iteration) are sufficient. (Strictly, a construct for iteration, such
as a
while, is also unnecessary, because any loop that can be written iteratively can also,
in theory, be achieved using only recursion.) Consider the flowcharts of various control
structures. Sequence has one box,
while has two, and if has three boxes. There are
other control structures that involve only three or less boxes; but from amongst them all,
these are the minimal feasible set.
It is easy to become engrossed in the arguments about the
goto statement, but is this
the central issue of structured programming?
Can a program that is written using only the three structures claim to be well struc-
tured? The answer is no; it is possible to create a bad program structure using the three
structures, just as it is possible (with greater difficulty) to create a good structure that
uses
goto statements. To illustrate why this is so, consider a badly structured program
that has been written using many
gotos. If we now transform this into a program that
uses the three structures, we still have a badly structured program, since we have done
nothing significant to improve it.
As a second example, consider a program to search a table for a required item. Two
alternative solutions, one structured, the other not, were compared earlier. However,
arguably, neither of these is the best solution. Here is another, in which the item being
sought is first placed at the end of the table:

a[tableSize + 1] = x
i = 1
while a[i] not = x
i = i + 1
endwhile
if i = tableSize + 1
then

else

endif
This is arguably the best of the solutions because it is less complex (the condition in the
while statement is simpler) and would execute more quickly on a conventional computer
(for the same reason that there is only one condition to test). This example illustrates that
the use of the approved structures does not necessarily guarantee the best design.
A structured program is essentially one that can be understood easily, and the most
useful tool in understanding is abstraction. Abstraction is concerned with identifying
the major elements of what is being studied, and ignoring detail. Such is the complex-
ity of software that we have to do this in order to stand a chance of understanding it.
7.5

What is structured programming?
>
>
BELL_C07.QXD 1/30/05 4:19 PM Page 96
7.5 What is structured programming? 97
Abstraction can only be achieved if the control flow constructs are used in a disci-
plined way, so that part of structured programming is the avoidance of
gotos. For
example, consider the program in Figure 7.3.

We can draw boxes around components as shown. Because it is built from limited
control structures, we can view the program at all levels of detail as consisting of
abstract components that have only one entry and one exit. If we examine any subsys-
tem of the program, it is totally contained – the boxes do not overlap. If we look in
detail at its contents, it does not suddenly sprout connections with other subsystems.
When we uncover the nested contents of a traditional Russian wooden doll, we do not
expect suddenly to encounter a doll that affects any of those we have already seen.
(Structured programs are, of course, more complex than these dolls; it is as if, when we
open a doll, not just one, but several more are revealed.)
Suppose that in the above program we inserted a
goto as shown in Figure 7.4. We
have now ruined the structure, since we can no longer view the program at different
levels of abstraction.
As an analogy compare the problems of understanding a plate of spaghetti as com-
pared with a plate of lasagna. In order to understand the spaghetti, we have to under-
stand it all; we cannot employ abstraction. With the lasagna, we can peel off layers, one
by one, uncovering the interesting detail of successive layers and understanding each
separately from the others.
while do
if
then
else
endif
endWhile
if
then
endif
Figure 7.3 A structured program, showing self-contained components
BELL_C07.QXD 1/30/05 4:19 PM Page 97

×