documentation as source

R

Randy W. Sims

Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes diverge
from its documentation. So maybe there could be a way to specify the
interface: the number of arguments and their types in the documentation,
and possibly pre- and post-conditions, and then the documentation would
be turned into code at runtime. I guess this would be implemented
something like Perl's source filters[1]. Possibly some constants and
such could be defined this way as well, version numbers, etc.

I'm not sure if this is a good idea or not; I haven't completely thought
it through. It seems like I've read about this being done before in some
other langage, but a brief search hasn't turned up anything.

Any thoughts?

Randy.

1. <http://perldoc.com/perl5.8.4/pod/perlfilter.html>
 
J

Jamis Buck

Randy said:
Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes diverge
from its documentation. So maybe there could be a way to specify the
interface: the number of arguments and their types in the documentation,
and possibly pre- and post-conditions, and then the documentation would
be turned into code at runtime. I guess this would be implemented
something like Perl's source filters[1]. Possibly some constants and
such could be defined this way as well, version numbers, etc.

I'm not sure if this is a good idea or not; I haven't completely thought
it through. It seems like I've read about this being done before in some
other langage, but a brief search hasn't turned up anything.

I haven't seen it done in Ruby, but the general idea is called "literate
programming". If you google for that term, you'll find lots of information.

I'm not a big supporter of the idea, though I've never done more than
tinker with it. I'd be curious to see what you come up with if you do
find a way to do it in Ruby, though.

- Jamis
 
T

trans. (T. Onoma)

On Monday 11 October 2004 10:59 pm, Randy W. Sims wrote:
| Are there any Ruby modules that allow documentation to act as source
| code? I was thinking of the problem of how souce code sometimes diverge
| from its documentation. So maybe there could be a way to specify the
| interface: the number of arguments and their types in the documentation,
| and possibly pre- and post-conditions, and then the documentation would
| be turned into code at runtime. I guess this would be implemented
| something like Perl's source filters[1]. Possibly some constants and
| such could be defined this way as well, version numbers, etc.

With duck-typing this is difficult. I wrote a method probe that tries to
figure out these method signatures, but it is incomplete because Ruby is not
100% reflective (at least not from the inside out).

Of course you're talking about putting these in documentation and generating
code. I suggest maybe going the other way around.

T.
 
A

Ara.T.Howard

Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes diverge
from its documentation. So maybe there could be a way to specify the
interface: the number of arguments and their types in the documentation,
and possibly pre- and post-conditions, and then the documentation would
be turned into code at runtime. I guess this would be implemented
something like Perl's source filters[1]. Possibly some constants and
such could be defined this way as well, version numbers, etc.

I'm not sure if this is a good idea or not; I haven't completely thought
it through. It seems like I've read about this being done before in some
other langage, but a brief search hasn't turned up anything.

Any thoughts?

do a search for 'literate programming' - it sounds like what you are talking
about.

kind regards.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| When you do something, you should burn yourself completely, like a good
| bonfire, leaving no trace of yourself. --Shunryu Suzuki
===============================================================================
 
R

Robert Klemme

Randy W. Sims said:
Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes diverge
from its documentation. So maybe there could be a way to specify the
interface: the number of arguments and their types in the documentation,
and possibly pre- and post-conditions, and then the documentation would
be turned into code at runtime. I guess this would be implemented
something like Perl's source filters[1]. Possibly some constants and
such could be defined this way as well, version numbers, etc.

I'm not sure if this is a good idea or not; I haven't completely thought
it through. It seems like I've read about this being done before in some
other langage, but a brief search hasn't turned up anything.

Any thoughts?

Two things come to mind:

1. literate programming (as others have mentioned already): there was a
recent thread here about the topic.

2. design by contract (DbC): there is a (experimental?) implementation of
DbC - I think by Andy Hunt.

Kind regards

robert
 
N

Niklas Frykholm

Jamis said:
I haven't seen it done in Ruby, but the general idea is called "literate
programming". If you google for that term, you'll find lots of information.

If you want to try out literate programming, I recommend the "Leo"
editor. It's an hierarchical text editor with features for literate
programming. Leo is written in our "sister language" Python, but it
isn't really tied in to any particular programming language. You can use
Leo to write Ruby, C, Pascal, PHP, LaTeX, HTML or whatever you want.
The web site is:

http://webpages.charter.net/edreamleo/front.html

I've toyed a bit with literate programming, but I'm not really sold on
the idea. I guess my problem with "documentation as source" (or even
with "source as documentation", but that is a smaller gripe) is the
notion that a program only has one "story". Usually, I find that in my
programs there are many different stories: a story for a beginner user,
a story for an expert user, a story for someone who wants to extend the
module, a story for someone who wants to hack it, a story for someone
who wants to understand and study the technology behind it. And of
course, there can be stories can be in different languages. Trying to
put all these stories as well as the source code in the same document
tends to be confusing, at least for me.

But even if you don't use literate programming, Leo by itself is a great
tool for organizing source code and text. You should check it out.

// Niklas
 
A

Alexander Kellett

Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes diverge
from its documentation. So maybe there could be a way to specify the
interface: the number of arguments and their types in the documentation,
and possibly pre- and post-conditions, and then the documentation would
be turned into code at runtime. I guess this would be implemented
something like Perl's source filters[1]. Possibly some constants and
such could be defined this way as well, version numbers, etc.

one thing i'd like to have in ruvi is good integration
with the version control systems. this includes the ability
to mark sections of documentation (and possibly there
dependancies if they are documented) as persistantly
invalidated when code is changed. i'd like this system
to be used for testcasing also, so a dependancy tree
between the testcases and the code they test is constructed,
therefore testcases that should possibly be added to could
be highlighted. really experimental stuff. it'll be years
before i get anything working nicely i guess. but its one
of the big aims :)

mvg,
Alex
 
R

Randy W. Sims

Jamis said:
Randy said:
Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes
diverge from its documentation. So maybe there could be a way to
specify the interface: the number of arguments and their types in the
documentation, and possibly pre- and post-conditions, and then the
documentation would be turned into code at runtime. I guess this would
be implemented something like Perl's source filters[1]. Possibly some
constants and such could be defined this way as well, version numbers,
etc.

I'm not sure if this is a good idea or not; I haven't completely
thought it through. It seems like I've read about this being done
before in some other langage, but a brief search hasn't turned up
anything.

I haven't seen it done in Ruby, but the general idea is called "literate
programming". If you google for that term, you'll find lots of information.

Doh! That's the term I've been trying to think of. Thanks.
I'm not a big supporter of the idea, though I've never done more than
tinker with it. I'd be curious to see what you come up with if you do
find a way to do it in Ruby, though.

I'm not looking for anything comprehensive. Just something to reduce the
redundencies that often exist at least for the common cases. Just small
stuff like (if you'll forgive a perl example, I'm more familiar with it)
perl modules often declare a version:

our $VERSION = 1.03;

Then somewhere else in the POD documents, you'd have:

=head1 VERSION

blah blah version 1.03

=cut

So anytime you change the version, you have to remember to change it in
multiple places. Ideally, you could just change the docs.

This is mostly just a curiosity at the moment. I just thought I'd ask if
anything like that was available that I could play with.

Randy.
 
B

Brian Schröder

Randy said:
Jamis said:
Randy said:
Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes
diverge from its documentation. So maybe there could be a way to
specify the interface: the number of arguments and their types in the
documentation, and possibly pre- and post-conditions, and then the
documentation would be turned into code at runtime. I guess this
would be implemented something like Perl's source filters[1].
Possibly some constants and such could be defined this way as well,
version numbers, etc.

I'm not sure if this is a good idea or not; I haven't completely
thought it through. It seems like I've read about this being done
before in some other langage, but a brief search hasn't turned up
anything.

