Discussion:
Techniques to document code?
(too old to reply)
f***@gmail.com
2020-08-21 16:54:23 UTC
Permalink
It's acknowledge by many that dating from its origins some decades ago:
single author Slackware had a unique/superior documentation method.
That's why several single-author systems have used it as their basis.
It's very frustrating when I can't understand the simplest little script
that I wrote a few days ago.
I suspect/hope there's a few fundamental rules to solve this problem.
And definitely NOT practice-makes-perfect.
IMO there's 2 ways of solving a problem: by association, like a football-player
or my dog, or a M$pook user, and then there's deduction: eg. where the
MINIMALIST underlying principals, like mass, length, time solve Newtonian
physics questions; or bits, bytes, files, directories in the unix family
consistently structure the solutions.
There's some good documentation by the unix originators, who went on to
refine it towards plan9...inferno...but I can't find any methods to capture-the-
underlying-logic of my own scripts, for later understanding/editing.
It reminds me of the undisciplined hacking of BASIC, before the days of
*STRUCTURED* programming. Where can I find documentation on this problem?
Poprocks
2020-08-21 17:47:58 UTC
Permalink
Post by f***@gmail.com
single author Slackware had a unique/superior documentation method.
That's why several single-author systems have used it as their basis.
It's very frustrating when I can't understand the simplest little script
that I wrote a few days ago.
[...]
Post by f***@gmail.com
There's some good documentation by the unix originators, who went on to
refine it towards plan9...inferno...but I can't find any methods to
capture-the- underlying-logic of my own scripts, for later
understanding/editing.
It reminds me of the undisciplined hacking of BASIC, before the days of
*STRUCTURED* programming. Where can I find documentation on this problem?
I have a very simple solution to your problem:

It's called "comments."
Rich
2020-08-21 18:05:19 UTC
Permalink
Post by Poprocks
Post by f***@gmail.com
single author Slackware had a unique/superior documentation method.
That's why several single-author systems have used it as their basis.
It's very frustrating when I can't understand the simplest little script
that I wrote a few days ago.
[...]
Post by f***@gmail.com
There's some good documentation by the unix originators, who went on to
refine it towards plan9...inferno...but I can't find any methods to
capture-the- underlying-logic of my own scripts, for later
understanding/editing.
It reminds me of the undisciplined hacking of BASIC, before the days of
*STRUCTURED* programming. Where can I find documentation on this problem?
It's called "comments."
Indeed. And, the OP should also consider that when writing the
comments, he should document the "why" something is being done, not
"what" is being done.

The "what" is almost always self explanatory from the code.

The "why" the code is doing what the code is doing is often not
immediately obvious from the "what" the code is doing, and so comments
documenting the "why" something was done are often much superior to
those that just say what is occurring.
Auric__
2020-08-22 01:44:16 UTC
Permalink
Post by Rich
Post by Poprocks
Post by f***@gmail.com
single author Slackware had a unique/superior documentation method.
That's why several single-author systems have used it as their basis.
It's very frustrating when I can't understand the simplest little
script that I wrote a few days ago.
[...]
Post by f***@gmail.com
There's some good documentation by the unix originators, who went on to
refine it towards plan9...inferno...but I can't find any methods to
capture-the-underlying-logic of my own scripts, for later
understanding/editing.
It reminds me of the undisciplined hacking of BASIC, before the days
of *STRUCTURED* programming. Where can I find documentation on this
problem?
It's called "comments."
Indeed. And, the OP should also consider that when writing the
comments, he should document the "why" something is being done, not
"what" is being done.
The "what" is almost always self explanatory from the code.
The "why" the code is doing what the code is doing is often not
immediately obvious from the "what" the code is doing, and so comments
documenting the "why" something was done are often much superior to
those that just say what is occurring.
That's not to say the "what" isn't important. A *short* summary of what's
happening means that you won't *need* to read through the code.
--
The GOD DAMN LINUX BOX distro is just going to contain one app: fdisk.
Lew Pitcher
2020-08-21 18:16:01 UTC
Permalink
Post by Poprocks
Post by f***@gmail.com
single author Slackware had a unique/superior documentation method.
That's why several single-author systems have used it as their basis.
It's very frustrating when I can't understand the simplest little script
that I wrote a few days ago.
[...]
Post by f***@gmail.com
There's some good documentation by the unix originators, who went on to
refine it towards plan9...inferno...but I can't find any methods to
capture-the- underlying-logic of my own scripts, for later
understanding/editing.
It reminds me of the undisciplined hacking of BASIC, before the days of
*STRUCTURED* programming. Where can I find documentation on this problem?
It's called "comments."
Well, it's usually /more/ than that. You need to document the code from the
inside and the outside. The "from the inside" should explain the "whats
going on" and "what we expect at this point", and the "why we did it this
way" and "why we expect what we do" of the code. The "from the outside"
should explain what the code does, at a macro level, how to use the code,
what caveats apply, and what (if any) are the known gotcha's and bugs.

