DAVID@PENNDRLS.BITNET (12/06/88)
While I was waiting for the Pressman book to get to me through inter-library loan, I found one of the software design books recommended by someone else (I don't know who): Structured Design: Fundamentals of a discipline of Computer Program and systems Design, Edward Yourdon and Larry L Constantine, Prentice-Hall, Englewood Cliffs, New Jersey, 1979 This book is several years old, so it stresses concepts that have been superceeded or amplified by more recent work (see the Pressman book), but it certainly does contain some food for thought. A lot of the basic concepts are echoed by Brody in Starting Forth, but there is more about *why* the ideas are good, which is very useful. For example, let's return to the question of argument lists for a moment. Constantine and Yourdon agree with Fraser in favoring parameter lists. The argument in favor of parameter lists is based on the concept of ``complexity''. The less complex a program is, the easier it is for the programmer to comprehend it, the fewer bugs he will introduce during initial coding and the easier it will be to fix bugs later. Speaking of the subroutine call interface, the interface is less complex if: * the information (represented by the call) can be accessed directly by the programmer (e.x.: no indirect data types.) * the information is presented locally (e.x.: parameter lists). * the presentation is standard (e.x.: input args first, output second). * its nature is obvious (e.x.: intuitive subroutine names(?)). They then present several example subroutine calls, ranging from the completely explicit [CALL LENGTH(x0,y0,x1,y1,distance)] to the completely implicit [CALL LENGTH]. There is a point to each example, but I am concerned here only with the difference between the first and last. Before I go on, I should also mention that another measure of complexity is the sheer number of keystrokes involved in the construct. The more keystrokes, the more chances for a ``finger-check''. Of course, finger-check ``bugs'' are considerably less significant than run-time bugs. Yourdon and Constantine argue that the completely explicit call form is best, since it meets the four criterion outlined above. In discussing (and rejecting) the implicit form, the authors say this: Finally, we consider (the implicit case), which suggests an interface of CALL LENGTH. At first glance, it may appear that such a subroutine call has *no* parameters -- but we know better. LENGTH still requires initial (X,Y) coordinates and final (X,Y) coordinates to perform its task, and it must still leave the DISTANCE information where that information will be stored. The problem is that the programmer doesn't know -- at least, not by looking at the statement CALL LENGTH. In other words, the parameters are not *local* to the subroutine-calling statement; all the information is provided *remotely*, in a place whose whereabouts cannot be determined by looking at the CALL LENGTH statement. If all the arguments were set up immediately preceding the call to LENGTH, it would be obvious. However, it is hardly safe to assume that all programmers using the CALL LENGTH statement will adhere to such discipline. Eventually, the programmer begins taking advantage of the fact that some of the parameters naturally are set up 23 statements earlier in the code. These arguments are fine, but they reflect an obvious traditional language bias. The subroutine call as it would appear in FORTH, LENGTH, is not referring to ``remote'' arguments; the arguments are all right there on the stack, and indeed must have been set up just prior to the call to LENGTH. (This is implied by the shortness of FORTH words.) The FORTH form also involves far fewer keystrokes and thus fewer opportunities for initial error. The FORTH call does, however, still fail the explicitness test (Fraser's argument), and so is inferior to the explicit form in terms of overall complexity. So, it would seem that explicit parameters win the day. But not, I would claim, by much. With my modification to Yourdon and Constantine's argument, the FORTH form of the call would appear to be a close second best call format out of the selection they discuss. It fails only because it does not show the arguments completely explicitly, but instead depends on the debugging programmer reading the entire word and keeping track of the three deep stack in his head. This is an important deficiency *all other things being equal*. As Yourdon and Constantine themselves point out, there are many factors that enter into the complexity problem. One is the fact that the FORTH call format takes fewer programmer keystrokes. (In the project I am currently working on, almost all of my ``compile time'' errors have been simple syntax/typos in subroutine call argument lists.) A second was mentioned already by another poster: the FORTH format gives the debugger more immediate access to the *algorithm* realized by the code (when there are no FLIP FLOP PLOPs) and this is a very important reduction in complexity. (Obviously, there is a tradeoff here. See below for my ``solution''.) Yourdon and Constantine also report that the human mind does not handle more than seven distinct simultaneous objects or more than three simultaneous levels of nesting. By the same token, however, it *does* handle that much, so there is no reason to avoid that level of complexity when it would reduce other aspects of complexity. So a three deep stack is no real problem, especially since most FORTH words ought to be seven or less non-stack words in length. (*Most*, not all; just as *most*, but not all, traditional language programs should be seven lines or less in length. (Actually, Constantine and Yourdon use 10 lines here, but seven seems more consistent with their other arguments.)) I would argue, then, that the parameterized call format is only marginally less complex than the FORTH implicit call. During initial coding, I certainly prefer the FORTH form; it means less work for me. During later debugging, explicit parameter lists are often more important. I would suggest that the ideal programming environment (note, *not* ``language'') would enable the programmer to enter only the subroutine name and when necessary (that is, when FLIP FLOP PLOP would otherwise be necessary) a shorthand form of the argument list, but would check and, *on command*, display the complete parameter lists. I don't know of any such environment. (I would say FORTH with the addition of named parameters comes close, but that is my FORTH bias showing through again.:-) In conclusion, I think we can now see at least one reason why FORTH programmers defend the parameterless FORTH words so vigorously: it means they don't have to type so much! :-) -- R. David Murray (DAVID@PENNDRLS.BITNET, DAVID@PENNDRLS.UPENN.EDU) P.S.: I do not expect you to be converted by my argument, Fraser; rather, I understand yours more fully now. But I think that FORTH, especially with the modern additions to the traditional techniques, is closer to the ideal than you give it credit for. Certainly it is close enough that I will not abandon its other advantages because it does not have parameter lists. Especially for personal projects.