Discussion:
[9fans] Plan 9/plan9port coding conventions
(too old to reply)
s***@icebubble.org
2012-01-11 18:41:19 UTC
Permalink
Hello,

As readers may remember from a previous thread, I have historically
been, well, less than enamored with some aspects of the coding style
used in Plan 9/plan9port. Now that I'm getting into development, I'd
like to know what coding conventions the Plan 9 community endorses. I
have read the Plan 9 compiler paper, and understand the conventions
described in it. While conventions such as composing variable names
using lower case letters and no underscores do irk me a bit, I can live
with them---because those are the conventions that the community has
adopted. However, there are a number of stylistic features in Plan
9/p9p code which I've noticed (which AREN'T discussed in the compiler
paper) and I'm wondering whether they're intentional conventions or not.

(1) For example, P9 code tends to use variable names like "i" and "j",
where I would typically use self-documenting variable names like "row"
and "col". Variable names like "row" and "col" are much easier to
search for (i.e., with a right-click), too. Names like "i" and "j"
(which occur in many identifiers) will generate many false positives.

(2) In functions, variables are often declared together in one
paragraph, and then, later, initialized in another paragraph, as in:

int i;
char *s;

/* stuff */

i = 0;
s = nil;

rather than something like:

int i = 0;
char *s = nil;

(3) Lots of global variables are used, without any distinguishing
syntax, i.e. "char *f". I prefer to designate global variables with
something like a leading underscore, i.e. "char *_filename".

(4) In ARGBEGIN/ARGEND blocks, boolean switches are often set using the
"++" operator rather than "|= 1", i.e.:

case 'v':
verbose++;
case 'x':
x++;

as opposed to:

case 'v':
verbose++;
case 'x':
x |= 1;

(5) P9 code tends to repeat constructs such as "argv[i]" over and over
throughout the code, like:

for(i = 0; i < argc; i++){
somestuff(argv[i]);
otherstuff(argv[i]);
}

whereas I would typically use something like:

int argnum;
char *argstr;

for(argnum = 0; argnum < argc; argnum++){
argstr = argv[argnum];
somestuff(argstr);
otherstuff(argstr);
}


Are these practices official/unofficial Plan 9 coding conventions? Are
they used for performance purposes? Are they just poor style? Or has
this kind of style been used for so long that it's BECOME Plan 9's style
of choice? Also, is it considered polite or acceptable coding practice
to alter the style of code written by other contributors? I don't want
to step on anybody's toes by "fixing" style which other Plan 9
developers consider to be "Plan 9" style coding conventions.

Thanks!
--
+---------------------------------------------------------------+
|Smiley <***@icebubble.org> PGP key ID: BC549F8B |
|Fingerprint: 9329 DB4A 30F5 6EDA D2BA 3489 DAB7 555A BC54 9F8B|
+---------------------------------------------------------------+
Richard Miller
2012-01-11 18:53:58 UTC
Permalink
style(6) deals with some of your questions.
Yaroslav
2012-01-12 20:20:04 UTC
Permalink
Post by Richard Miller
style(6) deals with some of your questions.
Since nobody mentioned it yet,

Besides style(6) you may want to read "Notes on Programming in C", Rob
Pike, 1989.
Jeremy Jackins
2012-01-11 19:01:33 UTC
Permalink
Are these practices official/unofficial Plan 9 coding conventions?  Are
they used for performance purposes?  Are they just poor style?  Or has
this kind of style been used for so long that it's BECOME Plan 9's style
of choice?  Also, is it considered polite or acceptable coding practice
to alter the style of code written by other contributors?  I don't want
to step on anybody's toes by "fixing" style which other Plan 9
developers consider to be "Plan 9" style coding conventions.
I'm not an active community member, but it seems you are confusing
style different from your own with poor style.
Russ Cox
2012-01-11 20:37:17 UTC
Permalink
In any project, the polite thing to do is to make your code
look like the surrounding code. You have identified many
ways in which your code does not look like the surrounding
code. That's always the first step.

