Hacker News new | past | comments | ask | show | jobs | submit login
A new way to think about programs (github.com/raganwald)
130 points by mrduncan on Nov 8, 2010 | hide | past | favorite | 29 comments



We did something similar we did when the company I work for specialized in consulting, back in the late '80s. At the end of a project, one of our deliverables was usually something we called "left hand pages".

It consisted of a binder with a complete listing of the source code we produced for the client, with the source code printed on the right hand pages. On the left hand pages was a detailed commentary and explanation of the corresponding right hand code. Extra space would be inserted in the right as necessary to make room for the left hand commentary. We would not skimp on the left.

The commentary was aimed at being all a new programmer at the client would need to take over maintenance and enhancement of the software. It was assumed he knew the language, and had a copy of and understood the hardware specs. Of course, hardware specs often deviate from what the hardware actually does, and we'd cover all those oddities and deviations in the left hand pages.


How do you keep both sides in sync? Special comments in the source that get printed as left-hand pages and suppressed from the right-hand ones?


It was pretty low tech. I seem to recall we'd do something like write the left hand pages in a word processor, then we'd use the page preview mode to see how the pagination of that was going to work out. We'd make a copy of the source code in a text editor, and insert blank lines as appropriate to get it to line up reasonably. Then I believe we'd print the left hand pages on the laser printer, turn the sheets over, and print the source code.


Literate programming, at least at Knuth defines it, includes some aspects which Docco omits.

Firstly, the machine readable file can be output in a different order than the human readable. (Indeed, sequential chunks in the human readable output can be directed to multiple different files.)

Secondly, the human readable file includes 'outlining': when describing a function, parts of it can be elided and covered later.

Now, these may have been required because the target language was C(like), which has different properties from many other languages. But I did want to point out that Docco is a quite different point in the literate programming landscape.

For examples, see a couple of literate programs that I've written.

