Literate Programming and Leo
jko9 writes "First proposed almost 20 years ago by Donald Knuth, the idea of Literate Programming is basically that of making program documentation primary, and embedding code in the documentation, rather than vice versa. Despite some obvious
advantages apparent to anyone who has struggled to understand a poorly
documented program, literate programming never really caught on.
That all could change, however, with the release of a new program called Leo,
written by Edward K. Ream.
Leo supports standard literate programming
languages like noweb and
CWEB, but with a crucial
difference - Leo adds outlines. The effect is striking: overall
organization of a program is always visible and explicit. Much of the narrative of the documentation gets placed in the outline, making documentation simpler, and allowing viewers to approach the code at various levels of detail. Screenshots and tutorials for Leo are here - if
that site gets slashdotted, you can download the visual tutorials in .chm
form or html form from Leo's
Sourceforge site. Leo is an open source program written in Python. Any current practioners of Literate Programming techniques out there? People
who have tried it and given it up? Can the addition of outlines to Literate
Programming make it more powerful / popular?"
My previous employer had a strict rule concerning code: you first write the JavaDoc for all the project, then implement it. It's useful as hell ... and if you mix that with UML design before the documentation, its a killer technique.
Life isn't like a box of chocolates. It's more like a jar of jalapenos. What you do today, might burn your ass tomorrow.
Few systems even allow multiple fonts in program text, although the original Bravo editor for the Xerox Alto did.
Did ANYONE learn (sic.) pseudo code ???
When i learned programming writing pseudo code was SUCH a big deal to the teacher that by the end of the year without even thinking i would write out the whole program in pseudo code, then, under each line of english add one line of code.
And has it ever paid off!
Now when I want to look at my own documentation, I just grep my java files and pull out all lines that begin with '//'
now when I am writing 20 pages of java code, and all my boss see's are comments I can tell him i'm am just writing Literate code!
Good day to you sir.
literate, without literate programming :)
Yuck. Leo is a "nifty" GUI which helps you do the outline. As I comment on another thread -- we programmers like our text editors thank you very much. I am ok with a visualization program but not one which takes over my workflow.
The main.cf config file of Postfix. Without the comments it's maybe 30 lines of actual settings. With comments its 540 lines, and it's clear enough that a relative n00b like myself got it up and running in 1 hr with minimal trips to the website. Good documentation was a major factor in my picking Postfix over Sendmail. No dis to Sendmail, you understand.
There are 01 kinds of cars in the world. The General Lee, and everything else.
If your code requires massive documentation within the code to make it understandable, then your code likely needs to be rewritten.
With most languages, the code itself is ample documentation. For instance:
Person &p = Person::findPerson("Harry");
cout p.name() endl;
Is pretty self-explanatory. Anyone can tell the output of this code. It's not that programmers need more documentation, rather they need better abstraction and encapsulation (insert your favorite argument for object oriented programming here).
int func(int a);
func((b += 3, b));
When we build systems, we work directly with the client and we are able to describe the system in three equal, but very different ways. Depending on the documentation required and the target audience, we can describe the system in a way that allows everyone involved to communicate effectively. This is an advantage I don't want to lose.
From what I've read, literate programming seems to be a discipline that works best when the programmers are isolated from the client. How it works when the programmers and the client closely interact is something I simply don't understand.
No Zen is good zen
Roedy Green has written an excellent, humorous online article on writing unmaintainable code. This relates directly to Literate Programming, especially Roedy's points about maintaining existing code. He writes (here): "[the maintainence programmer] views your code through a toilet paper tube. He can only see a tiny piece of your program at a time. You want to make sure he can never get at the big picture from doing that. You want to make it as hard as possible for him to find the code he is looking for. But even more important, you want to make it as awkward as possible for him to safely ignore anything. "
Literate programming in general, and Leo in particular, would be the ultimate cure for this. It allows you to easily navigate between multiple levels of description of a program. This is critically important if you are coming fresh to an existing piece of code. You need to constantly cross-reference the high-level design and low-level implementations (and the various levels of description between these extremes).
Sailing over the event horizon
I've tried Leo in the past, and while I support the author's ideas and the idea of literate programming in general, I do not believe that the practice will become significantly more common in the near future.
There are two reasons I believe this:
1. More and more modern IDEs support the idea of folding sections of code at multiple levels. Combine this with some well placed comments, and you achieve a very high degree of readability. This nullifies the primary benefit of Leo and ensures that most developers won't ever look at literate programming tools.
2. Changing over to literate programming is, at least superficially, a large change. It's a large change because it requires that developers switch their primary environment. That's a big deal. Even if developers had the tools for literate programming in their preferred programming language already in their hands, they probably wouldn't use it.
I do hope I'm wrong about the above though. I think a shift in the industry (even for a relatively short time) to literate programming would give us new ways of thinking about systems design, development, and would greatly ease long term maintenance.
Please mod this post only if you think others should/n't read this. I have enough ego^H^H^Hkarma. Thanks!
Every compiler vendor who has sold a mainstream language compiler/IDE using a "program database" or some other such approach has tanked. (Note that I mean program database as the primary means of storing the code -- a replacement of flat files, not an addition to them.) So far, it's not really been a technological lack, it's just that programmers don't like it.
I recall reading some papers written by the major language guys a decade ago, and one of the things they all wanted to see was per-function recompilation (instead of per-translation-unit), better program information (like "where is this function used?") and other things that would require a more database-like format. Still hasn't happened except in research environments. (Pity.)
One could, but one would be a lunatic.
(I'm too tired to write it all down now, but I'll just summarize by saying that XML is not a silver bullet.)
You cannot apply a technological solution to a sociological problem. (Edwards' Law)
The biggest problem with literate programming is that most people don't write programs that are worthy of exposition. Most programs are written under extreme time constraints to solve immediate or practical problems, and their complexity arises from handling exceptions, special cases, and last minute or ill conceived extensions. Documenting these with prose actually doesn't help very much, as the prose reads pretty much as the code does: as a set of ill conceived exceptions rather than bold themes. Making the prose flow well is just work that could be used to make the code better.
If your code doesn't have these faults, then the code is already an expression of the program ideas, and one that you can excecute, so in that case literate programming techniques are needed to a much smaller degree.
There is no doubt that literate programming (like extreme programming) has its benefits, but their principal benefits are to encourage an attitude of critical evaluation to your coding efforts. This criticism is encouraged in literate programming
but not a unique feature of that approach.
There is much pleasure to be gained in useless knowledge.
I don't think what he has is bad, but I think there a better ways to achieve cleaner code.
Many people have mentioned that writing cleaner code is the best form of documentation. This is definitely true, unfortunately you still have people who use letter for significant variables (i.e. not loop indexes) and who don't format their code or try to do too much in one line of code.
I think a better approach to documentation is the test driven approach that is used in XP and with packages such as JUnit and Cactus. Basiclly, you write your test cases first, which will force you to pin down the exact functionality for your components. These unit tests are essenailly doecumentation on how your components should work. Granted, this doesn't document the specific code but I think that one of the reasons why so much code is hard to read is because the functionality was not clearly thought through.
I also think API documention is more important. Alot of times I am trying to use an open source package and I have a hard time understanding how to use the API to achieve certian fucntionality. I can read the code just fine but it isn't clear how to use the objects themselves.
For example, many of the core java apis are well written and well documented. If you see the HTML javadocs, you can get a pretty good idea of the class.
However, when you open the source code of the same class, it is not good looking anymore. Why? Because each method is preceded with dozens of lines of javadoc, each of which is embedded with HTML markup. That is good when the javadoc HTML pages are finally generated, but not so good when you look at the source itself. C# is worse with its XML based documentation!
When I look at the source code, I want to see the flow of the code easily. All the documentation in the source should only aid this and not hinder this. Javadoc does both. The explanation part of the javadoc can be very useful in understanding what the author's intent was when he/she wrote the method, but I am not so sure about the rest. The param, return and exception tags are no doubt useful, but often developers don't explain these very well. Plus, these are the tags that can easily become outdated.
I would prefer short and succint pieces of information documenting the code, preferrably close to the line of code that it documents.
All your favorite sites in one place!
Something I didn't put in the original notice but now regret that I left out - Leo has another new feature more difficult to describe, but that which solves the problem that several people have mentioned about not wanting to abandon an existing text editor or tool. Leo can embed an outline structure in comments, so that one programmer can work with the file in JBuilder or EMacs, and a third programmer can still work with the program(s) in Leo. In effect, Leo is a meta-text editor. When Leo opens an outline containing a file that has been edited with another editor, all of the edits are retained. This is a further extension of LP because you are getting code read back into the documentation, which means that LP techniques can be used for understanding and/or teaching existing programs. It also means that Leo allows LP to be a secondary technique to add additional structure and documentation, rather than necessarily being the primary technique. This is explained in more detail in the tutorials and Leo docs.
.NET, but this ability to separate the outline from the program is something new, as far as I know. Also, unmentioned in the original article is the idea of having clone nodes, which means your outline can put the same code section into different branches simultaneously.
It is true that there are other IDEs that allow folding, e.g. Visual Studio
The following statements will be highly inflamatory to many people. They are not intended to be inflamatory but, rather a simple observation.
Basically, Leo is yet another tool to automate the documentation of programming code. There are dozens, possibly hundreds, of programs available for this task. Yet, the problem that these tools were designed to solve remain very prevalent, if not pervasive.
The reason that the problem remains and that Leo will not solve the problem either is relatively simple. Simply put, the problem is garbage-in, garbage-out (GIGO). These tools are not able to determine the purpose of the code or the intent of the programmer that is writing it. These tools cannot read the minds of the programmers. The tools rely on the programmer to write out their thoughts and the intended purpose of the code.
Most programmers are unwilling or incapable of performing this critical step thoroughly. All too often, they use shorthand and expect the reader to understand what they mean. Or, they believe that the reader should be able to understand their thought process by reading the code itself. Furthermore, they assume that if the reader can't do this, they are simply not a good programmer (1337).
To go a step further, many programmers are not capable of clearly expressing their thoughts in their native tongue. These people are quite brilliant and can do amazing things with their code but, they can't express their thoughts to another person unless that person is indeed, able to read and comprehend the code itself.
Now, in fairness to the programmers, we have to look at what they do and what they are taught. Most programming languages are all about efficiency. They rely heavily on abreviations and aliases, why do you think it's called code? They are designed to require a minimum or typing while providing a maximum of functionallity. The programmers themselves are always striving for increased efficiency both in their code and in the way they get the code done. They always try to put out more which leads to further shortcuts and abreviations. This all tends to make programmers minimalists and their documentation clearly reflects this.
So, Leo is unlikely to provide any documentation breakthroughs. The old rules still apply, garbage-in, garbage-out. The best idea I've seen was an earlier post, where the documentation is written first and then the code is developed to match the documentation. But, honestly, which of us going to do it that way. That's a lot of work and our ingrained habits are going to be hard to break.
IOOC 911.11? Would that be the International Olive Oil Council, or the Iranian Offshore Oil Company?
Not to feed the troll, but for the benefit of any impressionable young programmers:
The goal of a programming language is to provide a machine with a set of instructions, not to sit down and read it a story.
Programming languages intended for use by humans (as opposed to languages intended primarily for machine generation) have multiple goals, three of which are to be human-writable, human-readable, and human-maintainable.
Literate programming may not be a perfect solution, but it's addressing a real issue. Current programming languages tend to be pretty horrible at expressing abstractions in a human readable way. The ideal programming language would be one that allowed you to express abstractions at the level of the problem domain, yet was able to translate that into something as efficiently executable, or close to it, as something written in a lower-level language. Literate programming allows you to do something along these lines, although it still involves a fair amount of "manual intervention" on the part of the programmer.
I am more of a technical writer than a programmer (well, really, I'm not much of a programmer at all), but it was always clear to me that 90% of the software development headaches I lived with at various companies could have been resolved with minimal effort early in the project.. IF anyone cared about using a methodical approach to project documentation.
But nobody likes documentation. Writing it. Reading it. Just the word makes some people itch. For some reason, this is something that BOTH business managers and programmers don't get: documentation saves work. It is a way to produce a testable set of requirements, then a testable architecture/design, then a way to match up features and metrics in production and testing.
I mean, why does everybody think writing the manual is the LAST thing you do when you make software? With all the snarky "RTFM" comments I hear from geeks, I should start a new variant...
"PUHLEASE! BEFORE YOU START CODING, WTFM!"
I've got a bad attitude and karma to burn. Go ahead. Mod me down.
For a project I am working on, I needed to extend CWEB to do some things Knuth hadn't thought of, and I found that excessive cleverness in the data structures made it much more difficult to extend than it should have been, so that Knuth could demonstrate clever data structures that probably add a few percent to the performance over what he could have achieved with more prosaic ones (Knuth does not document why he made these excessively clever design choices, nor whether the performance advantages they offer were significant).
Similarly, a recent thread on comp.text.tex recently asking about the extensibility of TEX produced a number of comments from those who know about how unextensible and unreusable TEX really is.
So, while I use literate programming (CWEB) to document a lot of my own code, I don't believe in all these years, that I have ever seen a good example of literate-programming that looks towards the future (refactoring, extending, reusing) as opposed to generating a fossil with that comes with a good story of its life and times.
There's an old saying (was on a "Murphy's Laws of Computing" poster I used to have): "make it easy for programmers to write in English, and you'll find that programmers can't write in English."
Others have pointed out the all-too-common case where the code gets edited but the comments don't. This is bad, but not as bad as another common case: the programmer tries to comment the code, but his/her grasp of English isn't up to the task. This may be because English is a second language, or simply because the person specializes in computer languages, not human ones. In any case, the result is frequently misleading or incomprehensible comments that either do no good, or worse than no good. And, of course, deadline pressures never help.
I think Literate programming is a wonderful idea, but I don't think it's a practical one in many (most?) real-world environments.
I would like to distinguish between the techniques of literate programming and the practice of literate programming (LP) as it has always been done before Leo (traditional LP). The key technique of LP is what might be called "functional pseudocode." For example, here is a fragment of code that can be written in Leo:
The line: << do something complicated >> is a section reference. It works pretty much like a macro call. In particular, the code in the defintion of << do something complicated >> has access to the done and result variables. This is almost the entire content of noweb, one form of literate programming. It turns out that this technique can be extremely useful, as simple as it seems. Leo creates one or more "derived" files from an outline automatically when the outline is written, and Leo can update the outline from changes made to derived files when Leo reads the outline.In contrast to the technique of literate programming, the practice of traditional LP has focused on the central role of comments, and lots of them. Here is where Leo radically parts company with the LP tradition.
One's view of the proper role of documentation in a project hardly matters to Leo. You are free to use comments as you always did, though you will probably find that LP as implemented in Leo helps you out in unexpected ways. I discuss at length and in great detail the relationship between traditional LP, comments and Leo here. In short, discussions about the role of comments in programming (literate or not) do not get to the heart of Leo.
In fact, Leo often reduces the need for comments. Indeed, it is good style to organize Leo outlines like a reference book. Well-designed Leo outlines act both like self-updating tables of contents and self-updating indices. This is in marked contrast to the "stream-of-consciousness" or "narrative" style typically employed in traditional literate programming.
In my view, the essence of Leo is this: Leo makes outline organization the most important part of a program or a project. Both code and documentation could be considered secondary. At every moment, the overall big picture of a function, class, module, file or project is always at hand. Moreover, Leo makes outlines structure a part of the computer language. For example, I often define a Python class as follows:
The @others directive acts as a reference to all the text in all the outline nodes which are descendents of the node containing this class declaration. Such nodes are copied to the output (derived) file in the order in which they appear in the outline. The reference << declarations of myClass >> ensures that those declarations precede the methods. There are several other ways that outline structure is important in Leo; I won't discuss them here.
Leo fully exploits the organizational power of outlines. A single outline typically organizes an entire project. Outlines can handle large amounts of data with ease. Moreover, it is possible to clone any part of an outline so that changes to one clone affect all other clones. This is feature makes it possible for a single outline to contain multiple views of a project. For example, when fixing a bug, I clone all nodes related to the bug and gather them in a new part of the outline, called a task node. This task node effectively becomes a view of the project that focuses exclusively on the bug. Any changes I make to code are propagated to all other clones.
Earlier I mentioned that a well designed Leo outline acts like self-updating tables of contents and self-updating indices. Tables of contents you get for free: an entire outline is the table of contents. Clones create self-updating indices. For example, each task node acts like the index entry for that particular task.
- Edward K. Ream
None of that is true for technical writing. It's a discipline onto itself. It's not just about good writing. (I've known computer scientists who'd written award-winning papers and articles, but couldn't write technical docs worth beans.) It's about understanding your audience and the (often painfully boring) task of writing in the clearest possible language.
Not every project needs technical writers. If you're a small software shop, and you're building a set of components with an uncomplicated API, and hiring a professional writer isn't cost effective -- then yeah, use Javadoc or some other LP tools.
But for big projects... Back in 1998, I was in charge of production for the doc set of a large Java framework. Having the API docs embedded in the source code was a nightmare. Javadoc was supposed to allow any of the engineers who wanted to to do their own API docs -- but many botched it, because they didn't understand Javadoc or HTML very well. We had professional writers, but many of them couldn't be trusted with source code. Hell, some of them didn't understand why they couldn't edit the SCCS archives!
Worst of all was when the release cycle entered code freeze. Document freeze is always later than code freeze -- but you cannot let people modify the release code base during code freeze. The only solution was to split the source, then merge the docs back in after release. Very painful.
This is absolutely on the mark.
I believe that WEB was a great improvement over Pascal at the time that Knuth began to use it. However, it does not solve the underlying software engineering problem. Knuth's style at the time of TeX, etc., involved very little abstraction.
The biggest problem this causes is that the major data structures in TeX do not have well-defined or factored interfaces that allow them to be easily changed or extended. Furthermore, important details of these data structures are basically undocumented, and often cause interdependencies between different portions of a WEB that are not at all obvious.
If you wish to see the problem face-to-face, look through TeX: The Program at the "inner loop" and see how many different sections of the WEB that you would have to understand.
A similar problem is his use of enumerations with certain magic values, where the magic is documented (or becomes apparent, while still undocumented) some distance away from the point of definition.
Another serious problem with WEB is that it allows one to completely obscure the sequential nature of the program. Many times, one chunk depends on initialization that was performed by another chunk. If Knuth decided to make some laconic comment rather than remind you of that initialization, good luck reconstructing the sequential dependencies.
If one is writing monolithic programs, writing them like a Russian novel might be easier to comprehend than one large unformatted source file. However, if one has the alternative of writing a highly modular program with clean interfaces, I don't really see any advantage to breaking up and rearranging the underlying code.
I'm not a big fan of abusing Java's interfaces (an interface for each implementation hierarchy), but in a big project that has to be properly documented and strictly specified, this would seem to help.
The interface is after all closer to the specification level, so your documentation can be strictly about the specification. Then you can let the programmers code, document and freeze the implementation independently from the interfaces.
Since an interface doesn't have any implementation sourcecode, writers could be trusted with the files, and since the interface API per se is frozen at design, they can keep modifying the Javadocs without affecting the coders.
If the writers have to modify the API per se and recompile an interface, they are changing the specification (re-design) and of course the coders are forced to adapt their code to those changes.
But otherwise there would be no need to "split the source" and then "merge". All you would have to do is provide the Javadocs for your interfaces (plus a manual based on this, perhaps) and the Javadocs for your implementation (if implementation details are to be exposed, such as efficiency guarantees, etc).
If anything, I would think the split would improve documentation.
Freedom is the freedom to say 2+2=4, everything else follows...