Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Feb 1996 20:34:56 -0700 (MST)
From:      Barnacle Wes <wes@intele.net>
To:        freebsd-chat@freebsd.org
Cc:        wes@intele.net (Wes Peters)
Subject:   Coding (non-)style
Message-ID:  <199602290334.UAA24697@intele.net>

next in thread | raw e-mail | index | archive | help
Chris Layne (coredump@nervosa.com) said:
% This is from /usr/src/linux/Documentation/CodingStyle, it's Linus' own 
% personal coding style. Am I the only one here who finds this, ultimate 
% shit? Heh, I love how he says functions can't me more than 2 pages long, 
% and if you are indenting beyond 3 indentions, your function is broke, and 
% you should recode it. Whatever Linus.


You're certainly not the only one.  At my 'day job', our coding standards
consist of:

	Use 4-character indents
	Tabs are considered to be 4 characters wide.
	Open brace should be on the following line, aligned with the code
	above it.  The closing brace should line up with the opening brace.
	Everything in between should be indented one more tab.

That's it.  This works for a team of 14 programmers, maintaining and
upgrading 400,000 lines of C and C++ code continually.  It helps that
we have a pretty talented group.  ;^)


-------------------------------------------------------------------------


Anyhow, to nit-pick Linus' guide:

> First off, I'd suggest printing out a copy of the GNU coding standards,
> and NOT read it.  Burn them, it's a great symbolic gesture. 

This is stupid; FSF has produced a lot of good software, they must be
doing *something* right.  Studying their style, if only for points you
disagree with, is a good exercise for would-be style writers.


-------------------------------------------------------------------------


> Tabs are 8 characters, and thus indentations are also 8 characters. 

I thought tabs were .5 inches?  Which makes them 4 characters at
8 cpi, or 5 characters at 10 cpi, etc.


> There are heretic movements that try to make indentations 4 (or even 2!)
> characters deep, and that is akin to trying to define the value of PI to
> be 3. 

No, it's like trying to define it at 3.14 if you need two decimal places
of precision, instead of pendantically demanding that it is 3.1415926,
which is only slightly more accurate, and may be insignificant.


> Rationale: The whole idea behind indentation is to clearly define where
> a block of control starts and ends.  Especially when you've been looking
> at your screen for 20 straight hours, you'll find it a lot easier to see
> how the indentation works if you have large indentations. 

You will?  I certainly don't.  3 or 4 characters is plenty for me.
Get a better terminal.


> Now, some people will claim that having 8-character indentations makes
> the code move too far to the right, and makes it hard to read on a
> 80-character terminal screen.  The answer to that is that if you need
> more than 3 levels of indentation, you're screwed anyway, and should fix
> your program. 

Right.  Now I can see why your kernel is slow; you have too many function
calls in it.  This *really* bites on old, slower hardware with a lot
of overhead for function calls, like a 386.  Or the 68K cpus I use at
work.

	/* Do something big in little pieces 'cause Linus says I have to. */

	tons of global data here, since we can't just keep it all in the
	function...

	void
	big_func()
	{
		little_func_1();
		little_func_2();
		little_func_3();
		little_func_4();
	}

What crap.


> In short, 8-char indents make things easier to read, and have the added
> benefit of warning you when you're nesting your functions too deep. 
> Heed that warning. 


> Placing Braces
> 
> The other issue that always comes up in C styling is the placement of
> braces.  Unlike the indent size, there are few technical reasons to
> choose one placement strategy over the other, but the preferred way, as
> shown to us by the prophets Kernighan and Ritchie, is to put the opening
> brace last on the line, and put the closing brace first, thusly:
> 
> 	if (x is true) {
> 		we do y
> 	}

I suppose Linus hasn't heard that DMR blames this coding style on
the editors at Addison-Wesley, and doesn't code this way himself.
It was chosen to save space on the printed page, and the 5-char
indents for the same reason.

This brings up another interesting point: through most of this
document, Linus' reason for doing something is "because K&R did it
that way," unless he disagrees!  The 8-character tabbing is a case
in point.


> However, there is one special case, namely functions: they have the
> opening brace at the beginning of the next line, thus:

Aha!  A "special case"!  Sounds non-orthogonal to me!