I haven't seen it done in Ruby, but the general idea is called
"literate programming". If you google for that term, you'll find lots
of information.


Doh! That's the term I've been trying to think of. Thanks.
I'm not a big supporter of the idea, though I've never done more than
tinker with it. I'd be curious to see what you come up with if you do
find a way to do it in Ruby, though.


I'm not looking for anything comprehensive. Just something to reduce the
redundencies that often exist at least for the common cases. Just small
stuff like (if you'll forgive a perl example, I'm more familiar with it)
perl modules often declare a version:

our $VERSION = 1.03;

Then somewhere else in the POD documents, you'd have:

=head1 VERSION

blah blah version 1.03

=cut

So anytime you change the version, you have to remember to change it in
multiple places. Ideally, you could just change the docs.

This is mostly just a curiosity at the moment. I just thought I'd ask if
anything like that was available that I could play with.

Randy.
Only for this special case, you could use
# blah blah blah
# This is
VERSION = '1.03'
# blah blah blah.

Which is quite readable and valid ruby code.

regards

Brian
 
G

gabriele renzi

Randy W. Sims ha scritto:

This is mostly just a curiosity at the moment. I just thought I'd ask if
anything like that was available that I could play with.

I'd check if RDoc can solve your problems.. then patch it to do it if it
does'nt :)
 
B

Bil Kleb

Randy said:
Are there any Ruby modules that allow documentation to act as source
code?

require 'test/unit'

Then code test-first and you'll have executable documentation.

Code test-first with a partner, and you'll have /sane/ executable
documentation.

When test/unit2 appears, tests will become even more like documentation.

I've played with Literate Programming for over a decade and found
that it nearly always violates the DRY principal. As a result, it
eventually gets out of sync and begins to lie.

Regards,
 
F

Florian Gross

Bil said:
require 'test/unit'

Then code test-first and you'll have executable documentation.

I've coded up test-extract which lets you embed some of your test-cases
cloaked as sample code into your RDoc strings.

It looks like this in practice:
# Creates a Regexp which matches a literal string. In this
# string any special regular expression meta-characters will
# be escaped automatically.
#
# # This creates a Regexp which will match 3 "foo"s.
# re = Regexp::English.literal("foo" * 3)
# re.match("foofoofoo")[0] # => "foofoofoo"
def literal(text); Node::Literal.new(text); end

(Sample from Regexp::English)
# Unfreeze a frozen Object. You will be able to make
# changes to the object again.
#
# obj = "Hello World".freeze
# obj.frozen? # => true
# obj.unfreeze
# obj.frozen? # => false
# obj.sub!("World", "You!")
# obj # => "Hello You!"
def unfreeze
if $SAFE > 0
raise(SecurityError, "Insecure operation `unfreeze' at level #{$SAFE}")
end

return self if direct_value?

self.internal.flags &= ~RubyInternal::FL_FREEZE
return self
end

(Sample from Evil-Ruby)

I've attached it to this email.
Code test-first with a partner, and you'll have /sane/ executable
documentation.

Heh, I have not done this yet, but I've noticed that code design
generally turn out better if you do it via pair programming.
When test/unit2 appears, tests will become even more like documentation.

I'm interested: What will it change?
I've played with Literate Programming for over a decade and found
that it nearly always violates the DRY principal. As a result, it
eventually gets out of sync and begins to lie.

Would you consider the code samples from above Literate Programming?
Regards,
Bil Kleb, Hampton, Virginia

More regards,
Florian Gross


require 'test/unit/testcase'
require 'test/unit/ui/console/testrunner'

# Example isn't another way to teach, it is the only way to teach.
# --Albert Einstein

class Extracter
def self.process(fn)
new(File.read(fn))
end

