[comp.lang.c] Coding Standards. was: a style question

rmartin@clear.com (Bob Martin) (11/11/90)

In article <14369@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>
>Often, because it was written by amateurs, or at any rate hackers who
>have not learned the magnitude of the maintenance problem for 
>production software.

The lack of standard coding practice IS a big problem for software
maintenance.  At Clear we have instituded a style standard which
all our engineers follow.  This standard specifies how indenting
should be done, how variables, functions and types should be named.
I specifies that functions should have single entrance and single
exit points, and that functions should not be much longer then
one page.  It specifies a documentation style and demands that
comments always be placed on closing braces.  etc. etc.

One might think that engineers would resist this kind of "infringement
on their creativity"  But in fact we have found that most engineers
want to have standards like this since they can then read each others
code easily and channel their creativity towards the problem instead
of towards the style.

-- 
+-Robert C. Martin-----+---------------------------------------------+
| rmartin@clear.com    | My opinions are mine.  They aren't anybody  |
| uunet!clrcom!rmartin | elses.  And thats the way I want to keep it.|
+----------------------+---------------------------------------------+

imp@marvin.Solbourne.COM (Warner Losh) (11/17/90)

In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes:
: The lack of standard coding practice IS a big problem for software
: maintenance.

Agreed.  However, a bad coding standard can make life miserable for
everybody.

: It specifies that functions should have single entrance and single
: exit points

This is a bogus restriction, at least in terms of a single exit point.
When you have small functions, the return statement can be used to
give meaningful flow control to the functions w/o the need for a
"goto".  I have found that when I adhere to this rule, I either get
code that looks like:

	if (allocate-memory) {
		do some stuff
		if (get-more-memory) {
			do more stuff
			if (open-file) {
				do even more stuff
				if (alloc more memory) {
					...
					status = OK;
				}
				else
					status = NO_MEM
			}
			else
				status = NO_FILE
		}
		else
			status = NO_MEM
	}
	else
		status = NO_MEM

	return status;

Or I get code that looks like:

	if (!allocate-memory) {
		status = NO_MEM;
		goto done;
	}
	do some stuff
	if (!get-more-memory) {
		status = NO_MEM;
		goto done;
	}
	do more stuff
	if (!openfile)	{
		status = NO_FILE;
		goto done;
	}

	do even more stuff

	if (!alloc memory) {
		status = NO_MEM;
		goto done;
	}

	last stuff
	
	status = OK;
done:
	return status;

When what I really want is:

	if (!allocate-memory)
		return NO_MEM

	do some stuff

	if (!get-more-memory)
		return NO_MEM

	do more stuff

	if (!openfile)
		return NO_FILE

	do even more stuff

	if (!alloc memory)
		return NO_MEM

	last stuff
	
	return OK;

A quick check reveals that the above code segments are all the same.
However, I may have missed something.  The final one is the clearest
one, IHO, of them all.  Comments....

--
Warner Losh		imp@Solbourne.COM
How does someone declare moral bankruptcy?

6600dt@ucsbuxa.ucsb.edu (David Goggin) (11/17/90)

In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes:

>At Clear we have instituded a style standard which
>all our engineers follow.  This standard specifies how indenting
>should be done, how variables, functions and types should be named.
>I specifies that functions should have single entrance and single
>exit points, and that functions should not be much longer then
>one page.  It specifies a documentation style and demands that
>comments always be placed on closing braces.  etc. etc.

I don't think I'd
like to have a format forced on me like that.  I
think, however, I _well-designed_ standard does go a
long way in clearing up the problem.  I would
reccommend a standard that is thought out carefully
in advance, to be most logical in showing the
structure of code, as well as aestheticaly pleasing
(a big factor for me.)

*dt*
6600dt@ucsbuxa.bitnet

stanley@phoenix.com (John Stanley) (11/17/90)

imp@marvin.Solbourne.COM (Warner Losh) writes:

>This is a bogus restriction, at least in terms of a single exit point.
>When you have small functions, the return statement can be used to
>give meaningful flow control to the functions w/o the need for a
>"goto".  

  >>lots of code deleted<<

>A quick check reveals that the above code segments are all the same.
>However, I may have missed something.  The final one is the clearest
>one, IHO, of them all.  Comments....

   Ooh, an invitation for comments!

   The main advantage to having one exit point is that it is easier to be
sure any necessary cleanup is performed prior to exit. It can be quite
messy when cleanup code is distributed in multiple copies throughout the
file. The example that I deleted involved opening files, then doing
something, then exiting if that something caused an error. This type of
situation makes it very easy to forget to close that file. If you call
this function many times, and have many errors, you will eventually run
out of files.

   It was just this bug I found in some production code, a year after it
was released. I put the software into a neverending demo loop during a
trade show and noticed that it started complaining about "no more units"
after 20 minutes or so. The code was bullet proof enough that it didn't
crash, just could no longer access any data. If the code had had but one
exit from that routine, it would probably have never had that bug get by.




<> "Aneth!  That's a charming place!" "You've been to Aneth?" 
<> "Yes, but not yet." -- The Doctor and Seth, "The Horns of Nimon".
><
<> "Sanity check!" "Sorry, we can't accept it, it's from out of state." - me

c164-bd@falstaff.uucp (John D. Mitchell) (11/17/90)

>In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes:
>
>At Clear we have instituted a style standard which
>all our engineers follow.  This standard specifies how indenting
>should be done, how variables, functions and types should be named.
>I specifies that functions should have single entrance and single
>exit points, and that functions should not be much longer then
>one page.  It specifies a documentation style and demands that
>comments always be placed on closing braces.  etc. etc.
>
I hate to jump into the middle of a religious war :-) but...
from working as a consultant/contractor, school (as a student), and
school (as a reader) I have found that it's not so much someone's
code formatting that makes such a big difference in ease of comprehension
but their design.  I have seen many bizarre (to me :-)) coding formats but
as long as it was halfway rational (read I could figure it out :-)) and
most of all CONSISTENT I could quickly adapt and understand the
meaning.  Sure there are cases where the code is all nice and tidy but
makes no sense, but each time it's the ambiguity of the design of
the [module|function|whatever] that's to blame (which of course was
the coder/designer's fault).  So make my life easier by being consistent.

As far as single entry/exit points go, I side with those who say
"It depends."  Again I stress the need for a clean design.  Sometimes
(ok so I'm moody! :-)) it works out nice for multiple return calls
and other times it doesn't.  I've been led to believe that we're
all supposed to be grown-ups and can make those kinds of decisions.
The trick for me is:  which way is the least complicated.

Naming.  What a mess.  You get everything from the minimalists (i, i2,
tmp, etc.) to those foreigners (:-)) at M#$@*soft with their
'Hungarian' notation.  Once again (boy I sure am repetitive!), it depends.
My style is still evolving.  I use my own (I think more consistent and
orthogonal) version of 'Hungarian' notation.  Hey, it works for me and
the way the rest of the name is (long and descriptive :-)) if you don't
understand the prefix you can just ignore it.


-----	John D. Mitchell
	johnm@cory.Berkeley.EDU

dmocsny@minerva.che.uc.edu (Daniel Mocsny) (11/17/90)

In article <7267@hub.ucsb.edu> 6600dt@ucsbuxa.ucsb.edu (David Goggin) writes:
>In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes:
>>At Clear we have instituded a style standard which
>>all our engineers follow.
>
>I don't think I'd
>like to have a format forced on me like that.

But by deviating from the standard, you are forcing additional noise
and complexity on everyone who needs to read your code.

Even a fairly poor standard will beat no standards almost every time, 
provided that the poor standard begins with a large-enough share of
the user base. The standard then becomes the language that enables
the users to share ideas with each other. Like any communications
system, the overall value of the system is in direct proportion to the
number of subscribers.

For example, consider the english language (and associated dialects,
such as all the USA varieties). What a mess---hundreds of irregular
verbs, a hopelessly irrational non-phonemic alphabet, an enormous
number of grammatical and pronunciation rules which it violates
constantly, etc. Any person with a shred of logic would understandably
hate to have such a standard imposed on them. The logical person would
chuck this bloated, inconsistent monstrosity and start over with
something simple and elegant, such as esperanto or loglan.

Yet english, with all its obvious warts and shortcomings, is quite
simply THE most valuable language to speak. This does not follow from
any inherent advantage of the language. Rather, it follows from who
happens to be speaking the language. And humans, being such marvelously
adaptive creatures, are quite capable of tolerating the flaws of
english and using it to advantage in spite of them.

If everybody who didn't like the details of the language decided to
change them as they saw fit, what would happen to the language? It
would become worthless. Fragmentation doesn't always kill computer
languages, of course, because the computer can be made to "understand"
any dialect. But fragmentation does reduce the value of a computer
language as a means for communication between programmers. As long as
we insist on creating code of potential value to more than one person,
this will be an important consideration.

> I
>think, however, I _well-designed_ standard does go a
>long way in clearing up the problem.  I would
>reccommend a standard that is thought out carefully
>in advance, to be most logical in showing the
>structure of code, as well as aestheticaly pleasing
>(a big factor for me.)