Russ
erik quanstrom
2012-01-11 20:45:28 UTC
Permalink
Post by s***@icebubble.org
(2) In functions, variables are often declared together in one
int i;
char *s;
/* stuff */
i = 0;
s = nil;
int i = 0;
char *s = nil;
this (the former method) is good practice since mingling declaration and
initialization can lead to big copypasta errors if^w when the
code is reorganized.
Post by s***@icebubble.org
(3) Lots of global variables are used, without any distinguishing
syntax, i.e. "char *f". I prefer to designate global variables with
something like a leading underscore, i.e. "char *_filename".
i think the plan 9 convention is to keep few enough globals
so than one can be expected to remember them.
Post by s***@icebubble.org
(4) In ARGBEGIN/ARGEND blocks, boolean switches are often set using the
this is trivia. (and i'd argue that generally both are wrong;
it's not a bit array, and the count is not important.)
Post by s***@icebubble.org
(5) P9 code tends to repeat constructs such as "argv[i]" over and over
for(i = 0; i < argc; i++){
somestuff(argv[i]);
otherstuff(argv[i]);
}
int argnum;
char *argstr;
this is a variant of hungarian notation. what value
does it add? the declarations are clear enough. everyone
knows what argv/argc are.

i've fallen into most of these traps myself. i used to declare
main as main(int c, char **v). what i found was fitting in
and understanding the whys of the local conventions is much
more important than whatever quirks you have yourself.

- erik
John Floren
2012-01-11 21:20:04 UTC
Permalink
Post by s***@icebubble.org
(1) For example, P9 code tends to use variable names like "i" and "j",
where I would typically use self-documenting variable names like "row"
and "col". Variable names like "row" and "col" are much easier to
search for (i.e., with a right-click), too. Names like "i" and "j"
(which occur in many identifiers) will generate many false positives.
If everyone in the world uses i and j as row/column indexes into
arrays, aren't they self-documenting?

One reason is that in FORTRAN, identifiers that began with I
through... N? were automatically integers. Thus, I and J were easy.
There may be a good reason for that, I've heard that it came from
quaternions but that may be false.


John
Russ Cox
2012-01-11 21:25:10 UTC
Permalink
Style is style; it is not defensible on its own.
If I were contributing to smiley's projects, I would
make the code look the way the rest of his code
does. It's not that one way is necessarily better,
but one way is definitely least distracting in a given
context.

Russ
Iruatã Souza
2012-01-11 23:00:51 UTC
Permalink
Post by John Floren
Post by s***@icebubble.org
(1) For example, P9 code tends to use variable names like "i" and "j",
where I would typically use self-documenting variable names like "row"
and "col".  Variable names like "row" and "col" are much easier to
search for (i.e., with a right-click), too.  Names like "i" and "j"
(which occur in many identifiers) will generate many false positives.
If everyone in the world uses i and j as row/column indexes into
arrays, aren't they self-documenting?
One reason is that in FORTRAN, identifiers that began with I
through...  N? were automatically integers.  Thus, I and J were easy.
There may be a good reason for that, I've heard that it came from
quaternions but that may be false.
When you do software for physics it seems generally better if the code
has similar/analogous notation to the derivations you're dealing with.
In that case one letter variables often render a direct understanding
while more descriptive names do not.

iru
John Stalker
2012-01-11 23:57:29 UTC
Permalink
One thing to remember about descriptive identifiers is that the
compiler doesn't check whether the descriptions are accurate or
not. Often they were when the code was first written, but become
less so over time. Sometimes they were never accurate. One nice
thing about i, j, etc. is that you aren't tempted to make assumptions
about them that aren't backed up by the code. But I'm a mathematician,
so I tend to have peculiar ideas about such things.
--
John Stalker
School of Mathematics
Trinity College Dublin
tel +353 1 896 1983
fax +353 1 896 2282
Skip Tavakkolian
2012-01-12 01:33:41 UTC
Permalink
by way of an example:

int pszBesmirchHungeriansNotation;

-Skip
Post by John Stalker
One thing to remember about descriptive identifiers is that the
compiler doesn't check whether the descriptions are accurate or
not.  Often they were when the code was first written, but become
less so over time.  Sometimes they were never accurate.  One nice
thing about i, j, etc. is that you aren't tempted to make assumptions
about them that aren't backed up by the code.  But I'm a mathematician,
so I tend to have peculiar ideas about such things.
--
John Stalker
School of Mathematics
Trinity College Dublin
tel +353 1 896 1983
fax +353 1 896 2282
erik quanstrom
2012-01-12 02:53:54 UTC
Permalink
Post by Skip Tavakkolian
int pszBesmirchHungeriansNotation;
who let the camel's nose in the tent?

- erik
Christian Neukirchen
2012-01-12 17:56:20 UTC
Permalink
Post by erik quanstrom
Post by Skip Tavakkolian
int pszBesmirchHungeriansNotation;
who let the camel's nose in the tent?
The Go people.
--
Christian Neukirchen <***@gmail.com> http://chneukirchen.org
Skip Tavakkolian
2012-01-12 23:07:01 UTC
Permalink
i was providing the example to what John was pointing out about the
futility of including type information in identifiers when there isn't
an enforcement mechanism. in this case, presumably the variable named
pszBesmirchesAllHungariansEverywhereNotation is a 'pointer to zero
terminated string ...', which it clearly isn't.

I don't mind the mixed case names and the names in the main Go
packages seem very reasonable and easy to remember.

-Skip

On Thu, Jan 12, 2012 at 9:56 AM, Christian Neukirchen
Post by Christian Neukirchen
Post by erik quanstrom
Post by Skip Tavakkolian
int pszBesmirchHungeriansNotation;
who let the camel's nose in the tent?
The Go people.
--
Comeau At9Fans
2012-01-12 15:18:38 UTC
Permalink
Post by s***@icebubble.org
As readers may remember from a previous thread, I have historically
been, well, less than enamored with some aspects of the coding style
used in Plan 9/plan9port. Now that I'm getting into development, I'd
like to know what coding conventions the Plan 9 community endorses. I
have read the Plan 9 compiler paper, and understand the conventions
described in it. While conventions such as composing variable names
using lower case letters and no underscores do irk me a bit, I can live
with them---because those are the conventions that the community has
adopted. However, there are a number of stylistic features in Plan
9/p9p code which I've noticed (which AREN'T discussed in the compiler
paper) and I'm wondering whether they're intentional conventions or not.
(1) For example, P9 code tends to use variable names like "i" and "j",
where I would typically use self-documenting variable names like "row"
and "col". Variable names like "row" and "col" are much easier to
search for (i.e., with a right-click), too. Names like "i" and "j"
(which occur in many identifiers) will generate many false positives.
Most stylistic things have both pros and cons. So for instance, you are
correct that i and j *are* hard to grep for. And you are also correct that
one should normally strive for so-called self-documenting names. However,
with that in mind, row and col specifically have their own limitations (for
instance, they don't have much more meaning than i and j and in some ways
can be considered worse). So, as in many disciplines, we're left with a
bunch of engineering compromises to wiggle through. Some of the
compromises will be obvious flaws and mistakes, and then so must be dealt
with accordingly (resistance or learned helplessness :).
Post by s***@icebubble.org
(2) In functions, variables are often declared together in one
int i;
char *s;
/* stuff */
i = 0;
s = nil;
int i = 0;
char *s = nil;
Neither of these is necessarily superior to the other, or other forms.
Post by s***@icebubble.org
(3) Lots of global variables are used, without any distinguishing
syntax, i.e. "char *f". I prefer to designate global variables with
something like a leading underscore, i.e. "char *_filename".
I usually consider this to be putting a set of bad choices into a pot, and
picking from them at will. It also tends to yield exactly the competing
styles you're bumping into.