We document the code from the inside with comments. Comments need to be
meaningful. Consider a basic binary search:

for (midpt = (lowpt+highpt)/2;
array[midpt] != key && highpt > lowpt;
midpt = (lowpt+highpt)/2)
{
if (key > array[midpt])
lowpt = midpt + 1;
else
highpt = midpt - 1;
}

You could comment it like this:
for (midpt = (lowpt+highpt)/2; /* start here */
array[midpt] != key && highpt > lowpt; /* stop here */
midpt = (lowpt+highpt)/2) /* test here */
{
if (key > array[midpt])
lowpt = midpt + 1; /* add one */
else
highpt = midpt - 1; /* subtract one */
}

or, you could comment it like this:
/* LOOP through search UNTIL match found OR no elements left to search */
for (midpt = (lowpt+highpt)/2; /* start in the middle */
array[midpt] != key && highpt > lowpt; /* not found & in bounds */
midpt = (lowpt+highpt)/2) /* compute new midpoint */
{ /* ============================ **
** array[midpt] was NOT a match **
** ============================ */
if (key > array[midpt])
lowpt = midpt + 1; /* narrow search to between here and high */
else
highpt = midpt - 1; /* narrow search to beween low and here */
}
/* loop terminates when entry found OR no more array to search */

The first is how much code is "commented". The second tries to explain the
what and why, not the literal /how/.

We document the code from the outside with man pages. Until Unix, most API
and application manuals were either too terse or too verbose. The Unix
manpage format lends itself to documenting the essentials of the code, from
the outside, giving everthing from use to usage to bugs to references and
associated tools. You know that the manpage is well-written when you can use
it exclusively, instead of having to deep-dive into the code.

HTH
--
Lew Pitcher
"In Skills, We Trust"
Lew Pitcher
2020-08-21 18:27:58 UTC
Permalink
On August 21, 2020 14:16, Lew Pitcher wrote:
[snip]
Post by Lew Pitcher
We document the code from the outside with man pages. Until Unix, most API
and application manuals were either too terse or too verbose.
I worked most of my career with IBM mainframes, and had to "suffer" with
IBM's manuals. The /only/ IBM manual that matched the Unix manuals for
clarity was the "IBM System/370 Principles of Operations".

[snip]
--
Lew Pitcher
"In Skills, We Trust"
Aragorn
2020-08-23 09:19:40 UTC
Permalink
Post by Lew Pitcher
[snip]
Post by Lew Pitcher
We document the code from the outside with man pages. Until Unix,
most API and application manuals were either too terse or too
verbose.
I worked most of my career with IBM mainframes, and had to "suffer"
with IBM's manuals. The /only/ IBM manual that matched the Unix
manuals for clarity was the "IBM System/370 Principles of Operations".
[snip]
"This page intentionally left blank."


:p
--
With respect,
= Aragorn =
Poprocks
2020-08-23 20:40:17 UTC
Permalink
Post by Lew Pitcher
[snip]
Post by Lew Pitcher
We document the code from the outside with man pages. Until Unix, most API
and application manuals were either too terse or too verbose.
I worked most of my career with IBM mainframes, and had to "suffer" with
IBM's manuals. The /only/ IBM manual that matched the Unix manuals for
clarity was the "IBM System/370 Principles of Operations".
Professor Kevin O'Kane has a really interesting video on what I *though*
was the System/370 after reading your post, but was actually on the
System/360.

Either way, it's an interesting watch:


Henrik Carlqvist
2020-08-24 18:00:02 UTC
Permalink
Post by Lew Pitcher
/* LOOP through search UNTIL match found OR no elements left to search */
for (midpt = (lowpt+highpt)/2; /* start in the
middle */
Post by Lew Pitcher
array[midpt] != key && highpt > lowpt; /* not found & in bounds */
midpt = (lowpt+highpt)/2) /* compute new
midpoint */
Post by Lew Pitcher
{ /* ============================ **
** array[midpt] was NOT a match **
** ============================ */
if (key > array[midpt])
lowpt = midpt + 1; /* narrow search to between here and high */
else
highpt = midpt - 1; /* narrow search to beween low and here */
}
/* loop terminates when entry found OR no more array to search */
I agree that your second example of comments are easier to read. On the
other hand, in my experience, it is not uncommon to stumble upon code
which has evolved to a state where its comments are old and misleading.

