1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
|
<HTML>
<!--
***********************************************************************
FUNNELWEB MANUAL WEB PAGE
=========================
Copyright (c) Ross N. Williams 1992,1999. All rights reserved.
Permission is granted to redistribute and use this manual in
any medium, with or without modification, provided that all
notices (including, without limitation, the copyright
notice, this permission notice, any record of modification,
and all legal notices) are preserved on all copies, that all
modifications are clearly marked, and that modified versions
are not represented as the original version unless all the
modifications since the manual's original release by Ross N.
Williams (www.ross.net) consist of translations or other
transformations that alter only the manual's form, not its
content. THIS MANUAL IS PROVIDED "AS IS" AND WITHOUT ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
FITNESS FOR A PARTICULAR PURPOSE. TO THE EXTENT PERMITTED BY
LAW THERE IS ABSOLUTELY NO WARRANTY.
***********************************************************************
-->
<HEAD>
<TITLE>5.11 The Dangers Of FunnelWeb</TITLE>
<STYLE TYPE="text/css"> <!-- A {text-decoration: none} // --> </STYLE>
</HEAD>
<BODY BACKGROUND="binary/background.gif"
BGCOLOR="#FFFFFF"
TEXT="#000000"
VLINK="#660000"
LINK="#FF0000"
ALINK="#CC0000">
<TABLE WIDTH="490">
<TR>
<TD WIDTH="130" VALIGN="top">
<IMG SRC="binary/d_clear.gif" ALT="" WIDTH="130" HEIGHT="1"><BR>
<FONT SIZE="2">
<BR>
<A HREF="http://www.ross.net/"
TARGET="rosshome"
onClick="window.open('','rosshome','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
>
<IMG SRC="binary/rossnet_logo.gif"
WIDTH="64" HEIGHT="32"
BORDER="0" ALT="RossNet"
HSPACE="0" VSPACE="1"></A><BR>
<BR>
<A HREF="../index.shtml"
TARGET="funnelweb"
onClick="window.open('','funnelweb','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
>
<IMG SRC="binary/linklogo.gif"
WIDTH="64" HEIGHT="32"
BORDER="0" ALT="FunnelWeb"
HSPACE="0" VSPACE="1"></A><BR>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0><TR><TD BGCOLOR="#000000">
<A HREF="../reference/index.html"
TARGET="funnelwebreference"
onClick="window.open('','funnelwebreference','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
><FONT COLOR="#FFFFFF"><B>Reference</B></FONT></A><BR>
<BR>
<A HREF="../developer/index.html"
TARGET="funnelwebdeveloper"
onClick="window.open('','funnelwebdeveloper','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
><FONT COLOR="#FFFFFF"><B>Developer</B></FONT></A><BR>
<BR>
<A HREF="index.html"><FONT COLOR="#FFFFFF"><B>Tutorial</B></FONT></A><BR>
<A HREF="intro.html"><FONT COLOR="#FFFFFF">1 Introduction</FONT></A><BR>
<A HREF="macro.html"><FONT COLOR="#FFFFFF">2 Macros</FONT></A><BR>
<A HREF="type.html"><FONT COLOR="#FFFFFF">3 Typesetting</FONT></A><BR>
<A HREF="example.html"><FONT COLOR="#FFFFFF">4 Example</FONT></A><BR>
<A HREF="hints.html"><FONT COLOR="#FFFFFF">5 Hints</FONT></A><BR>
<A HREF="examples.html"><FONT COLOR="#FFFFFF">6 Examples</FONT></A><BR>
<A HREF="web.html"><FONT COLOR="#FFFFFF">7 Webmaking</FONT></A><BR>
<BR>
<A HREF="search.html"><FONT COLOR="#FFFFFF"><B>SEARCH</B></FONT></A><BR>
</FONT>
</TD></TR></TABLE>
</TD>
<TD WIDTH="360" VALIGN="top">
<FONT SIZE="3">
<A HREF="../reference/index.html"><IMG SRC="binary/title.gif"
WIDTH="302" HEIGHT="24"
BORDER="0" ALT="FunnelWeb Tutorial Manual"
HSPACE="0" VSPACE="0"></A>
<P><FONT SIZE="5">5.11 The Dangers Of FunnelWeb</FONT><BR>
<P>Like many tools that are general and flexible,
FunnelWeb can be used in a variety of ways, both good and
bad. One of the original appeals of the literate approach to
programming for Knuth, the inventor
of literate programming, was
that it allows the programmer to describe the target program
bottom up, top down, size to side, or chaotically if
desired.
<P>The flexibility that the literate style of
programming leaves much room for bad documentation
as well as good documentation. Years of experience
with FunnelWeb has revealed the following
stylistic pitfalls which the experienced FunnelWeb
user should take care to avoid. (Note: The fact that
these faults are listed here does not mean that
the author has eliminated them in his own work.
Rather, it is mainly the author's own mistakes
that have resulted in this list being compiled.
The author immediately confesses to several of the
faults listed here, most notably that of Pavlov
documentation).
<P><BLOCKQUOTE><B>Spaghetti
organization:</B> By far the
worst problem that arises in connection with the literate
style occurs where the programmer has used the literate tool
to completely scramble the program so that the program is
described and layed out in an unordered, undisciplined
"stream of consciousness". In such cases the programmer may be using
the literate style as a crutch to avoid having to think
about structuring the presentation.</BLOCKQUOTE>
<P><BLOCKQUOTE><B>Boring
organization:</B> At the other
extreme, a program may be organized in such a strict way
that it is essentially laid out in the order most
"desired" by the target programming language. For
example, each macro might contain a single procedure, with
all the macros being called by a macro connected to a file
at the top. In many cases a boring structure may be entirely
appropriate, but the programmer should be warned that it is
easy to slip into such a normative style, largely forgetting
the descriptive structural power that FunnelWeb provides.</BLOCKQUOTE>
<P><BLOCKQUOTE><B>Poor random
access:</B> Using FunnelWeb, it is
quite possible to write programs like novels
--- to be read from cover to cover. Sometimes the story is
very exciting, with data structures making dashing triumphs
and optimized code bringing the story to a satisfying
conclusion. These programs can be works of art.
Unfortunately, without careful construction, such
"novel-programs" can become very hard to access
randomly by (say) a maintenance
programmer who wishes only
to dive in and fix a specific problem. If the entire program
is scrambled for sequential exposition, it can be hard to
find the parts relating to a single function. Somehow a
balance must be struck in the document between the needs of
the sequential and of the random-access reader. This balance
will depend on the intended use of the program.</BLOCKQUOTE>
<P><BLOCKQUOTE><B>Too-interdependent
documentation:</B> Sometimes,
when editing a
program written using FunnelWeb, one knows how to modify the
program, but one is unsure of how to update the surrounding
documentation! The documentation may be woven into such a
network of facts that it seems that changing a small piece
of code could invalidate many pieces of documentation
scattered throughout the document. The documentation becomes
a big tar pit in which movement is impossible. For example,
if you have talked about a particular data structure
invariant throughout a document, changing that invariant in
a small way could mean having to update all the
documentation without touching much code. In such cases, the
documentation is too interdependent. This could be
symptomatic of an excessibly interconnected program, or of
an excessively verbose or redundant documenting style. In
any case, a balance must be struck between the
conversational style that encourages redundancy (by
mentioning things many times) and the normalized database
approach where each fact is given at only one point, and the
reader is left to figure out the implications throughout the
document.</BLOCKQUOTE>
<P><BLOCKQUOTE><B>Pavlov
documentation:</B> By placing so
much emphasis on the documentation, FunnelWeb naturally
provides slots where documentation "should" go. For
example, a FunnelWeb user may feel that there may be a
rather unpleasant gap between a <SAMP>@C</SAMP> marker and the
following macro. In many cases <I>no</I> commentary is
needed, and the zone is better left blank rather than being
filled with the kind of uninformative waffle one often finds
filling the slots of structured documentation written
according to a military standards
(e.g. MIL-STD-2167A). (Note:
This is not a criticism of 2167A, only of the way it is
sometimes used). The lesson is to add documentation only
when it adds something. The lesson in Strunk and
White<STRONG>[Strunk79]</STRONG> (p. 23) holds for program
documentation as it does for other writing: "Vigorous
writing is concise. A sentence should contain no unnecessary
words, a paragraph no unnecessary sentences, for the same
reason that a drawing should have no unnecessary lines and a
machine no unnecessary parts. This requires not that the
writer make all his sentences short, or that he avoid all
detail and treat his subjects only in outline, but that
every word tell.".</BLOCKQUOTE>
<P><BLOCKQUOTE><B>Duplicate
documentation:</B> Where the
programmer is generating product files that must exist on
their own within the entire programming environment
(e.g. the case of a programmer in a team who is using
FunnelWeb for his own benefit but must generate (say)
commented Ada specification package files) there
is a tendency for the comments in the target code to
duplicate the commentary in the FunnelWeb text. This may or
may not be a problem, depending on the situation.
However, if this is happening, it is certainly worth the
programmer spending some time deciding if one or other of
the FunnelWeb or inline-comment documentation should be
discarded. In many cases, a mixture can be used, with the
FunnelWeb documentation referring the reader to the inline
comments where they are present. For example:</BLOCKQUOTE>
<P>
<PRE>
@A Here is the header comment for the list package
specification. The reader should read these comments
carefully as they define a list. There is no need to
duplicate the comments in this text.
@$@<Specification package comments@>==@{@-
-- LIST PACKAGE
-- ============
-- * A LIST consists of zero or more ITEMS.
-- * The items are numbered 1 to N where N
-- is the number of items in the list.
-- * If the list is non-empty, item 1
-- is called the HEAD of the list.
-- * If the list is non-empty, item N
-- is called the TAIL of the list.
-- ...
@}
</PRE>
<P><BLOCKQUOTE><B>Overdocumenting:</B> Another
evil that can arise when using FunnelWeb is to over-document
the target program. In some of Knuth's earlier (e.g. 1984)
examples of literate programming, each variable is given its
own description and each piece of code has a detailed
explanation. This level of analysis, while justified for
tricky tracts of code, is probably not warranted for most of
the code that constitutes most programs. Such
over-commenting can even have the detrimental affect of
obscuring the code, making it hard to understand because it
is so scattered (see "spaghetti organization"
earlier). It is up to the user to decide when a stretch of
just a few lines of code should be pulled to bits and
analysed and when it is clearer to leave it alone.</BLOCKQUOTE>
<P><BLOCKQUOTE><B></B> In the case where there are a few rather tricky
lines of code, a detailed explanation may be appropriate.
The following example contains a solution to a problem
outlined in section 16.3 of the book "The Science of
Programming" by David Gries<STRONG>[Gries81]</STRONG>.</BLOCKQUOTE>
<P>
<PRE>
@C@<Calculation of the longest plateau in b@>
This section contains a solution to a problem
outlined in section 16.3 of the book @/The
Science of Programming@/ by David Gries[Gries81].
@D Given a sorted array @{b[1..N]@} of
integers, we wish to determine the @/length@/ of
the longest run of identically valued elements in
the array. This problem is defined by the
following precondition and postcondition.
@$@<Precondition@>==@{/* Pre: sorted(b). */@}
@$@<Postcondition@>==@{@-
/* Post: sorted(b) and p is the length */
/* of the longest run in b[1..N]. */@}
@D We approach a solution to the problem by
deciding to try the approach of scanning through
the array one element at a time maintaining a
useful invariant through each iteration. A loop
variable array index @{i@} is created for this
purpose. The bound function is @{N-i@}. Here is
the invariant.
@$@<Invariant@>==@{@-
/* Invariant: sorted(b) and 1<=i<=N and */
/* p is len of longest run in b[1..i]. */@}
@D Establishing the invariant above in the
initial, degenerate case is easy.
@$@<Establish plateau loop invariant@>@{i=1; p=1;@}
@D At this stage, we have the following loop
structure. Note that when both the invariant and
@{i == N@} are true, the postcondition holds and
the loop can terminate.
@$@<p=len(longest run in sorted b[1..N])@>@{@-
@<Precondition@>
@<Establish plateau loop invariant@>
while (i != N)
{
@<Invariant@>
@<Loop body@>
}
@<Postcondition@>
@}
@D Now there remains only the loop body whose
sole task is to increase @{i@} (and so decrease
the value of the bound function) while maintaining
the invariant. If @{p@} is the length of the
longest run seen so far (i.e. in b[1..i]), then,
because the array is sorted, the extension of our
array range to @{b[1..i+1]@} can only result in
an increase in @{p@} if the new element
terminates a run of length @{p+1@}. The increase
can be at most 1. Because the array is sorted, we
need only compare the endpoints of this possible
run to see if it exists. This is performed as
shown below.
@$@<Loop body@>==@{i++; if (b[i] != b[i-p]) p++;@}
</PRE>
<P>Where the code is more obvious,
it is often better to let the code speak for itself.
<P>
<PRE>
@C The following function compares two C
strings and returns TRUE iff they are identical.
@$@<Function comp@>==@{@-
bool comp(p,q)
char *p,*q;
{
while (TRUE)
{
if (*p != *q ) return FALSE;
if (*p == '\0') return TRUE;
p++; q++;
}
}
@}
</PRE>
<P>
<TABLE WIDTH="100%">
<TR>
<TD ALIGN="left" VALIGN="bottom"><A HREF="hints_make.html"><IMG SRC="binary/fw_left.gif" HEIGHT="32" WIDTH="32" BORDER="0" ALT="Prev"></A></TD>
<TD ALIGN="center" VALIGN="bottom"><A HREF="hints.html"><IMG SRC="binary/fw_up.gif" HEIGHT="32" WIDTH="32" BORDER="0" ALT="Up"></A></TD>
<TD ALIGN="right" VALIGN="bottom"><A HREF="hints_debugging.html"><IMG SRC="binary/fw_right.gif" HEIGHT="32" WIDTH="32" BORDER="0" ALT="Next"></A></TD>
</TR>
</TABLE>
<HR>
<FONT SIZE="2">
<A HREF="mailto:webmaster@ross.net">Webmaster</A>
<A HREF="copyright.html">Copyright © Ross N. Williams 1992,1999. All rights reserved.</A><BR>
</FONT>
</FONT>
</TD>
</TR>
</TABLE>
</BODY>
<!-- *********************************************************************** -->
<!-- End Of A FunnelWeb Manual Web Page (www.ross.net/funnelweb/) -->
<!-- *********************************************************************** -->
</HTML>
|