With Web (Knuth's tool): https://github.com/agl/rwb0fuz1024/raw/master/rwb0fuz1024.pd...

With my own tools: http://www.imperialviolet.org/binary/lsmsb.html


Fortunately, in most modern languages, functions can be defined in any order -- and baseline configuration can be included in a separate file.

In this day and age, generating the machine-readable version of the file in a different order than the version that is meant to be read, seems like an unnecessary convolution and debugging hurdle.


Sure you can define the functions in pretty much any order, but can you define two or more functions at the same time?

Say you are talking about the function to build the user interface, can you stop defining that, go back and define the callback, then continue defining the gui builder function?

Or, when you are writing an Android program, can you add stuff to the manifest file, right as you write the source code that uses it?

Or, when you are writing that rails app, can you put the code for one of your user stories, then extend your db model and finally add the code that test it -- before you continue with the next user story that adds code to the same controller?


> Say you are talking about the function to build the user interface, can you stop defining that, go back and define the callback, then continue defining the gui builder function?

That's how lisp folks worked. I don't see why that technique wouldn't work in bare python as well.

Static type systems can make that difficult. How many frameworks impose analogous constraints?


Not necessarily. I can see some value in having a different organization for explaining the program to someone new to it vs organizing it to make it easy to maintain for someone familiar with it. For example, for maintenance you'd like to have all of your constants defined together and usually near the top, but for documenting you'd probably prefer to introduce constants when they're needed.


I am working on system which (I hope) will be 5GL. I use literate programming as it main programming language. I cannot use any 1/2/3/4GL language in the system because of lot of limitations in 3/4GL languages. My system operates on meta-meta-data about code. I can define meta-meta-data about code using literate programming only.

If you will look at some existing systems, which operate with meta-meta-data, like yum/rpm, or apt/deb, or maven2, etc., then you will see, that code, which describes packages, is literate-like: it contains author, title, description, general overview of package, etc. It does not contains function, or something like that.

If my English is wrong - sorry. I am Ukrainian.


Literate Haskell seems to minimise the first difference (Haskell allows you to define functions out of order).

I'm not familiar with outlining. Does anyone have a simple example?


Check out 'libavl' which was written in the literate programming style: http://www.stanford.edu/~blp/avl/libavl.html/


One of the more unique programming approaches I've come across is the Leo editor, which was written to support literate programming but also functions as an outliner.

When you're working with Leo, you work with a tree of text nodes instead of working with explicit files/directories. Because the nodes exist in an always visible tree, the natural inclination is to label the node with what the code inside does. This subtly enforces literate programming.

This is good, but what makes Leo novel is the nodes can be cloned (think hard symlink) and then rearranged however you like. You can put a node containing a function's unit tests and another containing its documentation as children of the node containing the function. When fixing a bug, you can create a node that points to the issue's url in your bug tracker and then clone all related nodes as children for both documentation and convenience when you're working on the bug. When working on frontend code, you can clone nodes for related js/html/css for conveniently switching between them. It's very cool.

Unfortunately, it's not really practical to use it as your primary editor. Ed serializes/deserializes the nodes to files using sentinels in comments, so the output files tend to wind up with a lot of "junk" comments. I also missed the Vim command grammar a lot.


This sounds like the inmos transputer development system and the various editors that descended from it.


For folks wondering about what the "CoffeeScript is about to get even more interesting" bit is about, it's just the past month of changes since 0.9.4, which are considerable indeed:

https://github.com/jashkenas/coffee-script/compare/0.9.4...m...

If this article inspires you to get started, and you don't mind doing a little bit of legwork to figure out syntactic changes, I'd recommend starting with master instead of 0.9.4.


When do you estimate 1.0 will be out? (Great work by the way.)


When it reaches it's first anniversary... It'll be under the tree by Christmas Eve.


This isn't actually literate programming as Knuth defines it (If you read his 1984 paper, he specifically talks about _writing the code in such as way as to inform the programmer about what you want the computer to do_, which means that you write the code and documentation at the same time.

In addition the literate programming tools that came from Knuths original all allow you to order the in the order you find makes sense -- not in the other required by the compiler.

This, while very interesting, is much, much closer to Elucidative programming[1], which is less well known but is also properly easier to get started with.

[1]http://www.cs.aau.dk/~normark/elucidative-programming/index....


Jeremy Ashkenas (creator of Coffeescript and of docco) is uniquely positioned as an expert in accessible technology.

See his hypertext visualization of his thesis project or the various visualizations of government data in his portfolio. He works at DocumentCloud on similar themes.

http://ashkenas.com/


A new implementation of a way to think about programs may be a more accurate title. Quite enjoyed the article though, plus anything giving coffeescript love has my vote.


Luke Gorrie created a tool to format program listings for paper using emacs: http://fresh.homeunix.net/~luke/misc/emacs/pbook.el

Here's a rendered example of using the program on itself: http://discontinuity.info/~pkhuong/pbookc.pdf


The rendering seems pretty good. The prose needs some work though. It was only marginally more useful than relatively sparse comments. Didn't seem to add the value I was expecting.


If an exception is thrown in a Coffeescript program, does the runtime correctly report the original Coffeescript line numbers instead of that of the compiled Javascript? Things like this are the main reason why I'm wary of compilers that compile to another high-level language.


In practice, this isn't a problem. Coffeescript is more of an alternate syntax for Javascript than a different language. Sure it has some great sugar, but it's really easy to understand how that sugar translates into plain old Javascript. I'll usually have the .js file sitting in the next tab, being compiled live as I write code in the .coffee tab and hit save. Work like this for a little while and you'll learn to recognize which javascript is generated from which coffeescript really efficiently.

  coffee -cw -o js/ coffee/
Plus, your variable names in Coffeescript are well-preserved in the generated JS. Ultimately I find it harder to follow exceptions in my production javascript because of the obfuscation caused by minification (I use yuicompressor), so on my staging and development servers I point to a non-minified .js.

Bottom line: try it, you'll like it!


Your errors list JS line numbers. I didn't find it very difficult to mentally map the JS errors back to my Coffee source though - you get the same program structure and variable/method names before and after compile.

Let's say you found a bug in line 41 of my JS source here: https://github.com/dpritchett/chatbox/blob/master/public/cha...

Digging into the Coffee source shows the same short method with all the same identifiers and the same basic structure... just less boilerplate: http://dpritchett.github.com/chatbox/docs/chatbox.html#secti...


Aha, your answer is more concise, and it addresses FooBarWidget's misapprehension more directly. Yes, "the runtime" is just the browser javascript engine.


I'd seen a few of these pages before, but never known what they were called.

I've also heard of literate programming, but never given it a real shot. Combine that with a recent effort to write more, and this all seems right up my alley. Super cool.


The pseudocode programming process (PPP) described in Code Complete strikes me as quite similar to the concept of literate programming.

In PPP the idea is to start with pseudocode in the form of source code comments that start with a very high-level overview of the task being accomplished, written in plain English (or whatever human language), which is then broken down into smaller and smaller constituents.

When the explanation can no longer be decomposed, the actual code is written.

That approach seems like it would suit the literate programming style very well, and in particular would make the documentation generated by Docco easy to read and comprehensive.

That said, I've never really used PPP and prefer TDD instead.


I don't get it. I've read MozDev's Re-Introduction to Javascript and the coffeescript looks just as clean.


"Going from Javascript to Coffeescript today feels a lot like going from Java to Ruby felt to me in early 2003."

One should really wonder, why did he skip on Python, Perl and Ruby for all those years? Knowing that RoR appeared in 2004, and thinking that Coffeescript seems closer to Python




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: