[comp.lang.ada] comments on comments

rjh@cs.purdue.EDU (Bob Hathaway) (02/11/89)

Dave Jones [djones@megatest.UUCP] Writes:
>Here are some remarks that I wrote up for one of the
>members of my programming team.  I hope they will be
>helpful.

Thanks, I agree good documentation is invaluable.

>
>In my opinion, the most important parts of a program to document
>are the structure-declarations and the variable-declarations.
>

This is true, but alternate design strategies can call for an
extended perspective on documentation.  When using an object
oriented design strategy, I'll first write a design document
describing the primary objects in the system and their operations.
Also in the document will be a high-level description of the
important procedures written in an informal PDL, such as a pseudo
Ada code.  For objects (Adts), first is a description of the object and
its rational and system context.  For instance, what the object is
intended for, why I chose an abstract data object or an abstract data
type, and possibly how it will interact in the system, but
the last part could go in a separate document as pointed out
by Dave Jones.  Second is a numbered list of operations and their 
descriptions.   When the entire system is complete, the declarations
can be coded in a higher-order language.  In Ada, the design is directly
implementable as compilable specifications.  In Modula or some other
language in which the specifications aren't compilable the procedures
can be filled in with stubs or empty declarations.  The design document
can be included as comments and updates to the document and code should
be done concurrently.  The object descriptions are included in the
specifications and optionally in the package or module body, and the
(numbered) operation descriptions included for each procedure or method.

>Here's a good way to go about it:
>
>/*******************************
> * This is one block comment,
> * and it is easy to modify.
> ******************************/
>

Here's another way:

/*
 * my_procedure
 *
 *    <ADT design document index>
 *    This is a description of...
 *    ...
 */

             Bob Hathaway
             rjh@purdue.edu

rjh@cs.purdue.EDU (Bob Hathaway) (02/23/89)

(I write)
>|This seems to go backwards.  Programmers should first design
>|their software then implement it.  You seem to be advocating 
>|implementation then design.  The descriptive algorithm should 
>|come first, then the code.

In article <9689@ihlpb.ATT.COM>, nevin1@ihlpb.ATT.COM (Liber) writes:
>I have a problem with Top-Down programming (design then
>implementation); it happens to be the same problem I have with
>Bottom-Up programming (implementation then design).  You so eloquently
>point it out in your next sentence:  

Design then implementation is not necessarily top-down programming.
First some terminology.  Top-down design involves a functional view
starting at the top and working its way down.  Top-down implementation
is a programming methodology which begins coding (implementing the design)
at the top level procedures.   Bottom-up design also involves a 
functional (procedural) view but starts design with the bottom level
procedures and bottom-up implementation begins coding with the bottom
level procedures.  For the past several years (since my first program)
I began with an Adt, or more object oriented approach to design and
implementation.  I would study the problem and form an informal solution
and identify the Adts (objects in the system).  The informal solution
would be in a high level pseudo-code and was usually top-down for the
main program and within modules.  This provided a modular design with
abstract data types.  It could also be categorized as a top down design
with the data structures and functionally related subprogram units
encapsulated within modules.  The Adts provided an excellent starting point
for coding.  They could be separately tested and frequently the driver
program for these tests was most conveniently the original program and
after "testing" my Adts the program was finished.  The fact that I was
often done weeks early attested to the techniques success.  The informal
pseudo-code is refined into working code but since pseudo-code usually
offers a more informal description of an algorithm than working code,
it is easier to understand.

>|If the algorithm can be coded in a
>|truly self descriptive form no comments will be necessary but in
>|instances where the design and implementation are not the same,
>|comments help.

>But design and implementation should not differ!  If this is happening,
>one of the two is wrong!  In the case of Top-Down, I would guess that
>it is probably the design that is wrong; something wasn't taken into
>account until someone actually tried to implement the design.  The

I disagree.  Pseudo-code is much easier to read than programming code.
Comments reflect algorithms in an informal way that is more understandable
than programming code.  They are semantically equivalent, but if I think an
informal description is easier to read, I'll provide it (you can put me in
the conscientious category of programmer who is always trying to write better
software).  When an algorithm can be directly expressed in code (ie. just add
underscores) as is often the case, comments aren't necessary.

>problem with Top-Down (and Bottom-Up) programming is that there is no
>feedback mechanism.  What happens when an implementation discovers a
>bug in a design?  Does it happen that people go back and formally
>re-review an already approved design document?  Not nearly as often as
>it should, I suspect.  Or at least go back and change the design to
>match the implementation?  It gets even worse when there are many
>levels to the design.  There needs to be a feedback loop.

Any conscientious programmer will update the appropriate documents.  But
if put on a system where the comments are in doubt, I can always ignore
them.  When working with large C programs, I often waste a lot of time
trying to understand undocumented field declarations and incomplete function 
descriptions.  A correct comment would save time and it should be obvious
from the code if a comment isn't accurate.  As suggested in an earlier
article, large software projects with elaborate standards can hold design and
code reviews to insure correctness.

