home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / BASIC / QBS_0103 / SQBC010.DOC < prev   
Text File  |  1993-04-30  |  8KB  |  217 lines

  1.      ┌───── Structured QuickBASIC Programming ─────┐
  2.      │ ╒═════════════════════════════════════════╕ │▓
  3.      │ │Single Entry and Exit in QuickBASIC Code │ │▓
  4.      │ ╞═════════════════════════════════════════╡ │▓
  5.      │ │         an article written by           │ │▓
  6.      │ │          Quinn Tyler Jackson            │ │▓
  7.      │ │                   of                    │ │▓
  8.      │ ├─────────────────────────────────────────┤ │▓
  9.      │ │   JackMack Consulting & Development     │ │▓
  10.      │ │        #302-9085 Gildwood Drive         │ │▓
  11.      │ │       Burnaby, British Columbia         │ │▓
  12.      │ │             V3N 4L9 CANADA              │ │▓
  13.      │ └─────────────────────────────────────────┘ │▓
  14.      └─────────────────────────────────────────────┘▓
  15.        ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  16.  
  17.  
  18.  
  19.     WORD COUNT: 1,150
  20. Flesch-Kincaid: 9th grade
  21.  
  22.  
  23. A feature of maintainable code in any language is modular 
  24. single entry and exit.  By definition, single entry and 
  25. exit involves a simple principle: passing control to a 
  26. module in only one manner and returning from the module in 
  27. a similarly static fashion.  This keeps code flow clear 
  28. and understandable for future revision and review, since 
  29. whoever inspects the code begins the project with the 
  30. assumption that any given module is accessible in one way, 
  31. and will relinquish control in just as set a manner.  This 
  32. presumption frees the inspector to examine the program 
  33. flow, without cluttering his mind with random hops and 
  34. jumps triggered by numerous factors in the system.
  35.  
  36. First to consider is single entry.  Structured philosophy 
  37. dictates that a module should gain control in one way 
  38. only.  For example, if a module gains control with the 
  39. press of a key, it should not gain control through any 
  40. other means.  A programmer reading the code will know that 
  41. the only means of calling the module is by pressing a key, 
  42. and he will not have to worry about any other event 
  43. getting in the way of this.  Imagine the difficulty added 
  44. to program debugging if the same module were accessible by 
  45. a timer tick, or a byte arriving in a modem buffer.  How 
  46. would the programmer know if keyboard, modem, or timer 
  47. code caused a bug?
  48.  
  49. The importance of single entry becomes even more apparent 
  50. when modules begin to interact.  Miscellaneous accesses 
  51. juggle about control between modules, and these in turn 
  52. randomly access other modules and become part of an ever 
  53. more complex process.  Each module's having only one entry 
  54. point greatly simplifies tracking down a bug or series of 
  55. bugs in such a complex system.  The fewer stitches used to 
  56. hold the whole system together, the better off the whole 
  57. system is for it.
  58.  
  59. As a pseudocode example of a module that has multiple 
  60. entry points:
  61.  
  62.     IF KeyPressed = TRUE THEN React
  63.     IF ModemBuffer = FULL THEN React
  64.     IF TimerTicks = 5 THEN React
  65.  
  66.     MODULE React
  67.     BEEP
  68.     END MODULE
  69.  
  70. Although simple, this bit of code shows the problem.  Each 
  71. of the events KeyPressed, ModemBuffer, and TimerTicks can 
  72. give control to the same module called React.  In short, 
  73. React has three entry points, which complicates debugging 
  74. and maintenance accordingly.  But, how to work around this 
  75. problem?  What if you want all three situations to pass 
  76. control to a procedure that beeps?  Are you supposed to 
  77. write this, instead?
  78.  
  79.     IF KeyPressed = TRUE THEN BEEP
  80.     IF ModemBuffer = FULL THEN BEEP
  81.     IF TimerTicks = 5 THEN BEEP
  82.  
  83. This would accomplish the same task, but suppose the 
  84. module React were two hundred lines long, instead of just 
  85. a simple BEEP?  Would those two hundred lines have to be 
  86. repeated three times, once for each triggering event?  No.  
  87. A simple method to avoid repetition in single entry code 
  88. involves a type of indirection.  At first, it looks a bit 
  89. strange and seems impractical, but further investigation 
  90. shows that it simplifies code:
  91.  
  92.     IF KeyPressed =TRUE THEN KeyReact
  93.     IF ModemBuffer = FULL THEN ModemReact
  94.     IF TimerTicks = 5 THEN TimerReact
  95.  
  96.  
  97.  
  98.     MODULE KeyReact
  99.     React
  100.     END MODULE
  101.  
  102.     MODULE ModemReact
  103.     React
  104.     END MODULE
  105.  
  106.     MODULE TimerReact
  107.     React
  108.     END MODULE
  109.  
  110.     MODULE React
  111.     BEEP
  112.     END MODULE
  113.  
  114. In simple, one-page programs, this seems ridiculous.  In 
  115. theory, however, this indirection forces the modules of 
  116. the system into the single entry model.  ModemReact 
  117. responds to modem events, TimerReact to timer events, and 
  118. so on.  Now, instead of having three entry points, React 
  119. responds to one event: being called as a standard module.  
  120. React, having been buffered by indirection, now serves 
  121. only one purpose, not three.  Moreover, should it happen 
  122. that the code is to be modified, the programmer, having 
  123. isolated the three triggering events, can modify the 
  124. keyboard, modem, or timer code as separate units, and does 
  125. not have to consider anything other than the events he 
  126. wishes to alter.  The concept of a single purpose per 
  127. module is tied closely to the single entry and exit 
  128. principle.  Indirection isolates the module from the three 
  129. separate events to the extent that a programmer asked to 
  130. debug the code can uncover problems arising in the 
  131. keyboard, modem, or timer code without having to 
  132. simultaneously juggle the three about in his head.  
  133. Program flow becomes comprehensible.
  134.  
  135. Single exit, the first cousin of single entry, dictates 
  136. that there should only be one way to pass control from a 
  137. module.  QuickBASIC, with its EXIT SUB and EXIT FUNCTION 
  138. commands, could conceivably compile this code:
  139.  
  140.  
  141.     SUB Foo (variable AS INTEGER)
  142.     IF variable = 1110 THEN
  143.               SomeGlobalVariable = 3
  144.               EXIT SUB
  145.     ' The above line passes control from this module.
  146.     END IF
  147.     FOR a = 1 TO 10
  148.     IF variable = INT(RND * 100) THEN
  149.               SomeGloabalVariable = 8
  150.               EXIT SUB
  151.     ' So does the above line, but for different reasons.
  152.     END IF
  153.     NEXT a
  154.     DO
  155.     KeyPressed$=UPCASE$(INKEY$)
  156.     LOOP UNTIL KeyPressed$ <> ""
  157.     IF KeyPressed$ = "Y" THEN
  158.               SomeGlobalVariable = 9
  159.               EXIT SUB
  160.     ' And so does the above, for yet another reason!
  161.     END IF
  162.     ' As will the following code, for another!
  163.     SomeGlobalVariable = 5
  164.     END SUB
  165.  
  166.  
  167. An examination shows that control is passed from Foo if 
  168. one of three conditions are met:  first, if variable is 
  169. equal to 1110; then, if variable is equal to one of ten 
  170. random numbers between 1 and 100, and finally, the module 
  171. passes on control if the user presses a 'Y' on the 
  172. keyboard.  If none of these conditions are met, 
  173. SomeGlobalVariable is set to 5 and control passes on when 
  174. program flow reaches the logical end of the module.  (One 
  175. could argue that, for simplicity's sake, the best place 
  176. for control to be passed on is at the end of a SUB or 
  177. FUNCTION, since that is the default behavior of most 
  178. languages.)  Four different ways to exit one module.
  179.  
  180. This is unacceptable behavior in the single exit model, 
  181. which demands that a module exit under only one condition, 
  182. so that the programmer examining the code can state: "I 
  183. can be sure why Foo gave up control."  In unison with 
  184. single entry, this makes debugging a pleasure!  On the 
  185. other hand, multiple entry coupled with multiple exit can 
  186. be a nightmare. . . .
  187.  
  188. A possible reworking of the above messy code might be:
  189.  
  190.     SUB Foo (variable AS INTEGER)
  191.     SomeGlobalVariable = 5
  192.     IF variable = 1110 THEN
  193.               SomeGlobalVariable = 3
  194.     ELSE
  195.               FOR a = 1 TO 10
  196.               IF variable = INT(RND * 100) THEN
  197.               SomeGloabalVariable = 8
  198.               END IF
  199.               NEXT a
  200.     END IF
  201.     IF SomeGlobalVariable = 5 THEN
  202.               DO
  203.               KeyPressed$=UPCASE$(INKEY$)
  204.               LOOP UNTIL KeyPressed$ <> ""
  205.               IF KeyPressed$ = "Y" THEN
  206.               SomeGlobalVariable = 9
  207.     END IF
  208.     END SUB
  209.  
  210. As modified, Foo only exits under one circumstance: when 
  211. the program flow reaches the logical end of the module.  
  212. This simplifies things considerably and consequently makes 
  213. debugging and maintenance more manageable.  And of course, 
  214. manageable code is the objective of any structured 
  215. approach to programming, whether it be in QuickBASIC or 
  216. C++.
  217.