The situation for programmers is better than for natural-language
speakers, because automated formatting tools can allow individual
programmers some latitude for expression, while still retaining
compatibility with the standard. For example, the details of
indenting belong in a pretty-printing program (or language-sensitive
editor, for that matter). I can think of no reason to impose any
particular indenting style on a programmer, because a quick run through 
a standardizing beautifier will repair any idiosyncrasy.



--
Dan Mocsny				Snail:
Internet: dmocsny@minerva.che.uc.edu	Dept. of Chemical Engng. M.L. 171
	  dmocsny@uceng.uc.edu		University of Cincinnati
513/751-6824 (home) 513/556-2007 (lab)	Cincinnati, Ohio 45221-0171

gwyn@smoke.brl.mil (Doug Gwyn) (11/17/90)

In article <i7NRs3w163w@phoenix.com> stanley@phoenix.com (John Stanley) writes:
>   The main advantage to having one exit point is that it is easier to be
>sure any necessary cleanup is performed prior to exit.

A lot of the code in BRL's MUVES project has functions implemented more or
less along the following lines:

bool function( ... ) {
	...
	if ( problem )
		{
		ErSet( CODE_0 );
		goto err_0;
		}
	...
	if ( problem )
		{
		ErSet( CODE_N );
		goto err_n;
		}
	...
	return true;	/* success */

	/* error handling consolidated here: */

    err_n:
	fclose( fp );	/* for example */
	...
    err_0:
	FreeList( tp );	/* for example */
	...
	return false;
	}

The idea is to make sure the sequential actions are unwound in reverse
order when an error occurs.  While there are numerous other methods,
this one has worked rather well in practice.  It is also a good example
of structured use of "goto".

henry@zoo.toronto.edu (Henry Spencer) (11/18/90)

In article <6733@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes:
>...I can think of no reason to impose any
>particular indenting style on a programmer, because a quick run through 
>a standardizing beautifier will repair any idiosyncrasy.

Nonsense.  There are several reasons for not relying on beautifiers,
summed up well by the words written over a decade ago in the Indian Hill
style guide (with my footnote):

----------
This committee recommends that programmers not rely on automatic
beautifiers for the following reasons.
First, the main person who benefits from good program style is the
programmer himself.
This is especially true in the early design of handwritten algorithms
or pseudo-code.
Automatic beautifiers can only be applied to complete, syntactically
correct programs and hence are not available when the need for
attention to white space and indentation is greatest.
It is also felt that programmers can do a better job of making clear
the complete visual layout of a function or file, with the normal
attention to detail of a careful programmer\*f.
.FS
.IP \*F
In other words, some of the visual layout is dictated by intent
rather than syntax.
Beautifiers cannot read minds.
.FE
Sloppy programmers should learn to be careful programmers instead of
relying on a beautifier to make their code readable.
Finally, it is felt that since beautifiers are non-trivial programs
that must parse the source,
the burden of maintaining them in the face of the continuing evolution
of C is not worth the benefits gained by such a program.
----------
-- 
"I don't *want* to be normal!"         | Henry Spencer at U of Toronto Zoology
"Not to worry."                        |  henry@zoo.toronto.edu   utzoo!henry

dbc@bushido.uucp (Dave Caswell) (11/18/90)

.At Clear we have instituded a style standard which
.all our engineers follow.  This standard specifies how indenting
.should be done, how variables, functions and types should be named.
.I specifies that functions should have single entrance and single
.exit points, and that functions should not be much longer then
.one page.  It specifies a documentation style and demands that
.comments always be placed on closing braces.  etc. etc.

In my opinion anyone who wants to standardize simple formatting considerations
had better write a program to translate arbitrary code into that standard.

On the other hand rules like having a single entrance and exit point are good
ones.  They should be written down and strictly enforced.


-- 
David Caswell                             dbc%bushido.uucp@umich.edu

amodeo@dataco.UUCP (Roy Amodeo) (11/18/90)

In article <IMP.90Nov16123956@marvin.Solbourne.COM> you write:
>In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes:
>: It specifies that functions should have single entrance and single
>: exit points
>
>This is a bogus restriction, at least in terms of a single exit point.

It does solve some problems. The code fragments you've posted are
a pretty good illustration of why such standards exist. May I please
"correct" them?

>When you have small functions, the return statement can be used to
>give meaningful flow control to the functions w/o the need for a
>"goto".  I have found that when I adhere to this rule, I either get
>code that looks like:
>
>	if (allocate-memory) {
>		do some stuff
>		if (get-more-memory) {
>			do more stuff
>			if (open-file) {
>				do even more stuff
>				if (alloc more memory) {
>					...
>					status = OK;
>				}
>				else
>					status = NO_MEM
>			}
>			else
>				status = NO_FILE
>		}
>		else
>			status = NO_MEM
>	}
>	else
>		status = NO_MEM

	/*-- Don't forget to free memory and close files on failure!	--*/

	if ( status != OK ) {
		if ( file-is-opened )
			close-file;
		if ( more-memory-was-got )
			free-more-memory;
		if ( memory-allocated )
			free-memory;
	}
