| From: | Kenneth Brittain |
| Date: | 28 Feb 1996 |
Bravo.
Are there any published works (book or DVI), of significant length, that demonstrate literate programming using an OO language (such as C++)? I currently use CWEB/TeX to do my C++ literate programming. I have read the examples provided at the "Literate Programming Library". They are helpful but are only examples.
Here is my problem: I have adopted the style of placing the interface and implementation into a single web then having ctangle extract my external headers via the "@(class.hh@>" command. This works, however, it does not use literate programming to its fullest. It seems that I could do the same thing by commenting my code (sometimes). My general pattern winds up being:
@ Explain this rather short member function.
@<The member function@>
void Class::Member (void)
{
if (AnotherMember ())
SetSomething ();
}
@ @<Public@>+=
void Member (void);
I have read the object-oriented discussion at the LPL on the WWW and it seemed dated
(1992-93). Has there been any further discussion/progress made by people or tools in
using OO and literate programming together? My concern is that at the end of a project I
have some rather well documented classes but a less documented system. This is not bad
but it still not the desired effect of literate programming.
| From: | Norman Ramsey |
| Date: | 28 Feb 1996 |
Not necessarily a bad thing. Here are some comments based on my experience writing Modula-3 programs using noweb. It is often a good idea to keep interfaces (.hh for you C++ people) in a single chunk, since if the interface is small enough people can comprehend it all at once. For larger interfaces I may break it into several chunks with intercalated documentation (see the SRC interfaces for many examples of this style), but I never interleave interface and implementation. By contrast, when I write C code, I routinely put prototypes next to definitions.
Literate programming tools enable one to reorder code and to interleave documentation. In Modula-3, I seldom need to reorder, because
Almost all my Modula-3 code is simple enough that I put several related interfaces and an implementation in one source file. Interfaces go one per chunk; implementations usually have one procedure per chunk. Sometimes I will put several simple, related procedures in one chunk. Caveat: I have described a strategy I use to write better code, not what I do when writing a literate program for publication. Interested parties can try to chase down the ldb source from my home page.
| From: | Florence Maraninchi |
| Date: | 28 Feb 1996 |
I recently experimented noweb/LaTeX with C++, for writing a compiler front-end. What I found interesting is the incremental design of the structure of the abstract tree. I have a single noweb file from which I can extract: lg.yacc, AbstractTree.cc and AbstractTree.h. The classes in the module AbstractTree are all of the form:
class Foo {
... Foo1 ;
... Foo2 ;
<<Foo-AdditionalAttributes>>
public:
... FooMethod1 (...) ;
... FooMethod2 (...) ;
<<Foo-AdditionalMethods>>
} ;
where <<...>> is the noweb notation for code chunks. In the doc, you find a YACC
rule together with the definition of the class you need for storing this subtree, and its
constructor.
At the beginning, <<Foo-AdditionalAttributes>> and <<Foo-AdditionalAttributes>> are empty code chunks. AbstractTree.cc contains only the definition of the classes and the implementation of the constructors called in the yacc, for getting an image, in memory, of the source file.
Then, I start decorating the tree, by adding attributes and methods for dealing with them (print methods, links between use occurrences of identifiers and the corresponding definition occurrences, symbol tables...). The important point is that this is done in separate noweb files, in which I can redefine : <<Foo-AdditionalAttributes>> and <<Foo-AdditionalMethods>>.
Then I just have to cat the noweb files and to pipe the result into notangle, in order to obtain the complete definition of the classes. Of course, when I do this several times, the complete definition of the class in AbstractTree.h has a large number of attributes and methods, and is hard to read. But who cares ? I am happy with the structure of the doc.
When I was using C++ without noweb, I always had a lot of files opened for editing (the .h, several .cc) and I had to navigate between them. Now I use literate programming mostly for putting together in the same section of the doc, things that are designed together, even if they end up in different source files. Literate programming provides a super-level of structure, and you can really organize your code as you think it. Literate programming frees you from the particular structure of source files imposed by your programming language. Comments or reports about literate programming and C++ are welcome.
| From: | Felix Gaertner |
| Date: | 01 Mar 1996 |
I have a rather practical question concerning noweb and file naming: For a C++ class for example, I don't want to have both specification and implementation in one file. However, now I have a problem of how to call both files! Both are written in noweb, so they should have the suffix `.nw'; but both belong to the same class, so their names would come out identical.
What standards have you adopted to get around this problem? An idea would be to call noweb header files `.nwh' and implementation file `.nw'. But this would work only for certain languages. A different approach would be to use mixed suffixes, e.g. `xxx.h.nw' and `xxx.c.nw'. In any case, do you think this is a problem?
| From: | Joachim Schrod |
| Date: | 11 Mar 1996 |
Karel Zuiderveld writes: The main advantage of noweb is that I can have both specification and implementation in one file.
That possibility is the main disadvantage of any literate programming system. It blurs away the important distinction between specification and implementation: These are two documents for different audiences. The implementation might include the specification for reference (by \input or @i), but the specification should never ever include the implementation.
Please note that I don't argue on the programming language level: I want to emphasize focus on the human reader (that's what literate programming is about, isn't it?). If one explains the contract of one's module for potential users, one should use different presentation styles than while presenting the realization. That's best done in another document. We should not throw away the most important lessons software engineering has learned since the 70s just because we use a literate programming system.
| From: | Benedikt Stockebrand |
| Date: | 12 Mar 1996 |
Well, while I haven't actually used it myself, Eiffel doesn't even have a ``formal specification'' but a tool that basically extracts the specification from an implementation. I don't know if I got the rationale exactly right, but it's basically that you can only cast syntax into a PL specification file --- but the major thing about any specification is its semantics, and you can mess that up without ever touching the syntactical specification. It seems a better solution to keep everything together at an implementation level and then extract the specification automatically.
Initially I was opposing that approach, but by now I use a little shell script that uses a "#pragma header <headerfile>" and "#pragma noheader" to extract the include file parts out of a C/C++ program. If you want to find out about this, check B. Meyers "Object-Oriented Software Construction", Prentice Hall. I don't like Eiffel much as a bondage and discipline language, but it sure gives some insight.
Finally: Considering a header file to be a ``specification'' seems quite an oversimplification to me. It doesn't only contain function prototypes but also macros --- take a look at stdio.h. With C++ it's even worse, there are the non-public parts of class definition bodies, inline functions and even complete class template implementations. If you want some proper specification the best thing to do is to use a separate text.
Well, in the 70s I didn't know anything about computers yet. But I don't suppose that at that time there were things like make, source level debuggers, profilers, optimizing compilers or turn-around times measured in seconds. Today's development platforms are much more powerful and we'd be fools to do it ``the traditional way'' because back in the stone age that was the best way to do it.