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
© Copyright 2024