>
>	return status;
>
>Or I get code that looks like:
>
>	if (!allocate-memory) {
>		status = NO_MEM;
>		goto done;
>	}
>	...
>
>	last stuff
>	
>	status = OK;
>done:

	/*-- Insert same code fragment from above here		--*/
>	return status;
>
>When what I really want is:
	(with cleanup code added)
>
>	if (!allocate-memory)
>		return NO_MEM
>
>	do some stuff
>
>	if ( !get-more-memory)
	{
		free-memory-allocated-above
>		return NO_MEM
	}
>
>	do more stuff
>
>	if (!openfile)
	{
		free-memory-allocated-above
		free-memory-allocated-first-time
>		return NO_FILE
	}
>
>	do even more stuff
>
>	if (!alloc memory)
	{
		close-files
		...
>		return NO_MEM
	}
>
>	last stuff
>	
>	return OK;
>
>A quick check reveals that the above code segments are all the same.
I hope I've preserved that.

>However, I may have missed something.  The final one is the clearest
>one, IHO, of them all.  Comments....

But as you can see, it's also the most painful to modify to clean up
after itself. When there is no cleanup to be done, I agree that the
last example is clearest. However, if you introduce an operation near
the beginning that does have to be cleaned up when you fail then you
are setting yourself up for some pain.

That said, I think the first method is a pain, because of the indentation
required. The second one uses goto's which I still do not like (although
this is the only use of goto's that I consider justifiable (especially
if the programmers use a standard naming convention for the label at
the end of the routine. ))

A method we have been using on a very large project that retains readability
in exchange for making cleanup code a bit more awkward is the following:
( adapted to the conventions above )

In a project-wide include file we have

#define	FAILIF( cond, reason )	{ if (cond) { FAIL_ACTION; return reason; } }
#define	FAIL_ACTION	/*-- default is do nothing	--*/ 

The code we would write for your example would be:

#undef	FAIL_ACTION
#define	FAIL_ACTION	\
		if ( file-is-opened ) \
			close-file; \
		if ( more-memory-was-got ) \
			free-more-memory; \
		if ( memory-allocated ) \
			free-memory; \

	FAILIF( !allocate-memory, NO_MEM );
	do some stuff

	FAILIF( !get-more-memory, NO_MEM );
	do more stuff

	FAILIF( !open-file, NO_FILE );
	do even more stuff

	FAILIF( !alloc more memory, NO_MEM );
	return	OK;

The eye is forcibly directed to the abnormal termination conditions,
whereas embedded returns are a little harder to see. If one is concerned
about the amount of code generated, you could always do this:

#undef	FAIL
#define	FAIL(cond,reason)	{ if (cond) { status = reason; goto failed; } }

	FAILIF( !allocate-memory, NO_MEM );
	...

	return OK;

	failed:
		if ( file-is-opened )
			close-file;
		...
		return status;

Actually I really prefer the second form. The code produced is a little
tighter and it puts the cleanup code in a better place: near the normal
return statement.

Apologies for being longwinded, and I hope I didn't come off sounding
too arrogant. I'll second Warner's request for comments.

>Warner Losh		imp@Solbourne.COM

rba iv			(a signature file would be an admission of existence)
nrcaer!dataco!amodeo