def initialize(content)
comment_block_re = /((?:^\s*?(?:#.*?)?\n)+)/m
component_re = /\s*(?:class|def|module|alias)\s+:?([^\s()]+)?/
blocks = content.scan(/#{comment_block_re}#{component_re}/)

test_suite = Class.new(Test::Unit::TestCase)

has_test = false
blocks.each do |(comment, component)|
code_in_doc_re = /^(\s*# +(?:.*?)$)/
tests = comment.scan(code_in_doc_re)
body = tests.map do |test|
test.map do |raw_line|
line = raw_line.sub(/^\s*#\s{0,3}/, "")
if md = /(.*?)#\s*(=>|~>|raises?)\s*(.*?)$/.match(line)
new_line, type, result = *md.captures
new_line.strip!
case type
when "=>"
["begin",
" assert_equal(#{result}, #{new_line})",
"rescue => err",
" assert_equal(#{result.inspect}, (#{new_line}).inspect)",
"end"].join("\n")
when "~>", "raise", "raises"
"assert_raises(Object.const_get(#{result.inspect})) { #{new_line} }"
end
else
line
end
end.join("\n")
end.join("\n")

unless component
if $DEBUG
STDERR.puts "Can't get name for this code:",
body.gsub(/(?:\r?\n){2}/, "\n")
end
component = test.hash.abs
end

if body and not body.empty?
has_test = true
test_suite.class_eval %{
def #{test_method_name(component)}
#{body}
end
}
end
end

if not has_test
test_suite.class_eval do
def test_main; end
end
end

Test::Unit::UI::Console::TestRunner.new(test_suite).start
end

def test_method_name(component)
result = "test_#{component}"
{
"+" => "op_plus",
"-" => "op_minus",
"+@" => "op_plus_self",
"-@" => "op_minus_self",
"*" => "op_mul",
"**" => "op_pow",
"/" => "op_div",
"%" => "op_mod",
"<<" => "op_lshift",
">>" => "op_rshift",
"~" => "op_tilde",
"<=>" => "op_cmp",
"<" => "op_lt",
">" => "op_gt",
"==" => "op_equal",
"<=" => "op_lt_eq",
">=" => "op_gt_eq",
"===" => "op_case_eq",
"=~" => "op_apply",
"|" => "op_or",
"&" => "op_and",
"^" => "op_xor",
"[]" => "op_fetch",
"[]=" => "op_store"
}.each do |(what, by)|
result.gsub!(what, by)
end
return result
end
end

if __FILE__ == $0
file = ARGV.shift
load(file)
Extracter.process(file)
end
 
M

Mikael Brockman

Bil Kleb said:
require 'test/unit'

Then code test-first and you'll have executable documentation.

Code test-first with a partner, and you'll have /sane/ executable
documentation.

When test/unit2 appears, tests will become even more like documentation.

What's in the works for test/unit2?
 
M

Markus

I've toyed a bit with literate programming, but I'm not really sold on
the idea. I guess my problem with "documentation as source" (or even
with "source as documentation", but that is a smaller gripe) is the
notion that a program only has one "story". Usually, I find that in my
programs there are many different stories: a story for a beginner user,
a story for an expert user, a story for someone who wants to extend the
module, a story for someone who wants to hack it, a story for someone
who wants to understand and study the technology behind it. And of
course, there can be stories can be in different languages. Trying to
put all these stories as well as the source code in the same document
tends to be confusing, at least for me.

*smile* Wonderfully put.

-- Markus
 
D

Dido Sevilla

Are there any Ruby modules that allow documentation to act as source
code? I was thinking of the problem of how souce code sometimes diverge
from its documentation. So maybe there could be a way to specify the
interface: the number of arguments and their types in the documentation,
and possibly pre- and post-conditions, and then the documentation would
be turned into code at runtime. I guess this would be implemented
something like Perl's source filters[1]. Possibly some constants and
such could be defined this way as well, version numbers, etc.

I'm not sure if this is a good idea or not; I haven't completely thought
it through. It seems like I've read about this being done before in some
other langage, but a brief search hasn't turned up anything.

As other people have mentioned, what you're talking about is
essentially literate programming. It's an idea that originated with
the great Donald Knuth himself, and actually doing it actually
represents a major shift in the philosophy you have while programming.
The primary task of programming changes from explaining to the
computer what you want to do, to explaining to *people* what you want
the *computer* to do. I've been doing this kind of work using Norman
Ramsey's Noweb literate programming tool
(http://www.eecs.harvard.edu/~nr/noweb/) and what I can say after
doing it for a while is it can be quite difficult. It forces you to be
more careful about design, as you're supposed to be able to explain
why you're doing everything, but it is a lot of work.

It does pay off in the end: look at TeX. It's one of the few
nontrivial programs that can actually make the claim of being Bug
Free(tm), without it being an overly egregious lie.
 
N

Nathaniel Talbott

I'm interested: What will it change?

Well, the current plan is to let you to do something like this:

class Adder
include Testing

# Adds two numbers
example { assert_equal(2, Adder.new.add(1, 1)) }
def add(a, b)
a + b
end
end

Examples will then be collected and run as tests when you're in testing
mode, and (eventually) RDoc will understand the example blocks, so we
can get output like this:

add(a, b)

Adds two numbers

Adder.new.add(1, 1) => 2

I haven't yet had a chance to look through your test extractor (though
I was encouraged to pursue this idea by it), but from a cursory survey
it seems to take quite a different approach. Can you compare the
approaches?

HTH,


Nathaniel
Terralien, Inc.

<:((><
 
F

Florian Gross

Nathaniel said:
Well, the current plan is to let you to do something like this:

class Adder
include Testing

# Adds two numbers
example { assert_equal(2, Adder.new.add(1, 1)) }
def add(a, b)
a + b
end
end

Examples will then be collected and run as tests when you're in testing
mode, and (eventually) RDoc will understand the example blocks, so we
can get output like this:

Ah, that looks very nifty. :)
add(a, b)

Adds two numbers

Adder.new.add(1, 1) => 2

I haven't yet had a chance to look through your test extractor (though I
was encouraged to pursue this idea by it), but from a cursory survey it
seems to take quite a different approach. Can you compare the approaches?

Mine takes the RDoc style samples and converts it to a test-case and the
above mentioned takes a short test case and converts it to sample code.

I think we're doing the same, but from opposite ends.
HTH,
Nathaniel
Terralien, Inc.

Regards,
Florian Gross
 
J

James Britt

Markus said:
*smile* Wonderfully put.

Where do all of these different stories go, if not together, such that
when the code changes all of the stories are updated as well?

James
 
M

Markus

Where do all of these different stories go, if not together, such that
when the code changes all of the stories are updated as well?

Most fiction is layered; a novel may contain many short stories,
each of which advances one or more of the plot threads, tells a few
anecdotes, and may or may not be part of a larger series of related
stories which serve to tie the whole together but do not "advance."
There are also subtler dependencies that may arise, foreshadowing,
parallelism, etc.

As a consequence, no one can be expected to "understand" a novel
unless they read it cover to cover.

Software is often as complex, but requiring that people read it
"cover to cover" before they understand it seems unreasonable.
Therefore it makes sense (as Niklas suggested) to tease apart the
various stories and tell them separately. Tools to do this--clean
interface design, use of standards (that can be concisely documented by
reference), change logs/CVS, bug tracking system, design philosophy
documents (which also may be incorporated concisely by reference), all
act in the same was--they take some type of information that could have
been included in the source, merged into a novel of sorts, and pull it
out into a separate document.

This has the downside (as you point out) that when I want to
modify the code I have to also update the change log and perhaps the bug
list, etc. and this is somewhat less convenient when they are in
separate documents, but overall it is far easier (where in the code do
you document a bug when all you know are the symptoms? Do you really
want to embed a draft standard in your code as a comment?...) to keep
things distinct and their relationships more restricted.

-- Markus
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top