>|True, but requiring Joe Programmer to design his software first will help,
>|and the design can be included in the comments.

>Yes, but until we have good hypertext systems that will allow Joe
>Programmer to do this easily and painlessly, he basically has to
>maintain TWO design documents, and when a human being has to do it, it
>tends to get out of sync, and eventually useless.

Yes, thats why there are software development environments and APSE's and why
I keep asking for them:-)

|I think the poorly designed, poorly documented systems have caused most
|of the trouble, not out-of-date commenting.   Just follow the convention
|that when code is updated so are the comments.  The benefits of a well
|commented design far outweigh the costs.  Well documented code is easy
|to understand and modifications to the software can be done in terms of
|the higher-level design.  Since the design is directly implemented in the
|code, corresponding changes should be easy.

> The real question is:  what can we do to make this happen?

Be conscientious!

Bob Hathaway
rjh@purdue.edu

djones@megatest.UUCP (Dave Jones) (02/23/89)

In an article by rjh@cs.purdue.EDU, Bob Hathaway says that he usually
uses ADT's to do top-down design and implementation...

If it works for him, that's great.

I too have been designing all my programs around "abstract data-types"
for some time now, although not since my first program, as he has. 
I started programming for bucks back in '71, when we didn't think of 
such things.  Indeed, I sort of evolved into the practice years later
as a result of much head-scratching. Only afterwards did I discover that
I was not the only one to have dreamed up the technique.

But I don't usually do top-down.  I do bottom-up.  Design, implementation,
test, everything.  It actually shocks some people when I say that. In the
seventies "bottom-up" became a dirty word.  Never mind that top-down
methods resulted in some of the most inflexible code every put to disk.
Top-down good. Bottom-up bad. Unnngghh. :-)

I'll freely admit, there are times when top-down is the way to go.  But
it's not the way I do most of the programs I write by myself.

I start out with a "bottom" that consists of lots of -- okay, I'll go 
along with the name -- ADT's which are likely to be of use in just 
about any kind of program: lists, queues, hash-tables, avl-trees, 
flexible buffers, priority queues and so on.  Next I use these to form 
ADT's which are specific to the low-level objects under consideration, 
etc.  And so it goes from bottom to top.  The payoff comes when you want
to change something. All you have to do is reshuffle these building blocks,
which are still quite useful. But if you go from the top to the bottom, 
a change at the top is likely to invalidate the whole blasted thing.

I sometimes carry it to unlikely extremes.   My group is writing a Pascal 
compiler. If ever there seemed to be a top-down kind of task, that seemed to be
it.  I mean, Pascal is already done, for Pete's sake.  There are standards
documents which tell you what a Pascal compiler absolutely *has* to do. But..
I started out with my bag of standard ADT's anyway, and then defined some
more: Pascal blocks, types, parms, variable-accesses...  just about
every kind of Pascal-object you can think of.  One by one we implemented
them as we worked our way up to type-definitions, expression-trees, statements.
The methods for these ADT's went into a library.

It was only a matter of a few weeks, long before the compiler's high level 
was anywhere near finished, that it paid off.  Another group was doing 
a mouse-driven frontend for the interactive embedded compile/load/go
feature that we have.  They needed to be able to capture all of the 
type-information, formal parameters and so forth about the program being 
run, then fish around in it finding all the variables of this type, 
building all the short expressions that are assignment compatible to the 
second formal parm of procedure foo, etc..   

No problemo.  

Just link with the new Pascal-compiler-library and do yo thang! 
I was psyched.

Try doing that with a Pascal compiler that was designed top-down to
be a Pascal compiler.

billwolf@hubcap.clemson.edu (William Thomas Wolfe,2847,) (02/24/89)

From article <2325@goofy.megatest.UUCP>, by djones@megatest.UUCP (Dave Jones):
> In an article by rjh@cs.purdue.EDU, Bob Hathaway says that he usually
> uses ADT's to do top-down design and implementation. [...] But I don't 
> usually do top-down.  I do bottom-up.  Design, implementation, test, 
> everything.  [...] I'll freely admit, there are times when top-down 
> is the way to go.  But it's not the way I do most of the programs I 
> write by myself.  I start out with a "bottom" that consists of lots of
> [general-purpose] ADT's [...].  Next I use these to form ADT's which 
> are specific to the low-level objects under consideration, etc.  

    The relevant literature states, I believe, that most good programmers
    combine the top-down and bottom-up techniques; the programmer typically 
    starts with two interfaces and a semantic gap, and then builds each 
    interface in the direction of the other in some programmer-dependent 
    ordering, ultimately bridging the gap by joining the two interfaces at 
    some point in the "middle", somewhere between the two.

    Thus, rather than argue which face of the coin is better than the
    other one, perhaps the participants in this discussion should 
    recognize that each strategy has its advantages, and that each 
    functions best when applied in conjunction with the other. 


    Bill Wolfe, wtwolfe@hubcap.clemson.edu