jdarcy@encore.com (Jeff d'Arcy) (11/19/90)

dbc@bushido.uucp (Dave Caswell) writes:
>rules like having a single entrance and exit point are good
>ones.  They should be written down and strictly enforced.

Blech!  Consider the following example:

int fubar (x, y, z)
int x, y, z;
{
    if (abnormal_condition_1)
	return(foo);
    if (abnormal_condition_2)
	return(bar);
    for (blah; blah; blah) {
	do_some_stuff();
	if (screwed_up)
	    return(foobar);
	do_other_stuff();
    }
    return(blech);
}

If you enforce a single-exit-point rule the code will be obfuscated to a
pretty high degree.  For starters you'd have to declare a dummy return
variable to hold values for the abnormal_condition cases, just so you can
use it at your single exit point.  Then you'd have the entire for loop
encased in an unnecessary extra if statement, contributing to "indentation
creep", that nasty syndrome where the real work in a routine is indented
halfway across the page.  To get rid of the return statement in the for
loop you'd either have to use a break (another no-no) or add a new status
variable, making the loop condition more complex and indenting the bottom
part of the for loop still further.

In short, the handstands you'd have to do to enforce a single-exit-point
rule make the code *less* readable and often less efficient as well even
in simple cases such as this.  I'm rabidly opposed to unconstrained goto
statements, but return, break and continue are controlled enough to be
worthwhile.
--

Jeff d'Arcy, Generic Software Engineer - jdarcy@encore.com
             Ask me if I care. . .maybe I do

browns@iccgcc.decnet.ab.com (Stan Brown) (11/19/90)

In article <1990Nov10.191840.21113@clear.com>, rmartin@clear.com (Bob Martin) writes:
> 
> The lack of standard coding practice IS a big problem for software
> maintenance.  At Clear we have instituted a style standard which
> [...] demands that comments always be placed on closing braces.

Am I the only one who thinks this extremely silly?

        int io_fatal_error_count = 0;

        void io_error(int code) 
        {
            char *errmsg;

            errmsg = io_stget(code);
            if (errmsg == NULL) {
        	++io_fatal_error_count;
        	printf("Error code %d: full explanation not available\n");
            }   /* end if errmsg is NULL */
            else
        	printf("Error %d: %s\n", code, errmsg);

        }   /* end of function prterr */

Given _any_ rule in a coding standard, it's possible to come up with an
example where applying the rule is inappropriate.  But the rule cited
above is the other way round: following it is more likely to hurt than
help.  Following it blindly will certainly hurt.

Just to hammer homee the point: My problem is chiefly with the "always"
part of the cited rule.

Please do not attribute these remarks to any other person or company.
                                   email: browns@iccgcc.decnet.ab.com
Stan Brown, Oak Road Systems, Cleveland, Ohio, USA    +1 216 371 0043

ghoti+@andrew.cmu.edu (Adam Stoller) (11/19/90)

Excerpts from netnews.comp.lang.c: 16-Nov-90 Re: Coding Standards.
was:.. Warner Losh@marvin.Solbo (1834)

> When what I really want is:

> 	if (!allocate-memory)
> 		return NO_MEM

> 	do some stuff

> 	if (!get-more-memory)
> 		return NO_MEM

> 	do more stuff

> 	if (!openfile)
> 		return NO_FILE

> 	do even more stuff

> 	if (!alloc memory)
> 		return NO_MEM

> 	last stuff
> 	
> 	return OK;


The final one is the clearest one, IHO, of them all.  Comments.

Well, if you're looking for a highly maintainable coding standard - you
would be better off keeping the braces for each if/else/for/while/(etc)
loops (not to mention the semicolons after the return statements;-) -
i.e.:

{
    if (!allocate-memory){
        return (NO_MEM);
    }
    /* do some stuff */

    if (!get-more-memory){
        return (NO_MEM);
    }
    /* do more stuff */

    if (!openfile){
        return (NO_FILE);
    }
    /* do even more stuff */

    if (!alloc memory){
        return (NO_MEM);
    }
    /* last stuff */
    return (OK);
}

Whether or not to put parens around the argument to return is, of
course, another tidbit of religious wardom, I prefer to do it, a lot of
other people prefer not to - whatever you do, you should try to be
consistant.

As for the braces - the reason for them is that it helps to avoid nasty
situations when the next person maintaining the code has to add one more
thing before the return statement - and doesn't realize that there
wasn't a set of braces around it to begin with.  By always putting the
braces there, you waste a fairly insignificant amount of space, do
nothing if not improve readabiltiy, and increase the maintainability (by
others) quite a bit -- by not leaving the door open for those simple to
make (and often hard to find) bugs.

Other than that, I agree with you in that I find your third example
(with above modification) much clearer to work with than the [in]finite
nesting, or goto style.

--fish
    

dmocsny@minerva.che.uc.edu (Daniel Mocsny) (11/20/90)

In article <1990Nov18.005030.28841@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>In article <6733@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes:
>>...I can think of no reason to impose any
>>particular indenting style on a programmer, because a quick run through 
>>a standardizing beautifier will repair any idiosyncrasy.
>
>Nonsense.  There are several reasons for not relying on beautifiers,
>summed up well by the words written over a decade ago in the Indian Hill
>style guide (with my footnote):
>----------
>This committee recommends that programmers not rely on automatic
>beautifiers for the following reasons.
>First, the main person who benefits from good program style is the
>programmer himself.

I apologize for being unduly vague with "programmer". I should have said 
"competent programmer". I assumed a programmer who already believes 
(s)he has a "good" programming style, and is able to write code that 
(s)he can read. I didn't mean someone who loses the ball after writing 
50 lines of spaghetti. Such a programmer definitely should not rely on 
a beautifier (if the beautified output is too different from the
original, it won't assist the programmer's thinking). So the "any 
idiosyncrasies" I had in mind would probably be rather slight. 

However, in the rest of this article, I will try to show that if
beautifiers are deficient, then our definition of "good program style"
must be similarly deficient.

>Automatic beautifiers can only be applied to complete, syntactically
>correct programs and hence are not available when the need for
>attention to white space and indentation is greatest.

This was written 10 years ago. That sounds like a long time in the
world of computers. It especially sounds like a long time in the
C language market, which is quite dynamic and competitive now. Has no 
progress transpired in the meantime, or are we talking about an
inherent limitation of beautifiers? (Remember, in my original comment,
I assumed a programmer who does not need help from a beautifier to
read her/his own code, and I was speaking of a beautifier as a
tool to assist programmers in the job of reading other programmer's
code.)

>It is also felt that programmers can do a better job of making clear
>the complete visual layout of a function or file, with the normal
>attention to detail of a careful programmer\*f.

This is the crux of the original notion in this thread. The question 
was whether a standardized coding style was a good idea. I said I 
favored standards over chaos, in general. Saying the programmer
can do a better job at source formatting is equivalent to saying that
we cannot rigorously define a standardized coding style. A rigorously
defined style would be suitable for implementing in a beautifier
and compliance-checking program. If this is not possible, then what
we call "good program style" must necessarily remain somewhat vague.

A vague standard leaves many details to the discretion of the
programmer. While this probably reduces the value of the standard,
insofar as minimizing the barriers to inter-programmer communication,
it also reduces the potential for disagreements on style. 

>In other words, some of the visual layout is dictated by intent
>rather than syntax.

The standard must not interefere, then, with the details of layout
that depend on programmer intent. However, that still leaves some
question about how syntax shall dictate those portions it dictates.
What will happen when two programmers disagree on the best way to
lay out those portions of their code which are amenable to syntax-
dictated layout? 

Since these two programmers disagree about a detail which is easy
to embed in a beautifier program, since it depends only on syntax, 
then a beautifier program should be able to mediate the style 
disagreement, and allow each programmer to view the other's code
consistently with personal preference. I now modify my original 
garbled claim to the previous sentence.

>Beautifiers cannot read minds.

Then this must also be true of the definition of "good program style".
Everything we can unambiguously state about "good program style" must
be able to live in a beautifier. If we can't write good beautifiers,
then we also can't say exactly what we mean by "good program style",
other than we know it when we see it. :-)