With that experience I prefer to keep few comments and make functions and
variable names self-explanatory. To continue with a third version of your
example:

/* LOOP through search UNTIL match found OR no elements left to search */
for (middle_point = (low_point+high_point)/2;
array[middle_point] != key && high_point > low_point;
middle_point = (low_point+high_point)/2)
{
/* array[middle_point] was NOT a match */

if (key > array[middle_point])
{
/* narrow continued search to between here and high */
lowpoint = middlepoint + 1;
}
else
{
/* narrow continued search to beween low and here */
high_point = middle_point - 1;
}
}

In the example above some of your comments has been replaced with more
explaining variable names. I also removed the last comment which where
redunant to the first comment. The reason that I did choose to keep the
first comment was that it was close to the code that it described, if you
would change that code it would be easier to see that also the comment
should be changed.

regards Henrik
Lew Pitcher
2020-08-24 18:22:22 UTC
Permalink
Hi, Henrik
Post by Lew Pitcher
Post by Lew Pitcher
/* LOOP through search UNTIL match found OR no elements left to search */
for (midpt = (lowpt+highpt)/2; /* start in the
middle */
Post by Lew Pitcher
array[midpt] != key && highpt > lowpt; /* not found & in
bounds
Post by Lew Pitcher
Post by Lew Pitcher
*/
midpt = (lowpt+highpt)/2) /* compute new
midpoint */
Post by Lew Pitcher
{ /* ============================ **
** array[midpt] was NOT a match **
** ============================ */
if (key > array[midpt])
lowpt = midpt + 1; /* narrow search to between here and high
*/
Post by Lew Pitcher
else
highpt = midpt - 1; /* narrow search to beween low and here */
}
/* loop terminates when entry found OR no more array to search */
I agree that your second example of comments are easier to read. On the
other hand, in my experience, it is not uncommon to stumble upon code
which has evolved to a state where its comments are old and misleading.
With that experience I prefer to keep few comments and make functions and
variable names self-explanatory. To continue with a third version of your
/* LOOP through search UNTIL match found OR no elements left to search */
for (middle_point = (lo>
regards Henrikw_point+high_point)/2;
array[middle_point] != key && high_point > low_point;
middle_point = (low_point+high_point)/2)
{
/* array[middle_point] was NOT a match */
if (key > array[middle_point])
{
/* narrow continued search to between here and high */
lowpoint = middlepoint + 1;
}
else
{
/* narrow continued search to beween low and here */
high_point = middle_point - 1;
}
}
In the example above some of your comments has been replaced with more
explaining variable names. I also removed the last comment which where
redunant to the first comment. The reason that I did choose to keep the
first comment was that it was close to the code that it described, if you
would change that code it would be easier to see that also the comment
should be changed.
Yes. I agree with your changes.

Your version makes my point better than mine did, I think.
--
Lew Pitcher
"In Skills, We Trust"
Mike Small
2020-10-04 12:58:15 UTC
Permalink
Post by f***@gmail.com
I suspect/hope there's a few fundamental rules to solve this problem.
And definitely NOT practice-makes-perfect.
IMO there's 2 ways of solving a problem: by association, like a football-player
or my dog, or a M$pook user, and then there's deduction: eg. where the
MINIMALIST underlying principals, like mass, length, time solve Newtonian
physics questions; or bits, bytes, files, directories in the unix family
consistently structure the solutions.
There's some good documentation by the unix originators, who went on to
refine it towards plan9...inferno...but I can't find any methods to capture-the-
underlying-logic of my own scripts, for later understanding/editing.
It reminds me of the undisciplined hacking of BASIC, before the days of
*STRUCTURED* programming. Where can I find documentation on this problem?
Maybe you are someone who might become an enthusiast of literate
programming:

https://en.wikipedia.org/wiki/Literate_programming

That doesn't list shell script as a language with an existing
implementation, but, assuming there's really nothing out there for
it, and supposing you become very dedicated to the approach and
are inclined to depart from norms in a similar way to how GNU
developers of the past have to solve other problems, m4 might be
a means to get there. But that's not at all in the style of Slackware,
it adding an extra layer and a lot of up front work.
Joe Rosevear
2020-10-17 04:49:16 UTC
Permalink
Post by f***@gmail.com
single author Slackware had a unique/superior documentation method.
[snip]
...but I can't find any methods to capture-the-underlying-logic of my own
scripts, for later understanding/editing. It reminds me of the
undisciplined hacking of BASIC, before the days of *STRUCTURED*
programming. Where can I find documentation on this problem?
Well, I'm not a professional programmer, but I have programmed for many
years as a hobby and also as part of my profession. So I have a point
of view.

