libs-base/Documentation/coding-standards.texi

417 lines
14 KiB
Text
Raw Normal View History

\input texinfo @c -*-texinfo-*-
@setfilename coding-standards.info
@set DATE 26 Jun 1996
@ifinfo
@format
* Coding: (coding). Coding Standards for GNUstep Libraries
@end format
@end ifinfo
@ifinfo
Copyright @copyright{} 1997 Free Software Foundation
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
@end ifinfo
@setchapternewpage odd
@settitle Coding Standards for GNUstep Libraries
@titlepage
@finalout
@title Coding Standards for GNUstep Libraries
@flushright
@value{DATE}
@end flushright
@author Adam Fedor
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1997 Free Software Foundation
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
@end titlepage
@node Top, Introduction, (dir), (dir)
@top Coding Standards
@menu
* Introduction::
* ChangeLog Entries::
* Coding Style::
* Memory Management::
* Error Handling::
* Variable Declaration::
* Object Persistance::
* Before You Commit::
* Contributing::
@end menu
@c ******************************************************************
@node Introduction, ChangeLog Entries, Top, Top
@section Introduction
This document explains the official coding standards which developers
for GNUstep should follow. Note that these standards are in addition
to GNU coding standards, not a replacement of them.
To summarize, always add a ChangeLog message whenever your commit a
change. Make sure your patch, if possible, improves the operation of
the library, not just fixes things - i.e. there are many places where
things are just hacked together from long ago and really aren't
correct. It's better to rewrite the whole thing correctly, then just
make some temporary fix.
Some particular pieces of code which may seem odd or wrong may in fact
be there for particular and obscure, but necessary reasons. If you
have questions, ask on @email{bug-gnustep@@gnu.org} or
@email{gnustep-dev@@gnu.org}.
@c ******************************************************************
@node ChangeLog Entries, Coding Style, Introduction, Top
@section ChangeLog Entries
Always include a ChangeLog entry for work that you do. Look for the
ChangeLog file in the current directory or look up to any number of
parent directories. Typically there is one for each library.
Emacs currently formats the header like this:
@example
2000-03-11 Adam Fedor <fedor@@gnu.org>
@end example
and formats changes to functions/methods like this:
@example
* Source/NSSlider.m ([NSSlider -initWithFrame:]):
@end example
to which you add your own comments on the same line (with word
wrapping). Although if you're making similar changes to multiple
methods, it's ok to leave out the function/method name.
Important: Changelog entries should state what was changed, not why it
was changed. It's more appropriate to put that in the source code, where
someone can find it, or in the documentation.
@c ******************************************************************
@node Coding Style, Memory Management, ChangeLog Entries, Top
@section Coding Style
The point is not what style is 'better' in the abstract -- it's what
style is standard and readily usable by all the people wanting to
use/work on GNUstep. A reasonably good consistent style is better for
collaborative work than a collection of styles irrespective of their
individual merits. If you commit changes that don't conform to the
project standards, that just means that someone else will have a tedious
time making the necessary corrections (or removing your changes).
The GNUstep coding standards are essentially the same as the GNU coding
standards (@url{http://www.gnu.org/prep/standards_toc.html}), but here
is a summary of the essentials.
White space should be used for clarity throughout. In particular,
variable declarations should be separated from code by a blank line and
function/method implementations should be separated by a blank line.
Tabstops should be 8 spaces.
All binary operators should be surrounded by white space with the
exception of the comma (only a trailing white space), and the
@code{.} and @code{->} structure member references (no space).
@example
x = y + z;
x += 2;
x = ptr->field;
x = record.member;
x++, y++;
@end example
Brackets should have space only before the leading bracket and after
the trailing bracket (as in this example), though there are odd occasions
where those spaces might be omitted ((eg. when brackets are doubled)).
This applies to square brackets too.
Where round brackets are used for type-casts or at the end of a statement,
there is normally no space between the closing bracket and the following
expression or semicolon-
@example
a = (int)b;
- (void) methodWithArg1: (int)arg1 andArg2: (float)arg2;
a = foo (ax, y, z);
@end example
The placement of curly brackets is part of the indentation rules. the
correct GNU style is
@example
if (...)
@{
...
@}
@end example
For function implementations, the function names must begin on column zero
(types on the preceeding line). For function predeclaration, the types and
the name should appear on the same line if possible.
@example
static int myFunction(int a, int b);
static int
myFunction(int a, int b)
@{
return a + b;
@}
@end example
The curly brackets enclosing function and method implementations should be
based in column 0. Indentation is in steps of two spaces.
@example
int
myMax(int a, int b)
@{
if (a < b)
@{
return b;
@}
return a;
@}
@end example
Lines longer than 80 columns must be split up, if possible with the
line wrap occurring immediately before an operator. The wrapped lines
are indented by two spaces form the original.
@example
if ((conditionalTestVariable1 > conditionaltestVariable2)
&& (conditionalTestvariable3 > conditionalTestvariable4))
@{
// Do something here.
@}
@end example
Some things the standards seem to think are 'should' rather than 'must':
Multiline comments should use @code{/* ... */} while single line
comments may use @code{//}.
In a C/ObjC variable declaration, the @samp{*} refers to the variable,
not to the type, so you write
@example
char *foo;
@end example
not
@example
char* foo;
@end example
Using the latter approach encourages newbie programmers to thing they can
declare two pointer variables by writing
@example
char* foo,bar;
@end example
when of course they need
@example
char *foo, *bar;
@end example
or (in my opinion better)
@example
char *foo;
char *bar;
@end example
An exception to the indentation rules for Objective-C: We normally don't
break long methods by indenting subsequent lines by two spaces, but make the
parts of the method line up instead.
The way to do this is indent so the colons line up.
@example
[receiver doSomethingWith: firstArg
and: secondArg
also: thirdArg];
@end example
That's the style used mostly in the GNUstep code - and therefore the one I
try to keep to.
Finally, my own preference (not part of the standard in any way) is to
generally use curly brackets for control constructs, event where only one line
of code is involved
@example
if (a)
@{
x = y;
@}
@end example
@c ******************************************************************
@node Memory Management, Error Handling, Coding Style, Top
@section Memory Management
In anticipation of the day when we can make the use of a Garbage Collector
possible for all GNUstep apps (it's almost-usable/usable-with-care for
non-gui apps now), the normal use of retain/release/autorelease is
deprecated.
You should always use the macros RETAIN(), RELEASE() and AUTORELEASE()
(defined in NSObject.h) instead.
There are also some extra macros that may be of use -
@itemize @bullet
@item
ASSIGN(object,value) to assign an object variable, preforming the appropriate retain/release as necessary.
@item
ASSIGNCOPY(object,value) to copy the value and assign it to the object.
@item
DESTROY(object) to release an object variable and set it to nil.
@item
TEST_RETAIN(object) to retain an object if it is non-nil
@item
TEST_RELEASE(object) to release an object if it is non-nil
@item
TEST_AUTORELEASE(object) to autorelease an object if it is non-nil
@item
CREATE_AUTORELEASE_POOL(name) to create an autorelease pool with the
specified name.
@item IF_NO_GC(X) compile the code 'X' only if GarbageCollection is not
in use.
@end itemize
@c ******************************************************************
@node Error Handling, Variable Declaration, Memory Management, Top
@section Error Handling
Initialization methods (e.g. -init) should, upon failure to
initialize the class, release itself and return nil. This may mean
in certain cases, that it should catch exceptions, since the calling
method will be expecting a nil object rather than an exception on
failure. However, init methods should endeavor to provide some
information, via NSLog, on the failure.
All other methods should cause an exception on failure*, unless
returning nil is a valid response (e.g. [dictionary
objectForKey: nil]) or if documented otherwise.
Failure here is a relative term. I'd interpret failure to occur when
either system resources have been exceeded, an operation was performed
on invalid data, or a required precondition was not met.
On the other hand, passing a nil object as a parameter (as in
[(NSMutableData *)data appendData: nil]), or other "unusual"
requests should succeed in a reasonable manner (or return nil, if
appropriate) and/or reasonable default values could be used.
If an error is recoverable or it does not damage the internal state of
an object, it's ok not to raise an error. At the very least, though, a message
should be printed through NSLog.
Special care should be taken in methods that create resources like
allocate memory or open files or obtain general system resources (locks,
shared memory etc.) from the kernel. If an exception is generated
between the allocation of the resource and its disposal, the resource
will be simply lost without any possibility to release. The code should
check for exceptions and if something bad occurs it should release all
the allocated resources and reraise the exception.
Unfortunately there is no nice way to do this automatically in OpenStep.
Java has the "finally" block which is specifically designed for this task. A
similar mechanism exists in libFoundation with the CLEANUP and FINALLY
blocks.
@c ******************************************************************
@node Variable Declaration, Object Persistance, Error Handling, Top
@section Variable Declaration
All variables should be decalred at the beginning of a block. The new
C99 standard (and gcc 3.X) allow variables to be declared anywhere in
a block, including after executable code. However, in order to be compatible
with older compilers, all GNUstep programs should keep the old behavior.
Certainly we would consider it a bug to introduce code into the
GNUstep libraries which stopped them compiling with one of the
commonly used compilers.
@c ******************************************************************
@node Object Persistance, Before You Commit, Variable Declaration, Top
@section Object Persistance
The standard method of saving and restoring object information in GNUstep
is through the use of the -encodeWithCoder: and -initWithCoder: methods.
Any object which requires persistance implements these methods. They are
used, for instance by Gorm, to save GUI interface elements. It is important
that all changes to these methods be backward compatible with previously
stored archives (for instance, those created by Gorm). The easiest way to do
this is to use class version numbers to indicate which archive configuration
should be read.
@c ******************************************************************
@node Before You Commit, Contributing, Object Persistance, Top
@section Before You Commit
@itemize @bullet
@item Make sure you have a ChangeLog entry
@item Make sure everything still compiles
@item Make sure you've tested the change as much as is reasonable.
@item If you have added a class, add the class to @file{Foudation/Foundation.h}
or @file{Appkit/Appkit.h} if appropriate.
@item If you have updated and configure checks, be sure to run both
autoconf and autoheader.
@end itemize
@c ******************************************************************
@node Contributing, , Before You Commit, Top
@section Contributing
Contributing code is not difficult. Here are
some general guidelines:
@itemize @bullet
@item
We maintain the right to accept or reject potential contributions.
Generally, the only reasons for rejecting contributions are cases where
they duplicate existing or nearly-released code, contain unremovable
specific machine dependencies, or are somehow incompatible with the
rest of the library.
@item
Acceptance of contributions means that the code is accepted for adaptation
into GNUstep. We reserve the right to make various editorial changes
in code. Very often, this merely entails formatting, maintenance of various
conventions, etc. Contributors are always given authorship credit and shown
the final version for approval.
@item
Contributors must assign their copyright to FSF via a form sent out
upon acceptance. Assigning copyright to FSF ensures that the code
may be freely distributed.
@item
Assistance in providing documentation, test files, and debugging
support is strongly encouraged.
@end itemize
Extensions, comments, and suggested modifications of existing GNUstep
features are also very welcome.
@bye