>Finally, it is felt that since beautifiers are non-trivial programs
>that must parse the source,
>the burden of maintaining them in the face of the continuing evolution
>of C is not worth the benefits gained by such a program.

This is almost certainly true if the programming team must maintain 
its own tools. However, in 10 years the market for C language tools 
has grown substantially. The market today can provide the economy of
scale needed to turn the "burdens" of 10 years ago into profitable
opportunities.

I suspect that 10 years ago, the burden of maintaining full-screen 
symbolic debuggers was also not worth the benefits gained by such a
program. Today, of course, we regard an environment lacking such to
be rather deficient.


--
Dan Mocsny				Snail:
Internet: dmocsny@minerva.che.uc.edu	Dept. of Chemical Engng. M.L. 171
	  dmocsny@uceng.uc.edu		University of Cincinnati
513/751-6824 (home) 513/556-2007 (lab)	Cincinnati, Ohio 45221-0171

dbc@bushido.uucp (Dave Caswell) (11/20/90)

I said
>>rules like having a single entrance and exit point are good
>>ones.  They should be written down and strictly enforced.

.
.Blech!  Consider the following example:
.
>int fubar (x, y, z)
>int x, y, z;
>{
>    if (abnormal_condition_1)
>	return(foo);
>    if (abnormal_condition_2)
>	return(bar);
>    for (blah; blah; blah) {
>	do_some_stuff();
>	if (screwed_up)
>	    return(foobar);
>	do_other_stuff();
>    }
>    return(blech);

Try modifying this to pass in the error value, or how about if clean-up
code has to be written.  They're plenty of reasons to think that a goto
to ERROR_EXIT: (or whatever), is better than having more than one return
statement.

-- 
David Caswell                             dbc%bushido.uucp@umich.edu

peter@ficc.ferranti.com (Peter da Silva) (11/20/90)

(crossposted to comp.lang.misc... this is a general coding problem and
 not C-specific)

My objection to beautifiers is what they do to stuff like this:

ARGDESC	Args[] =
{
	'T',	ARGOPT,		argChar,	__ &TabChar,	"Tab",
	'a',	ARGOPT,		argBool,	__ &AllFlag,	"All",
	'1',	ARGOPT,		argBool,	__ &OneFlag,	"First",
	' ',	ARGREQ,		argStr,		__ &Format,	"Format",
	' ',	ARGREQ|ARGLIST,	listStr,	__ &CmdNames,	"Command",
	'f',	ARGOPT|ARGLIST,	listStr,	__ &Files,	"File",
	ENDOFARGS
};

The only real solution to this is to include formatter commands in comments
or something of that nature, so the code ends up as:

ARGDESC	Args[] =
{
/*.TS	L	L		L		L		L */
	'T',	ARGOPT,		argChar,	__ &TabChar,	"Tab",
...
	'f',	ARGOPT|ARGLIST,	listStr,	__ &Files,	"File",
/*.TE */
	ENDOFARGS
};

Which is probably a good idea, especially if you make the format command
syntax loose enough:

/*.TS	option	flags		function	variable	keyword */

But I don't know any fprmatter that supports this...
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com 

salomon@ccu.umanitoba.ca (Dan Salomon) (11/21/90)

In article <6741@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes:
>In article <1990Nov18.005030.28841@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
> > It is also felt that programmers can do a better job of making clear
> > the complete visual layout of a function or file, with the normal
> > attention to detail of a careful programmer\*f.
>
> ... Saying the programmer
> can do a better job at source formatting is equivalent to saying that
> we cannot rigorously define a standardized coding style. A rigorously
> defined style would be suitable for implementing in a beautifier
> and compliance-checking program. If this is not possible, then what
> we call "good program style" must necessarily remain somewhat vague.
>

The real problem is that to prepare the ideal layout for a program the
beautifier would have to:

  (1) Read and understand the comments.  This is especially true
      if the comments label the rows and columns of a table of data
      or expressions.
  (2) Understand the problem being solved, and the method being used.
      Blank lines in code segments can help delineate the steps in a
      computation, and spaces can be used to group related parts
      of an expression.
  (3) Know enough psychology to predict the human response to a layout.
      Layout choices made by a standard can be optimal in the general
      case but suboptimal in specific cases.

All of these factors influence a complete program layout.  It is
still much easier for a programmer to do it while coding than for
someone else to write a beautifier that can do it after the fact for
any program at all.
-- 

Dan Salomon -- salomon@ccu.UManitoba.CA
               Dept. of Computer Science / University of Manitoba
	       Winnipeg, Manitoba, Canada  R3T 2N2 / (204) 275-6682

rmartin@clear.com (Bob Martin) (11/22/90)

In article <291@dcsun21.dataco.UUCP> amodeo@dataco.UUCP (Roy Amodeo) writes:
>In article <IMP.90Nov16123956@marvin.Solbourne.COM> you write:
>>In article <1990Nov10.191840.21113@clear.com> rmartin@clear.com (Bob Martin) writes:
>>: It specifies that functions should have single entrance and single
>>: exit points
>>
>>This is a bogus restriction, at least in terms of a single exit point.
>
>It does solve some problems. The code fragments you've posted are
>a pretty good illustration of why such standards exist. May I please
>"correct" them?
>
>A method we have been using on a very large project that retains readability
>in exchange for making cleanup code a bit more awkward is the following:
>( adapted to the conventions above )
>
>In a project-wide include file we have
>
>#define	FAILIF( cond, reason )	{ if (cond) { FAIL_ACTION; return reason; } }
>#define	FAIL_ACTION	/*-- default is do nothing	--*/ 
>
>The code we would write for your example would be:
>
>#undef	FAIL_ACTION
>#define	FAIL_ACTION	\
>		if ( file-is-opened ) \
>			close-file; \
>		if ( more-memory-was-got ) \
>			free-more-memory; \
>		if ( memory-allocated ) \
>			free-memory; \
>
>	FAILIF( !allocate-memory, NO_MEM );
>	do some stuff
>
>	FAILIF( !get-more-memory, NO_MEM );
>	do more stuff
>
>	FAILIF( !open-file, NO_FILE );
>	do even more stuff
>
>	FAILIF( !alloc more memory, NO_MEM );
>	return	OK;
>

The thing that I don't like about this is that the "cleanup"
code is relatively hidden, and thus it is easier for a noviciate
to make modifications which are not "cleaned up".

I understand the desire to hide the cleanup details since they
detract from the 'intent' of the function.  It is easier to
determine "what" a program is doing if the cleanup details
are hidden.  But it is harder to determine if the "what" is
being done correctly.  

IMHO if a function is going to be understood, then the details
are just as important as the "what", and deserve as prominent
a place in the code.  If this makes the function a bit harder
to understand, then I say that the extra effort is justified
since otherwise the function would not "really" be understood.

When you hide cleanup details, you are sending a message to future
readers of your code:  "Don't worry about this guys, I've already
taken care of it."  This is _never_ the message you want to send.
Instead you want to say:  "This is what I did to do the job, and
this is what I did to clean up after."

-- 
+-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for |
| rmartin@clear.com    |:R::R:C::::M:M:M:M:| my words but me.  I want  |
| uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all   |
+----------------------+:R::R::CCC:M:::::M:| the blame.  So there.     |

rmartin@clear.com (Bob Martin) (11/22/90)

In article <2055.27469abd@iccgcc.decnet.ab.com> browns@iccgcc.decnet.ab.com (Stan Brown) writes:
>In article <1990Nov10.191840.21113@clear.com>, rmartin@clear.com (Bob Martin) writes:
>> 
>> The lack of standard coding practice IS a big problem for software
>> maintenance.  At Clear we have instituted a style standard which
>> [...] demands that comments always be placed on closing braces.
>
>Given _any_ rule in a coding standard, it's possible to come up with an
>example where applying the rule is inappropriate.  But the rule cited
>above is the other way round: following it is more likely to hurt than
>help.  Following it blindly will certainly hurt.
>
>Just to hammer homee the point: My problem is chiefly with the "always"
>part of the cited rule.

The "ALWAYS" is present because it is the safest course.  Programmers
are not always very good at predicting what changes will be made
to their code in the future.  If he makes decides that comments
on his closing braces are not important because his conditionals
are trivial, then he is ignoring the possibility that two
years from now some other engineer my add many lines of code
to his conditionals, making the comment on the closing brace
useful.

The convention is "demanded" because it is cheap, easy, has very
few down-sides, and the _possibility_ of significant up-sides.


-- 
+-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for |
| rmartin@clear.com    |:R::R:C::::M:M:M:M:| my words but me.  I want  |
| uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all   |
+----------------------+:R::R::CCC:M:::::M:| the blame.  So there.     |

peter@ficc.ferranti.com (Peter da Silva) (11/29/90)

In article <6733@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes:
> Even a fairly poor standard will beat no standards almost every time, 
> provided that the poor standard begins with a large-enough share of
> the user base. [uses English language as an example]

Ah, but consider what it would be like to have to express oneself:
	1) In bureaucratese which
		a) is the sort of standard that standards committees
		   generate
			i) with the best of intentions
			ii) despite their own best efforts
		b) is capable of driving people
			i) insane
				A) clinically
				B) metaphorically
			ii) to desparate acts
		c) nobody wants to read, whether
			i) they want to
			ii) they have to
				A) as a job requirement
				B) simply to get along
					I) with friends
					II) with family
					III) with the government
						... etc...
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com 