> Heretic people all over the world have claimed that this inconsistency
> is ...  well ...  inconsistent, but all right-thinking people know that
> (a) K&R are _right_ and (b) K&R are right.  Besides, functions are
> special anyway (you can't nest them in C). 

Maybe your compiler can't.  ;^)


> Rationale: K&R. 

Irrationale: pedantic, except when he chooses to be inconsistent.


> Also, note that this brace-placement also minimizes the number of empty
> (or almost empty) lines, without any loss of readability.

Says you.  I prefer white space to separate each functional grouping
of code, and find that it makes the code much more readable.
Writers of english do this, too; they call the functional blocks
"paragraphs" or "stanzas."  ;^)


> Thus, as the
> supply of new-lines on your screen is not a renewable resource (think
> 25-line terminal screens here), you have more empty lines to put
> comments on. 

The supply of new-lines on *my* screen is entirely adequate at 50.
If I feel the need to have 60, I'll go out and buy a 19" monitor
to replace my 17".  If you're stupid enough to program on a terminal,
you need to find a better job.


-------------------------------------------------------------------------


> C is a Spartan language, and so should your naming be.  Unlike Modula-2
> and Pascal programmers, C programmers do not use cute names like
> ThisVariableIsATemporaryCounter.  A C programmer would call that
> variable "tmp", which is much easier to write, and not the least more
> difficult to understand. 

This C programmer prefers to name variables functionally.  If the
variable is a loop counter, and you want to call it loopCounter,
go right ahead.  index might be a better name, but it might also
be overloaded in the problem-space, leading to confusion.  Best
bet is to avoid confusion at all costs.


> HOWEVER, while mixed-case names are frowned upon, descriptive names for
> global variables are a must.  To call a global function "foo" is a
> shooting offense. 

Unless, of course, the function stands for "file on output," right?
mixedCaseNames are no more or less fowned upon than silly_old_c_
coder_names_full_of_embedded_underscores.  Name your variables and
functions reasonably and the actual style becomes far less important.


> Encoding the type of a function into the name (so-called Hungarian
> notation) is brain damaged - the compiler knows the types anyway and can
> check those, and it only confuses the programmer.  No wonder MicroSoft
> makes buggy programs. 

We agree on something at last!


> LOCAL variable names should be short, and to the point.

How 'bout if we just stick with "to the point."  Short is irrelevant.


> If you have
> some random integer loop counter, it should probably be called "i". 

If you have some random integer loop counter, you need to rewrite
your code.  Keeping arrays of random stuff around is non-productive.
If you are using a loop counter to enumerate each of the items in
an array, name the loop counter appropriately.  I.e.

	// If all inputs was specified, loop through each defined
	// switcher input and add it to the switch request.

	if (switchInputs == ALL_INPUTS)
	{
	    for (INPUT input = 0; input < numSwInputs; input++)
	    {
		INPUT swInput = toSwitcherInput(input);
		if (swInput != UNDEF)
		{
		    request.append(swInput);
		    LogMessage(...debugging code here...);
		}
	    }
	}

Whew!  Just broke 3 or 4 of Linus' rules in that little snippet
of code, paraphrased from what I'm working on right now.  Funny,
it still looks readable to me...


------------------------------------------------------------------------


> Functions should be short and sweet, and do just one thing.

Exactly.  Short enough, but not too short.


> They should
> fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
> as we all know), and do one thing and do that well. 

Bzzzt!  Arbitrarily setting the maximum length of a function at 48
lines is nor more or less stupid than setting at 9,604 lines, or
even 111,613 lines.  The function should be long enough to accomplish
the task at hand.


> However, if you have a complex function, and you suspect that a
> less-than-gifted first-year high-school student might not even
> understand what the function is all about, you should adhere to the
> maximum limits all the more closely.  Use helper functions with
> descriptive names (you can ask the compiler to in-line them if you think
> it's performance-critical, and it will probably do a better job of it
> that you would have done). 

This assumes that you have a small, encasulated data set so you don't
have to resort to global variables to accomplish this.  Perversely 
enough, this works better in C++ than in C.  Keep in mind, however,
that class data members are just another form of global variables.


> Another measure of the function is the number of local variables.  They
> shouldn't exceed 5-10, or you're doing something wrong.  Re-think the
> function, and split it into smaller pieces.  A human brain can
> generally easily keep track of about 7 different things, anything more
> and it gets confused.  You know you're brilliant, but maybe you'd like
> to understand what you did 2 weeks from now. 

