Re: Debian coding style?
uwd38znr@umail.furryterror.org (Amy Fong) writes:
* Compiling: all code must compile clean at warning level 3 with warnings
as errors.
`gcc -Wall -W -Werror' is what I use for my own code.
2. Testing: all code must be compilable, tested, and DIFF'ed before being
checked into source safe. No code should ever be checked in if it will break
functionality in another part of the program, or if it will break the build.
This isn't exactly what we do in unstable branches of programs. We
only try to do this in `stable' branches--i.e., where only bug fixes
are allowed.
All code must be tested by the developer before being checked in. This
includes walking through the code using a debugger and forcing error
conditions to make sure that all code paths have been tested. Remember that
the person who is most qualified to test any piece of code is the person who
wrote it.
This is a good idea, but we don't enforce testing. I do recommend it.
3. Tabs should be set to 2, and they should be kept as tabs, no spaces
please.
2-character tabs? That will break all standard Unix utilities.
4. Code width: The complete line of code should be visible without having to
scroll horizontally - i.e. it should normally not pass the 78th column.
Fine with me. Although I use a 132-column screen, I do the same thing.
5. Naming conventions:
a) Class names always start with upper-case 'C', followed by an upper-case
letter, followed by mixed upper/lower case and must always take the form of
a descriptive noun.
eg. class CPhoneBookEntry
GNU style prefers phone_book_entry over this camelcapped style.
b) Method/function names always start with upper-case followed by mixed
upper/lower case and must always take the form of a descriptive verb or
action.
eg. void CPhoneBookEntry::GetUserName();
void phone_book_entry::get_user_name().
c) Variable names must use hungarian notation (see below) followed by
upper-case followed with mixed upper/lower case and must always take the
form of a descriptive noun. Variables which are members of a class must have
m_ prepended to the name.
eg. int nUsageCount;
char* m_pstrUserName;
Hungarian Notation:
m_ member variable
ch char
n int, unsigned int
s short, unsigned short
l long
u unsigned
b bool
d double
f float
a array of
str, sz any string (str preferred for new code)
e enumerated type
id integer ID of a control, resource, etc.
p pointer to
c, o generic C++ object
h handle
k constant value
g global
I don't like Hungarian notation. I haven't ever seen anyone use it
outside of Windows-specific code.
* Magic numbers must not be embedded directly in the source code. Use a
const int variable to hold the magic number rather than a #define.
Good.
7. Comments : Please comment your code, it makes everyone's life easier.
Comment major
blocks of code explaining what you are about to do (or expect to do). Pay
special attention to cases where the code was written a specific way to work
around a problem, etc. Don't be afraid to be verbose, but please make sure
that whatever comments you use really do add value. Remember that comments
are not a replacement for well written and easily understood code. Rather,
they are meant to augment the code by detailing information which may not be
immediately apparent by looking at the code.
[...]
GNU standards recommend capitalizing the first letter of a sentence in
comments and ending sentences with a period. I prefer this style,
too.
Also, please always use C-style /* */ comments in header files that
can be included in a C program, since otherwise a C compiler can't
read them, only a C++ compiler can.
8. File level comments are to be included in all source and header files.
Module name, author, a general description of the code or class contained in
the file, and a copyright notice should be included as per the sample below.
The leading and trailing lines (with all the asterisks) should be 78
characters long to serve as a reference ruler for gauging the length of code
lines.
//****************************************************************************
//
// Module: mntlist.h
//
// Author: Andy Bounsall
//
// Description: definition of class CFccMountList which maintains a list of
// CFccMountItems representing all mountable branches of the
// file system.
//
// Copyright 1998 Corel Computer Corp. All rights reserved.
//
//****************************************************************************
I deleted spurious newlines above
The correponding GNU comment is something like this:
/* PSPP - computes sample statistics.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
9. Function level comments are to be included for all functions/methods.
Function/method name and a general description of the purpose of the
function should be included as per the sample below. The leading and
trailing lines (with all the asterisks) should be 78 characters long to
serve as a reference ruler for gauging the length of code lines.
//***************************************************************************
//
// Method: OpenCamera()
//
// Purpose: Tries to open a device driver and, if successful, sends an
// OPEN_CAMERA IOCTL request to initialize the device with the
// desired video mode.
//
//***************************************************************************
GNU recommends not naming the function in the comment. After all,
unless the comment is really long, you should be able to see the
function and the comment at the same time. In my opinion, the above
is too wasteful of vertical space.
Corresponding GNU comment:
/* Tries to open a device driver and, if successful, sends an
OPEN_CAMERA IOCTL request to initialize the device with the desired
video mode. */
10. Function/method size: bigger is not better. Functions and methods should
be kept to a maximum of 40-50 lines. Larger methods should be broken down
into several smaller methods.
I hope that's not a strict rule. Sometimes functions must be large.
It's a good principle though.
11. Curly braces
[...I'm not even going to touch that holy war...]
13. Assertions and debug only code should be used liberally to check for
validity of all pointers; range/value validation of function and method
parameters; assumed states, conditions, etc., etc. The assert() macro is
your friend - make use of it to validate assumptions, but don't try to use
it as a replacement for handling runtime errors. (If you're not sure how to
properly use assertions, please ask your PL). The assert() macro compiles to
nothing in Release builds (i.e. when NDEBUG is undefined). Debug code other
than these macros should be bracketed within #ifndef NDEBUG ... #endif
conditionals so that it is excluded from Release builds.
Sounds good.
14. Compilation conditionals, with the exception of debug code noted above,
should be avoided since they make the source code difficult to read and
maintain. Old or unwanted code should be deleted from the source files prior
to check-in. Source safes history feature can be used to retrieve an old
version of the file if the old code is ever required again.
Okay.
15. Duplicate blocks of code should be avoided. If the same code is needed
in more than one location, place it in a separate function and call it from
where ever it's needed.
Yes.
16. Goto statements should not be used.
Sometimes they're helpful. Do a Dejanews search on comp.lang.c to
find out why; I'm a regular there, and you should be able to find me
defending their use in certain cases that come up from time to time.
17. Return: functions and methods should be structured to have a single
return.
Ugh. Same as 16.
18. Switch statements must always handle the default: case. If all expected
cases have otherwise been handled, the default: case should force an
assertion failure.
Good, this is my style too.
Case statements should be indented by 1 tab and separated
from each other by 1 blank line. Code within each case should be kept to a
minimum - i.e. call a function from the case statement if more than a few
lines of code are needed.
Not touching that.
19. Comparisons for equality against a constant value should list the
constant value first. Its easy to miss one of the equals signs - this way
the compiler will catch it if you do.
eg. if (-1 == m_nResult) rather than if (m_nResult == -1)
I thought you turned up the warning level on your compiler anyway? It
should catch things like that for you.
20. Header files must not include other header files (to prevent header file
bloat). Use forward class references to inform compiler of required data
types.
I don't like that rule; it's too strict. Nested headers are useful
sometimes, although they're not always advisable.
21. Filenames: source files should have .cpp extension. Header files should
have a .h extension.
Most Debian source code is written in C, not C++. Much Debian C++
code has .cc extension, not .cpp.
All filenames should be created using only lower case
characters. All filenames in #include statements should also be
written in lower case. Source and header files should normally
reside in the same directory. Large projects should be split up
into smaller sub-projects to keep the number of source files in
each directory manageable.
Good practice.
22. Localization: text which will be visible to the user should never be
embedded within the source code. All string literals should be placed in a
separate header file to ease the pain of possible future translation.
That is not the Unix style. Unix is a multi-user OS, and users expect
to be able to choose their preferred language at runtime. Using the
above technique would force the program to be recompiled to change the
language choice.
Instead, Unix software uses runtime substitution of string literals to
do translations, using an internationalization library. Often, this
just means that instead of writing
printf ("This is some text to be i18n'd.\n");
you must write
printf (_("This is some text to be i18n'd.\n");
where _(...) is a call into the internationalization library.
[...C++ stuff...]
I'm not a C++ expert so I'll let those comments slide.
26. const modifier is to be used where ever possible, for pointer/reference
parameters and return values and for methods which do not modify the class.
Yes, good. gcc has an option to give string literals const char *
type, which can be useful.
[...more C++ stuff...]
You should take a look at the GNU Coding Standards. I think that
others have given you pointers to them, so I won't tell you again.
Thanks,
Ben.
Reply to: