Document 204317

HOW TO DEVELOP MODULELOGIC USING
PSEUDO-CODE AND STEPWISE REFINEMENT
o This method is easier to produce, to change, and to
read than the design presented in flowchart form.
Trying to follow the logic of a module flowcharted
in more than two pages is quite d i f f i c u l t . The
reader's concentration is often broken by flipping
through the pages and trying to remember the point
to return to in order to continue the logic flow.
Flowchart updating is very seldom done. Flowcharts
usually are drawn i n i t i a l l y with a l l the design
changes being kept in the designer's mind, then are
redrawn at the completion of the project, shortchanged because of time and money overruns, thus,
leaving the design process undocumented during i t s
development.
Anthony A. Lekkos
University of Houston, Clear Lake
Carl M. Peters
University of Texas at Dallas
Abstract: The use of pseudo-code and the stepwise refinement process in developing the logic of
modules is discussed, and the advantages of this
method are analyzed. An example is given to i l l u s trate the steps to be taken in analyzing the function,
selecting data structure and algorithm, abstracting
the function in pseudo-code, expanding the function
into subfunctions, and f i n a l l y , verifying the function.
The key to a good module design is rewriting and
more rewriting. The f i r s t idea is very seldom the
best idea. With the help of a pseudo-language
processor or a text editor the pseudo-code can be
easily changed. And remember rethinking and reworking is the rule in a good design. Appendix A
suggests some rules to be followed using pseudocode.
Keywords: pseudo-code, stepwise refinement,
developing modules logic.
I.
Introduction
The computer age has seen an amazing growth,
and as in a l l things, i t s increasing size leads to a
disproportionately increasing complexity. Therefore,
much of the programming a c t i v i t y is now directed
towards managing the complexity instead of designing
e f f i c i e n t programs.
o Pseudo-code can be easily converted to executable
code. In fact, i t would be similar to some
programming languages such as COBOLor PL/I.
o Pseudo-code helps teach structured programming.
Traditionally, the teaching of programming was
associated with teaching the syntax of a programming language, which is s t i l l true in most colleges.
In addition, teaching programming was almost always
associated with mathematical problem assignments
that advocate the coding rather than the programming statements. However, this method is not
actually programming, which explains why software
can be so costly and yet so unreliable.
Until recently, flowcharts were used to create
the required details on how the logic of a module
(subroutine, procedure, function, etc.) should be
coded. Although flowcharts proved adequate for
smaller and less complex applications, i t was
recognized in the early 1970's that most applications
were too complex t~ be described and specified by the
use of flowcharts. • The increased size and complexity
of applications have now outgrown the capability and
scope of flowcharting, setting the stage for a new
technique, i . e . , the use of a pseudo-language as a
tool for designing detailed programs prior to coding.
2.
Students in colleges should be introduced to
the pseudo-code concept prior to learning the
details of a programming language. They should be
encouraged to conceive a solution to the problem
and record the steps required to solve the problem
in an English-like language, the pseudo-code.
Introducing pseudo-code is the best way to teach
structural programming because i t is an informal
method of expressing structured programming logic.
The Adyantages of Usin9 Pseudo-code
By using a pseudo-code language, the module logic
is produced and presented in a top-down fashion and is
oriented towards being easily understood by people.
The later issue is a fundamental one that has been
addressed collectively by a l l software engineering
techniques in order to produce programs with easier
maintainability and understandability. The purpose
for designing the logic of a module using a pseudolanguage is to communicate the designer's idea to other
people and not to a computer.2 Thus, suggestions,
criticisms, and modifications can be incorporated into
the design, and possibly, resulting in complete
rewriting of major sections.
o Pseudo-code is used by the stepwise refinement
process in a specific and systematic way to
develop the detailed logic of a module. This stepby-step process involves describing the function of
a module in very high-level pseudo-code and expanding i t into subfunctions, again described by pseudocode, until the lower level of program details is
reached.
o
Other advantages of the pseudo-code language methods
are:
o
I t allows the designer/programmer to concentrate on
"what" rather than on "how"; that i s , i t helps the
designer to concentrate i n i t i a l l y on what is to be
done, and then systematically to become concerned
with how to do i t . j In other words, i t permits
conce~ation on the logic, thus freeing the
desi gner/programmer from low level detail s
associated with coding in a particular language.
o
I n i t i a l l y , the module logic can be "coded" with
whatever level of detail is appropriate to the
problem at hand, depending on the complexity of the
problem and the experience of the designer/
programmer.
3.
Pseudo-code can be retained as a comment card to
document the logic of the module. In addition,
segments of pseudo-code can proceed the actual
executable code as a means of commenting the code,
making i t more meaningful rather than the comments
just echoing the code. For organizations that
have adopted the use of HIPO diagrams, pseudo-code
can be inserted in the process section to describe
b r i e f l y the "what" that this module is supposed to
do. This is helpful not only to the designer/
programmer, but also to the managers, users, and
maintenance programmers.
Pseudo-code Constructs
Pseudo-code languages have often been called
"pidgin" languages because they incorporate the
vocabularly of the English language and the three
366
basic constructs of a structured programming language.
These constructs are sequence, IF-THEN-ELSE, and
DOWHILE.
o
Analyzing the function of the module
o
Selecting data structure and algorithm
o
Abstracting the "main" function flow
o
Stepwise expanding the function into new
functions and proving the expansion
o
Converging the pseudo-code into executable
statements
Sequence Construct
The sequence construct is the simplest construct;
control is transferred into i t , a process is performed, and control is transferred out to the next program
construct. The sequence construct must always s t a r t
with a verb. For example,
Get next character
Search table l i n e a r l y
Calculate wages
Analyzing the function of the module
Stepwise refinement cannot be rushed into without
f i r s t understanding the function to be carried out.
The function of the module must be analyzed, and i t s
constraints must be well thought out and documented,
so that abstracting the function may be started. The
problem of understanding what a module should do is
a much deeper problem than writing the actual code.
IF-THEN-ELSE Construct.
The IF-THEN-ELSE construct is used to modify the
flow o f program c o n t r o l . I t corresponds to classical
IF...THEN...ELSE of ALGOL and PL/I. For example,
IF symbol in symbol table THEN
set found f l a g to true
ELSE (symbol not in table)
set found flag to false
i n s e r t symbol in symbol table
ENDIF
Traditionally, this phase receives less attention
than i t requires. Decisions on error conditions are
very seldom thought of before the actual coding. Or,
the complexity of implementing the function is not
f u l l y realized u n t i l the expansion or coding phase.
Underestimating the time that i t w i l l take to implement
the module is the rule rather than the exception.
DOWHILE Construct
The function cf a module must be documented
formally and vigorously. A good method might be to
use the HIPO detailed diagram, which provides sections
for defining the interfaces and the "what" that the
module is supposed to do.
The DOWHILE construct has a decision construct
and one or more sequence constructs. When control
enters the DOWHILE, the terminal condition is tested
first.
Depending upon the condition, control is
e i t h e r passed out of the element or the process is
performed and the construct condition is retested.
I t is s i m i l a r to DOWHILE or WHILEDO of some programming languages.
Selecting Data Structure and Algorithm
The implementation of the module is heavily
influenced by the selection of the proper data
structure. Thus, i t is extremely important that the
goal language c l e a r l y mirrors the data structure
s e l e c t i o n , 6 which in turn influences the algorithm.
Therefore, this section may require a l o t of
r e w r i t i n g and r e t h i n k i n g . These fundamentals of data
structures must be well understood by a l l designers/
programmers.
For example,
DOWHILE there are input records
END[)O
4.
The algorithm selected must be simple and
straightforward. Unless i t is specified as a cons t r a i n t , e f f i c i e n c y is not to be considered; s i m p l i c i t y
must be stressed.
Programmingby Stepwise Refinement
The program or system design process includes
the d e f i n i t i o n of a l l modules in the program, the
hierarchical structure of the modules, and the interfaces among the modules. Since complexity is our
worst enemy, the primary way to make a program less
complex is to decompose i t into a set of highly
independent and functional modules. This general
design process is followed by the detailed module
design process. In this process, the module logic
is f i r s t designed on "what" the function of the
module is and later expanded into "how" to do i t .
The idea of function expansion leads to step-wise
refinemen~ programming, which was f i r s t conceived by
D i j k s t r a , ~ and l a t e r improved and presented by
Wirth b in an e x c e l l e n t t u t o r i a l paper that uses the
Eight-Queens problem to i l l u s t r a t e i t .
Abstracting the "main" function flow
In t h i s phase, the major elements of the module
function are f i r s t recognized. Using pseudo-code
constructs a high-level solution is f i r s t formed.
Details are postponed as long as possible, so that the
highlevel solution is not d i l u t e d by the i n f l e x i b i l i t y
o f d e t a i l s . Emphasis is on "what" the module does,
rather than on "how" i t does i t .
Programming, even at a higher l e v e l , is a t r i a l
and e r r o r process. Mistakes may be made or j u s t the
wrong solution may be explored. During the expansion
phase, the higher-level solution may have to be
r e w r i t t e n , as the f i r s t idea is seldom the best idea.
Rethinking and reworking is the rule here.
The module logic development can be regarded as
a top-down process having the f o l l o w i n g f i v e d i s t i n c t
phases:
As an example, assume that the function of a
module is to read the year and date (in Julian form)
and p r i n t the month, day, and year. Abstracting the
367
IIF year <1753 or year> 2000
or Date> days-in-year
_I
THEN
check f o r v a l i d year, date -~
p r i n t error message
|
stop
|ELSE ( v a l i d year, date)
1ENDIF
"main" flow may be as follows:
Read year, date
Check for leap year
Check for v a l i d year, date
Calculate month, day
P r i n t month, day, year
Stepwise expanding the function
Converting pseudo-code into executable code
The idea in stepwise refinement is to " d i v i d e
and conquer" a specified function by reexpressing i t
i n t o an equivalent structure of pseudo-code constructs,
each solving part of the problem and each simpler than
the o r i g i n a l . In other words, stepwise refinement is
a tool for decomposing each module's function i n t o
i n t e r n a l l o g i c needed to carry out the function.
A f t e r a series of refinements, the pseudo-code
has reached the lowest-level of d e t a i l , which is
recognized when every pseudo-code statement can be
coded with one or two programming language statements.
I f the refinement process was carried out with vigor
at a l l l e v e l s , the programmer should feel confident
about the program.
The stepwise refinement process uses pseudo-code
in a specific and organized manner. Having abstracted
the "main" logic flow in few pseudo-code constructs,
each element is then expanded into simpler elements
to further divide and conquer. I f the function represented by each pseudo-code element is not familiar,
expand i t enough to feel comfortable.
I f the function
is a simple one, then further expanding may be unnecessary.
Converting the pseudo-code into executable code
should be an easier task. A f t e r converting the code,
check for correctness vigorously. Make sure every
pseudo-code statement is coded c o r r e c t l y before going
on. Do not hesitate to go back and make changes i f
these changes w i l l make the program simpler. This is
the best debugging technique.
The stepwise refinement process has two invaluable
advantages:
o
I t helps us deal with complexity by postponing
details u n t i l l a t e r ,
o
I t provides a mechanism for producing a correct
program.
In our previous example, to convert the f o l l o w i n g
pseudo-code segment i n t o executable FORTRANcode is a
very simple task.
i IF MOD(YEAR,4) : 0 THEN
{
LEAP YEAR
{ ELSE
{
NOT A LEAP YEAR
}
{ENDIF
leap : ' f a l s e '
IF (mod(year,4) = O)
The later issue is of major importance. As Mills 7
points out, t r a d i t i o n a l l y , program development was to
write program statements and v e r i f y that the statements
do what the program intended them to do, hence,
synthesis. Proving program correctness has been an
impossible and expensive task. However, the problem
is not one of synthesis, but of analysis. Expand each
pseudo-code element into a lower level of detailed
nseudo-code elements. Verify the expansion. Do the
lower level pseudo-code elements do what the expanded
pseudo-code elements are supposed to do? Since t h i s
v e r i f i c a t i o n is l o c a l , and since the level of expansion
is not done in great leaps, then there is no reason why
the f i n a l program is not a correct program. With the
help of the stepwise refinement process, programming
may become more of a recording process than a t h i n k i n g
leap = 'true'
The best way to comment executable statements is
to precede them with the pseudo-code statements as
they were generated.
5.
Stepwise Refinement Example
To i l l u s t r a t e the f i v e d i s t i n c t steps in developing the l o g i c of a module with an example, l e t us
assume a module whose function is to i n s e r t a symbol
in a symbol table.
analyze the function of the module
search symbol table for symbol; i n s e r t i t i f not
already there; check for symbol table overflow;
return appropriate flags
process.
In expanding pseudo-code elements, every e f f o r t
should be made to conceive and evaluate a l t e r n a t e
s o l u t i o n s . By doing so, i t is very l i k e l y that a
b e t t e r idea f o r the whole program may emerge.
Rewriting and r e t h i n k i n g is the key to successful
refinement, and t h i s is why a pseudo-language processor
can be so valuable. I t w i l l encourage people to make
changes by providing the f a c i l i t y f o r quick and easy
updates.
interface:
i n p u t : symbol
output: f l a g found:
i f found = " t r u e " ,
symbol in symbol t a b l e ,
else ' f a l s e '
f l a g overflow: i f overflow = ' t r u e ' ,
symbol table overflow.
For the previous example, r e f i n e "check for leap year":
i
check for leap year =
select data structure and algorithm
IF mod(year,4):O THE!I
leap year
ELSE
not a leao year
, ENDIF
data structure (consider goal language)
VAR
symbol,
max-entries i n i t ( I 0 0 ) ,
symbol-table array (max-entries),
e n t r i e s - i n - t a b l e i n i t (0): i n t e g e r ;
found, overflow: boolean:
-
or r e f i n e "check for v a l i d year, date"
368
o algorithm
- search symbol table l i n e a r l y
set loop-counter = l
set found = 'false'
WHILE loop-counter ~entries-in-table and found =
'false' DO
IF symbol-table (loop-counter) = symbol THEN
set found = 'true'
ELSE (do nothing)
ENDIF
increment loop counter by one
ENDDO ( a l l entries compared)
IF found = 'true' THEN
do nothing
ELSE (insert symbol in symbol table)
increment entries-in-table by one
IF entries-in-table > max-entries THEN
set overflow = 'true'
ELSE (no overflow)
set overflow = 'false'
set symbol table (entries-in-table) = symbol
ENDIF
ENDIF
return found, overflow flags.
abstract module's logic "main" flow
compare each entry in table with symbol
IF symbol found THEN
do nothing
ELSE (s~nnbol not in symbol table)
IF symbol table overflow, THEN
set overflow = ' t r u e '
ELSE (insert symbol)
set overflow - 'false'
insert symbol in symbol table
ENDIF
ENDIF
return flags found, overflow
stepwise refine functions (rethink and rework)
o step l
compare each entry in =
table with symbol
~set loop-counter = l
set found = 'false'
WHILE loop-counter <
entries-in-table-and
found = 'false'
DO: IF symbol-table (loop
counter) = symbol THEN
set found 'true'
ELSE do nothing
ENDIF
increment loop counter
by one
ENDDO ( a l l entries compared)
pseudo-code module's !o~;ic as of step 1
set loop-counter = l
set found = 'false'
WHILE loop-counter sentries-in-table and found =
'false'
DO: IF symbol-table (loop-counter) = symbol THEN
set found = 'true'
ELSE (do nothing)
ENDIF
increment loop-counter by one
ENDDO ( a l l entries compare~C;
IF symbol found THEN
Summary
As designers/programmers, we probably want to use
the stepwise refinement process for every module that
we write. In a few isolated cases where the program
steps are r e l a t i v e l y simple and do not require any
complicated logic, we may write the final code without
going through the stepwise refinement process.
In the stepwise refinement process only major
elements are considered f i r s t ; as the module logic
expands, the newest parts are inserted into the basic
structure. Each expansion process is studied caref u l l y and only a small amount of expansion takes place.
The use of pseudo-code is very strongly recommended. I t is not a "panacea" and i t is possible to
produce bad module logic design using i t . However,
have found that the students in Structured Programming
classes quickly learn to use pseudo-code effectively.
The main objectives of using pseudo-code and the
stepwise refinement mental process are:
o
do nothing
ELSE (symbol not in table)
IF symbol table overflow THEN
o Every refinement, once written, is capable of
being shown to be correct, thus establishing
a program's correctness.
set overflow = 'true'
ELSE (insert symbol in table)
set overflow = 'false'
insert symbol in table
ENDIF
ENDIF
return found, overflow flags
APPENDIX A
some rules for making up a pseudolanguage
-
o step 2
IF symbol table
overflow THEN
set overflow =
'true'
ELSE (no overflow)=
set overflow =
'false'
insert symbol in
symbol table
ENDIF
-
Divide and conquer complexity, not just
programs
increment entries-in-table by
one
IF entries-in-table > max
entries THEN set 6~erflow =
'true'
ELSE (no overflow)
set overflow = 'false'
set symbol-table (entriesin-table) = symbol
ENDIF
-
start sentence with a verb
i . e . , p r i n t table x
get next record
search table x for symbol
use DOWHILE for looping
i . e . , WHILE (condition) DO
ENDDO ( a l l records were processed)
o include comments on ENDDOline
use IF-THEN-ELSE to test Conditions
i . e . , IF (condition) THEN
final detailed pseudo-code program
369
ELSE (condition not true)
ENDIF
o always include an ELSE even i f dummy
o comment the ELSE condition
i . e . , ELSE (word not in the table)
r e f i n e one statement at a time, i f possible
o ask yourself: do the new expanded statements
do what the o r i g i n a l statement was supposed to
do?
o be careful and systematic in expanding; build
f a i t h in your development process.
o do not r e f i n e too many statements at once
l i n e up ELSE, ENDIF with t h e i r IF: l i n e up
ENDDO with WHILEDO
indent two spaces a l l statements
f o l l o w i n g WHILEDO, IF-THEN-ELSE
o write a simple processor to do that
be prepared to rewrite and rework; one's f i r s t
solution is seldom the best.
REFERENCES
l.
Van Leer, P., "Top-down developing using a
program design language", IBM System
Journal, No. 2, 1976.
2.
Caine, S.H. et.al. "PDL: A tool for Software
Design", Proceeding NCC 1975.
3.
Conway, R., Gries, D and Zimmerman, E.C., "A
Primer on PASCAL" Winthrop Computer Systems
Series, 1977.
4.
Dijkstra, E.W., "A Constructive Approach to the
Problem of Program Correctness," BIT, 8(3),
1974-186 (1968).
5.
Wirth, N., "Program Development by Stepwise
Refinement." Communications of the ACM,
Vol. 14, No. 4, April 1971.
6.
Wirth, N., "Systematic Programming: An
Introduction," Prentice-Hall, 1973.
7.
Mills, H.D., "How to Write Correct Programs and
Know I t , " IBM, FSD, Gaithersburg, Maryland,
1973.
8°
Aron, D., "The Program Development Process"
Addison-Wesley, 1971.
9.
Hughes, J. and Michtom, J., "A Structured Approach
to Programming," Prentice-Hall, 1977.
370