7 +/- 2, according to Card, Moran, and Newell.  On the other hand,
aribtrarily splitting up a function into smaller functions that operate
on the same data doesn't make it simpler, it makes it more complex.
When you're telling the story of variable 'userSessions', you should
tell it all in one function.


------------------------------------------------------------------------


> Comments are good, but there is also a danger of over-commenting.

There are good (helpful) comments, and there are bad (unhelpful)
comments, but there are NEVER too many comments.  Just too many
unhelpful comments.

Having the entire design for a chunk of software in the comments
is a wonderful thing, if the design was helpful in the first place.

> NEVER
> try to explain HOW your code works in a comment: it's much better to
> write the code so that the _working_ is obvious, and it's a waste of
> time to explain badly written code. 

Yup.

> Generally, you want your comments to tell WHAT your code does, not HOW. 

Yup.

> Also, try to avoid putting comments inside a function body: if the
> function is so complex that you need to separately comment parts of it,

Nope.  As I said before, once you've marshalled some interesting
data into one place (a variable or structure), you should go ahead
and complete the function right then and there.  If you have to do
4 separate "transformations" on that variable, your code should look
like 4 paragraphs.  This doesn't however require you to add in the
extra conceptual overhead of splitting it into four functions.

> you should probably go back to chapter 4 for a while.  You can make
> small comments to note or warn about something particularly clever (or
> ugly), but try to avoid excess.  Instead, put the comments at the head
> of the function, telling people what it does, and possibly WHY it does
> it. 

Why is fodder for the design document.


------------------------------------------------------------------------


> You've made a mess of it.

As we say at work, "This week, on This Old Code:"  ;^)

"Ah, a lovely 17th-century interrupt service routine.  Unfortunately,
Norm, I think we're going to have to remove it completely."


> That's ok, we all do.  You've probably been told by your long-time unix
> user helper that "GNU emacs" automatically formats the C sources for
> you, and you've noticed that yes, it does do that, but the defaults it
> uses are less than desirable (in fact, they are worse than random
> typing - a infinite number of monkeys typing into GNU emacs would never
> make a good program). 

Obviously you haven't taken the time to learn how to use it correctly.
Typical ignorance.  Let's take a look through my .emacs file...

	(c-set-style "Stroustrup")

Ah, the style that refreshes.  Recto-cranial inversion reverted.  ;^)


> So, you can either get rid of GNU emacs, or change it to use saner
> values.  To do the latter, you can stick the following in your .emacs file:
> 
> (defun linux-c-mode ()
>   "C mode with adjusted defaults for use with the Linux kernel."
>   (interactive)
>   (c-mode)
>   (setq c-indent-level 8)
>   (setq c-brace-imaginary-offset 0)
>   (setq c-brace-offset -8)
>   (setq c-argdecl-indent 8)
>   (setq c-label-offset -8)
>   (setq c-continued-statement-offset 8)
>   (setq indent-tabs-mode nil)
>   (setq tab-width 8))

Gag choke puke.  Make that (defun pig-ignorant-code-mode ()


> This will define the M-x linux-c-mode command.  When hacking on a
> module, if you put the string -*- linux-c -*- somewhere on the first
> two lines, this mode will be automatically invoked. Also, you may want
> to add
> 
> (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
>                        auto-mode-alist))
> 
> to your .emacs file if you want to have linux-c-mode switched on
> automagically when you edit source files under /usr/src/linux.

Mine'll get called if you have -*- pig-ignorant-code -*- embedded
somewhere in the first two lines, which is MUCH funnier.  ;^)

Assuming you're stupid enough to *want* to look under
/usr/src/pig-ignorant-code.


> "indent" has a lot of options, and especially when it comes to comment
> re-formatting you may want to take a look at the manual page.  But
> remember: "indent" is not a fix for bad programming. 

Obviously -- look in /usr/src/linux!

-- 
   Wes Peters	| Yes I am a pirate, two hundred years too late
    Softweyr 	| The cannons don't thunder, there's nothing to plunder
   Consulting	| I'm an over forty victim of fate...
 wes@intele.net	|					Jimmy Buffett



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199602290334.UAA24697>