(4) In ARGBEGIN/ARGEND blocks, boolean switches are often set using the
Post by s***@icebubble.org
verbose++;
x++;
verbose++;
x |= 1;
Again, we have language limitations yielding multiple acceptable'ish
compromises of 6 of one and 1/2 dozen of another.
Post by s***@icebubble.org
(5) P9 code tends to repeat constructs such as "argv[i]" over and over
for(i = 0; i < argc; i++){
somestuff(argv[i]);
otherstuff(argv[i]);
}
int argnum;
char *argstr;
for(argnum = 0; argnum < argc; argnum++){
argstr = argv[argnum];
somestuff(argstr);
otherstuff(argstr);
}
This one's a mixed bag again. Used to be you may have had to do something
like this in the name of efficiency (of the executable code). There can be
times to prefer the latter, but that said, argstr has it's own issues, so
does creating another variable when just saying what something is in the
first place can be its best name, but repeating complicated dimensions,
struct membership selections, etc. can get messy too. So....
Post by s***@icebubble.org
Are these practices official/unofficial Plan 9 coding conventions? Are
they used for performance purposes? Are they just poor style? Or has
this kind of style been used for so long that it's BECOME Plan 9's style
of choice? Also, is it considered polite or acceptable coding practice
to alter the style of code written by other contributors? I don't want
to step on anybody's toes by "fixing" style which other Plan 9
developers consider to be "Plan 9" style coding conventions.
Be careful when delving into "poor". Some loose thoughts: Beauty is in
the eye of the beholder. There often is not a best, just engineering
compromises. This does not mean one will not run across something horrid.
Continue to question all. Many things are often at odds.
--
Greg Comeau / 4.3.10.1 with C++0xisms now in beta!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Andrés Domínguez
2012-01-13 14:55:03 UTC
Permalink
Post by s***@icebubble.org
(1) For example, P9 code tends to use variable names like "i" and "j",
where I would typically use self-documenting variable names like "row"
and "col".  Variable names like "row" and "col" are much easier to
search for (i.e., with a right-click), too.  Names like "i" and "j"
(which occur in many identifiers) will generate many false positives.
I haven't written code for plan9, so this is my own taste about plan9
coding style.

for ( i=0; i < nrows; i++);

or

for (i=firstrow; i <= lastrow; i++);

"i" is only an iterator variable, as used in the sigma notation for summation.
What has meaning to me is the condition or initialization variable (nrows,
firstrow, lastrow...)
Post by s***@icebubble.org
(2) In functions, variables are often declared together in one
 int i;
 char *s;
 /* stuff */
 i = 0;
 s = nil;
This style looks standard.


Andrés
faif
2012-01-16 10:02:07 UTC
Permalink
I haven't developed anything for Plan 9 yet but these are my thoughts.

IMHO there's nothing wrong with using i and j as names for local variables with a short life. If a function is as short as it normally should be, you will generally search for functions instead of variable names. And functions should be named properly anyway.

I agree with the argument that the code you are writing should conform to the conventions used by the existing code. Name refactoring doesn't sound like a good idea unless you are planning to refactor the complete codebase.

Also, notations like Hungarian are usually problematic (http://programmers.stackexchange.com/questions/102689/what-is-the-benefit-of-not-using-hungarian-notation) instead of beneficial.
John Stalker
2012-01-16 11:04:12 UTC
Permalink
Also, notations like Hungarian are usually problematic (http://programmers.=
stackexchange.com/questions/102689/what-is-the-benefit-of-not-using-hungari=
an-notation) instead of beneficial.
I don't ever use Hungarian notation myself, but in its defense I would
say that there is some merit to the original idea, it's just been
almost universally misunderstood. There's a coherent, if rather
longwinded, explanation in the first link in that stackexchange
page you cited.
--
John Stalker
School of Mathematics
Trinity College Dublin
tel +353 1 896 1983
fax +353 1 896 2282
s***@icebubble.org
2012-01-16 22:50:22 UTC
Permalink
Post by s***@icebubble.org
used in Plan 9/plan9port. Now that I'm getting into development, I'd
Well, I've been hacking on P9P for a bit, rolled up a patch, and noticed
that the patch contains edits to the shebang (#!) lines for the shell
scripts in the development tree. I presume they're the changes made by
the moveplan9.sh script. What's the conventional way to omit these
shebang edits when committing code?

I could moveplan9.sh the #! paths back to /usr/local/plan9. But then
the development environment would be broken. I could run moveplan9.sh
before and after each commit; but that would be annoying and get old
real fast. Moving the tree to the real /usr/local/plan9 would risk
breaking the existing installed (and working) P9P while development is
underway. I was thinking I could up wrap the #! edits into a patch, and
apply that patch before and after every commit, but that would be about
equally as tedious as having to run moveplan9.sh over and over again.

Any ideas? What's the customary way to do this?
--
+---------------------------------------------------------------+
|Smiley <***@icebubble.org> PGP key ID: BC549F8B |
|Fingerprint: 9329 DB4A 30F5 6EDA D2BA 3489 DAB7 555A BC54 9F8B|
+---------------------------------------------------------------+
andrey mirtchovski
2012-01-16 22:57:58 UTC
Permalink
Any ideas?  What's the customary way to do this?
move your changes to a fresh clone of the repository and submit from
there without running ./INSTALL.

Continue reading on narkive:
Loading...