Natt Serrasalmus wrote:
After years of operating without any coding standards whatsoever,
the company that I recently started working for has decided that
it might be a good idea to have some. I'm involved in this initiative.
Typically, I find that coding standards are written
by some guy in the company who has a way of coding that he likes
and then tries to force everybody else to write code the way he likes it,
not for any rational reason, but simply for the subjective way he likes it.
Are you that guy?
I think this is wrong.
Yes, but are you that guy?
This is particularly irksome when it comes to issues of code layout style
which has very little relevance to the execution of the code or the
readablility and maintenance of the code.
You need to distinguish between *style* issues
and good programming practice.
I also think [that] it is wrong for coding standards
to try to prevent idiots from doing stupid things.
I don't think it's wrong.
I just don't think it works.
No matter how stringent some standards are,
somebody stupid is going to find a way to do something stupid to the code.
My point is that instead of making the standard more restrictive on good coders,
the bad coders should be brought up to speed to be able to write good code,
not pandered to by the standard.
For example, there is the seemingly universal attitude that fully bracketed
syntax is the way to go (this will stop the idiots). I strongly disagree.
There are many times that leaving out the braces where not necessary makes
for more readable code. It also reduces the maintenance of braces; the fewer
braces the easier it is to keep braces matched up. The problem is that I
think most coders are too lazy to be bothered to know exactly when they need
braces and when they don't. If you don't know, just stick them in everywhere
that it can't hurt. Lots and lots of braces means lots and lots of code to
maintain that doesn't need to be there.
I recently read a standard that prohibited use of the ternary
(conditional ?:) operator. I find that most C programmers
just haven't bothered to learn how to use it and don't want others to use it,
because then they'll have to figure it out. However, I have also found that
in most cases where it is used, it can make the code much clearer
even for those who are not accustomed to its use.
a = (b == c)? d: e;
Is just as understandable and more maintainable than
if (b == c) {
a = d;
}
else {
a = e;
}
It may be the only practical way to initialize a constant
const int a = (b == c)? d: e;
In the first case it is obvious in one line that
you are simply assigning a value to a based on the condition.
The use of the if statement makes for a lot more code
that is subject to error in maintenance.
Another issue that I have come across is the one way out of a function
issue. I contend that if there are conditions that warrant an earlier exit
from a function then the early exit should be taken. For eample:
int funct(int arg)
{
....
if (condition) return ERROR;
...
return OK;
is much better than
int funct(int arg)
{
int retval = ERROR;
....
if (!condition) {
retval = OK;
(rest of function);
...
} /* end of if ( !condition) */
return retval;
This is a bit of a "straw man" argument.
The problem is that functions which contain multiple exit points
are extremely difficult to read, understand an maintain.
Suppose, for example, that you need to modify the code
and malloc some temporary storage.
How do you ensure that that storage is free'd
before any of the multiple exits?
Maybe you can write more concise code
with one, two, three or mre return statements.
But where do you draw the line.
The line has been drawn, perhaps somewhat arbitrarily,
at a single point of return --
preferrably at the end of the function.
This simplifies cleanup, for example,
because the thread of execution is guaranteed
to run through any statements such as free
which are placed just before it.
In the first case you've been very clear as to what values are going to be
returned, you've reduced the number of braces involved and you've reduced
the indentation level of the major part of the function. The argument
against this is that there may be some clean up that needs to be done in a
function and this style may lead an idiot to exit the function with out
doing the clean up. My rebuttal is that number one, only a small minority of
functions have the requirement that the clean up be done before exiting the
function. Number two, the clean up should be a separate function anyway that
can be called from anywhere in the parent function
and number three you just can't count on the standard
to protect the code from idiots anyway so why pretend that it does?
A similar issue is this one:
if (condition) {
retval = func(arg);
}
If that condition has to be tested before each function,
then the condition should be evaluated by the function instead:
retval = func(arg, condition);
...
int func(int arg, BOOLEAN condition)
{
if (!condition) return OK;
...
}
On the whole I consider less code to be more maintainable than lots of code.
Anywhere I can reduce the lines of code
then that makes it easier to maintain. For example:
if(condition)
{
retval = func(a, b);
}
else
{
retval = func(a, c);
}
if (retval != OK)
{
error_exit_func ();
}
a much better way is
if (!func(a, condition? b: c) error_exit_func ();
Is there anybody out there who will agree with me on these issues
or am I the lone voice for this type of coding?
As far a coding style is concerned
that should be left up to each individual programmer.
Any rules regarding the style used for code repositories
can and should be resolved with a code reformatter such as indent
http://www.gnu.org/software/indent/indent.html
From: E. Robert Tisdale
Subject: Tisdale's C and C++ Style Guide
Newsgroups: comp.lang.c, comp.lang.c++
Date: 2003/01/13
Style is a very subjective and personal consideration.
C and C++ programmers develop or adopt a style
in order to make their code easier for themselves
and other programmers to read, understand and maintain.
If you are developing your own style, there are no rules
except that you should try to be consistent.
Otherwise, you should try to adopt a style
with which other C and C++ programmers are comfortable,
familiar or that they will at least recognize.
Personally, I try to use the same punctuation rules
that are used for ordinary (mathematical) typesetting.
Here are my recommendations :
Terminators always follow immediately after an expression
x@ for all @ in {?, :, ,, ;}
and are followed by at least one white space.
Write
x? y: z
instead of
x ? y : z
or
x?y:z
and write
void f(int, int, int); void g(double);
instead of
void f(int,int,int); void g(double);
for example.
There is no space
between some binary operators and their operands
x@y for all @ in {::, ., ->, .*, ->*, *, /, %, &, ^, |}
but there is always a space
between other binary operators and their operands
x @ y for all @ in {+, -, <<, >>;, <, <=, >, >=, ==, !=,
&&, ||, =, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^=}
except when expressions appear as subscripts.
Write
x + y
instead of
x+y
and
x*y
instead of
x * y
for example.
But you may wish to write
A[i+1][j-1]
instead of
A[i + 1][j - 1]
for example to subscript array A.
Most unary prefix operators never have any whitespace
between themselves and their operands
@x for all @ in {::, ++, --, ~, !, -, +, &, *}
but others do
@ x for all @ in {sizeof, new, delete, delete [], throw}
No unary postfix operators
x@ for all @ in {[], (), ++, --}
ever have any whitespace between themselves and their operands.
Use the normal typesetting rules for parentheses (),
square brackets [], angle brackets <> and curly brackets {}.
No space after (, [, < or { and no space before ), ], > or }.
Write
(x)
instead of
( x )
or
(x )
or
( x)
and write
[x]
instead of
[ x ]
or
[x ]
or
[ x]
for example.
There are, of course, exceptions
where extra white space helps to make your code more readable:
double A[2][3] = {{ 1, -1, 0},
{-10, 11, -21}};
Don't give identifiers cryptic, mangled names.
Use ordinary, meaningful words, conventional symbols
or abbreviations with annotations.
Write
double distance, velocity, acceleration, mass, Force;
Force = mass*accelerati on;
or
double x; // distance
double v; // velocity
double a; // acceleration
double m; // mass
double F; // force
F = m*a;
for example.
Don't rely on defaults. Make declarations explicit.
Write
int i = 1;
instead of
i = 1;
to declare and initialize integer i and write
class X {
private:
// Representation
int I;
public:
// Constructors
// ...
};
instead of
class X {
// Representation
int I;
public:
// Constructors
// ...
};
to define the private data members of class X for example.
Use indentation to emphasize scope.
Everybody is comfortable with standard indentation:
void f(void)
{
// indent
}
But I indent curly brackets to the scope of the function body:
void f(void)
{
// indent
}
And I include the open curly bracket with the function heading:
void f(void) {
// indent
}
to save a line of code.
I always indent just two spaces at a time and
I place just one statement on each line so that
there is usually room for a comment at the end of each line
beginning in column 33 or 41.
Write
if (condition) {
// statements
}
instead of
if(condition) {
// statements
}
and
while (condition) {
// statements
}
instead of
while(condition ) {
// statements
}
to distinguish flow control structures from function calls.
I use
// comment
for comments in C++ and I reserve
/*
a = b;
// comment
b = c;
*/
to comment out code which may include comments.
If you find yourself in an environment
that requires you to conform to style rules with which you are not
comfortable,
consider investing a little time and effort in a program like astyle
Artistic Style
http://astyle.sourceforge.net/
which changes the appearance of C or C++ programs
by inserting or deleting whitespace.
Write
constant == variable
instead of
variable == constant
when comparing a variable to a constant for equality
so that if you write
constant = variable
by mistake, the compiler will detect the error.
I always write
x < y
or
x <= y
instead of
y > x
or
y >= x
when comparing two values so that the expression is true
when the left hand side is to the left of the right hand side
on the real number line.