To write well documented, easy to use code you need to do these things:

1. You need to write good code. Bad code generally defies
understanding. Documentation doesn't help much.

2. This is my pet peeve: Use a coding style that includes logical
indentation and blank lines (white space). Code makes more sense when
it is easy to read, and logical, consistent use of indentation and
white space helps this immensely.

3. When you can (and that is perhaps *always*) word your code so the
logic of your if-blocks is clear. This is another peeve, especially in
Bash. There are lots of ways to write an if-block in Bash. Maybe I'm
just dumb, but I think you owe it to yourself and your users to write
them like this:

if [ "$blah" = "blah" ]; then

run something
fi

Or for compound statements

if [ \( "$blah" = "blah" \) -o \( "$fred" = "farley" \) ]; then

run something
fi

4. In bash use "\" to continue lines as needed. for example, the
above, might be better written:

if [ \( "$blah" = "blah" \) -o \
\( "$fred" = "farley" \) ]; then

run something
fi

5. Also for Bash learn how to use the "cat << DONE" method of
providing output, and use it to avoid indenting when there isn't room.
This a compromise, but that's how I do it. It works for me. For
example:

if [ \( "$blah" = "blah" \) -o \
\( "$fred" = "farley" \) ]; then

cat << DONE

Here is some output. It is very helpful to do it this way, because
your editor will make new lines for you where needed, and you don't run
of of room on the line because of the space needed for "echo..." or
"printf...".

DONE
fi

6. Don't just program, but be a student of programming. Study it.
Collect and read books about it. And especially, keep extensive notes
(or "lessons") organized by subject and/or by command which tell what
you have learned by testing and/or Internet searching.

Don't just learn something, document it in a way which allows you to
find it again by use of grep. Or better make a tool which invokes grep
for you. For example, I have a tool that lets me recursively search
for a string like this:

forall . grep Bob

Then use your tool when searching through your lessons for tips about
how to do something. The above would search for all occurences of
"Bob" in the current dir and all sub-dirs. Go to your lessons dir
first, then give the search command. My lessons dir has sub-dirs by
command and sometimes by subject, and occaisionally those sub-dirs are
further divided.

7. Put examples of code you have written in your lessons dir, but also
organize your collection of code, so that it can itself be a source of
documentation. Bash is great for this. Bash scripts and function
definitions, especially when clearly written and documented, both serve
a purpose and serve to document how to do something.

8. Write code which helps you write, document and organize your code.
You will write better code and document it better if it is easy to do
so. I use a system that I developed myself called SAM (available at
http://sourceforge.net/projects/sam-kernel). It is all Bash plus three
short C executables. It works by manipulating the environment. The
result is a command line prompt which reflects both the dir you are in
and the state of your PATH variable. It doesn't show all of PATH, just
what you have added to it. It uses the concept of menus where a menu
corresponds to a dir which is currently included in PATH. For example,
this bit of code adds a dir to the path, executes the printreport
command which is in that *menu*, then returns to the previous menu:

bound /mnt/joresorc/tools
printreport
bye

In the usual Bash fashion, you can enter the above lines at the command
line or you can type then into a script or function defintion and run
the script or function.

At any point in the use of SAM this command will display a menu
description telling you the available commands and the syntax for how
to use them, as well as any other notes you have added:

menu

SAM simply builds the output from the contents of a file called
$level/menu.dat where $level is the path to the dir which is the
current menu. For example

bound /mnt/joresorc/tools
menu

will change to the menu at /mnt/joresorc/tools (updating the prompt,
path and functions accordingly), then display output built from
/mnt/joresorc/tools/menu.dat

And to allow you to write SAM tools which operate on the current
environment without having to source them, SAM also adds and removes
functions (to and from the environment--I hinted at this in the
previous paragraph) as needed when changing menus. To add functions to
a menu, put defintions for the functions in the menu dir each having
this first line:

#OK SAM

This has been a cursory overview of what SAM does. SAM is essentially
just Bash, so of course it is sometimes a nuissance, but it has served
me well. Most certainly, writing and using SAM has shaped the way that
I write and use code--hopefully for the better. You are welcome to
download SAM from Sourceforge and use it and modify it per the license
agreement.

Or write your own code which helps you write, document and organize
your code.

-Joe

Loading...