rsalz@bbn.com (Rich Salz) (12/06/90)

In <L237B.5@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
>My objection to beautifiers is what they do to stuff like this:
	ARGDESC	Args[] =
	{
		'T',	ARGOPT,		argChar,	__ &TabChar,	"Tab",
		'a',	ARGOPT,		argBool,	__ &AllFlag,	"All",
		'1',	ARGOPT,		argBool,	__ &OneFlag,	"First",
		' ',	ARGREQ,		argStr,		__ &Format,	"Format",
		' ',	ARGREQ|ARGLIST,	listStr,	__ &CmdNames,	"Command",
		'f',	ARGOPT|ARGLIST,	listStr,	__ &Files,	"File",
		ENDOFARGS
	};
If you put the curly braces in then there would be no problem:
	{ 'T',    ARGOPT,         argChar,        __ &TabChar,    "Tab", }
Anyone who maintains the code after you will thank you for it.

The other problem is to not use the C pre-processor to change the syntax of
the language, as __ and ENDOFARGS apparently do.
	/r$
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.

peter@ficc.ferranti.com (Peter da Silva) (12/07/90)

In article <3072@litchi.bbn.com> rsalz@bbn.com (Rich Salz) writes:
> In <L237B.5@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
> >My objection to beautifiers is what they do to stuff like this:
> 		'T',	ARGOPT,		argChar,	__ &TabChar,	"Tab",

> If you put the curly braces in then there would be no problem:
> 	{ 'T',    ARGOPT,         argChar,        __ &TabChar,    "Tab", }

Really? I run this code through Indent and I get:

	{
		'T', ARGOPT, argChar, __ & TabChar, "Tab",
	}

> Anyone who maintains the code after you will thank you for it.

Good point. I normally do, but in this case I was cribbing from the
parseargs sample code.

> The other problem is to not use the C pre-processor to change the syntax of
> the language, as __ and ENDOFARGS apparently do.

Complain to Eric Allman. I don't see this as such a heinious sin, myself,
if it significantly improves readability (as it does in this case).
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com