DISCUSSION: Naming conventions (for C code)

Donald Beaudry (don@vicorp.com)
Fri, 4 Jun 93 11:51:31 EDT

What a great idea!

> The full naming scheme gives functions a name as follows:
> Py<Module>_<Function>, where <Module> is the (sometimes abbreviated)
> name of the module to which the function belongs (this may also be a
> basic type), and <Function> is a descriptive name for the function.
> The <Module> and <Function> parts use a mixed-case convention: each
> is spelled with an initial capital letter, and if they consist of
> multiple words each word has an initial capital. Embedded underscores
> are not used except between <Module> and <Function>. Some examples:

> PyList_Append
> PyList_GetItem
> PyList_New
> PyString_GetValue
> PyErr_SetStr

This is fine for all of the built in objects types but I would like to
suggest a slight variation for use with extension modules. Each
extension module should have a short abbreviation which is then
inserted between the Py and the object name. Using this convention
will allow one extention module to define objects with the same as
another extention module with out having to worry name collisions.
For example, Motif defines a string type which when wrapped by a
Python object should be called PyXmString. Any other objects added by
the Xm module should be name in a similar manner, PyXmFontList is
another example.

> Global variables are named using similar conventions, e.g.

> PyType_List
> Py_ZeroDivisionError

I suppose that we have to have a naming convention for global
variables though I believe that their use should be strongly
discouraged. Often they are unavoidable and in these cases they
should not be part of the public interface to the module in which they
are declared. Rather, they should be named with a leading underscore
to indicate that they are private to the module and the module should
provide a procedural interface to them. If performance is crucial
then this interface could take the form for a macro or two.

> Functions and variables that have to be global for some reason but are
> not part of the official interface have an initial underscore, e.g.

> _Py_RefTotal

This rule should also apply to any name that is not part of the
official interface. Often it is useful to define structure or macros
that need to be shared by the files of a module, but are of no use to
the user of the module.

> Macros with arguments are named like functions, e.g.:

> Py_IsList
> Py_IncRef

I think that the distinction here should not be based on the existance
of arguments, but on the usage of the arguments. If the macro acts
like, and can be replaced by a function then it should be named like a
function. This is an important distinction since some macros are not
very well behaved and evaluate their arguments more than once, or they
do what cannot be done by a function, like statically initialize a
structure (OB_HEAD). These non-function macros should be named
entirely in capitals with underscores seperating the words.

> Note that the current system has a number of structures that are not
> covered by typedefs. These will be given typedef names.

Good.

> Also note that pointer types will continue to be written with the "*"
> notation, e.g. "PyObject *". Pointers in C have sufficiently special
> semantics to make it important in practice to know whether a
> particular variable is a pointer; e.g. Python frequently uses casts
> between various object pointers.

Using this conventions will make it less convienent to use a very
useful information hiding trick. Often, the definition of a structure
only needs to be known within the module that uses it. The public
header file can then declare a typedef as a pointer to the structure
without specifying the structure at all. Using this convention will
either force all structure defination to be exposed in the public
header files.

I think that a better approach is to define all stuctures with a
typedef name that ends with the suffix 'Struct', (or 'Rec' as Xt
does). And then use a typedef to create a pointer type for that
structure. The name should be the same as the structure minus the
suffix. Now, header files can declare the same pointer type without
having access to the actual structure definition. It is true that
this hides the fact the the type is a pointer, but whenever the type
is used outside of the module of its defination, only the public
interface functions should be used to access the type, thus the
question of whether or not it is a pointer becomes irrelevant.

> Header files will follow the conventions for typedef names, e.g.

> "PyList.h"

I would rather see header files put into a seperate directory, for a
couple of reasons. First, it helps to keep the name of the header
file short. On many systems, this is very important. And second, it
makes it possible to distinguish public header file from private
header files. That is, only public header files will be moved
(linked, copied, whatever) into the public area. All private headers
could be kept with the source that needs them. So, include directives
would end up looking somthing like this:

#include <Py/List.h>
#include <PyXt/Widget.h>
#include <PyXm/String.h>

> A header named "Python.h" will collect almost all useful headers.

When it comes to header file inclusion, I have a simple rule that I
like to follow: "If you use it, include it." In other words, if your
source uses any of the functionality or types provided by a header
file it should explicitly include that header file. This rule also
applies to header files that use types defined in other header files.
Also, you should not assume that a given header file includes any
other header file for you. This implies that all header files should
guard against multiple inclusion by wrappign themselves in a
preprocessor directive like this.

#ifndef PyHEADER_FILE_H
#define PyHEADER_FILE_H

<text of header file>

#endif

Unnecessary inclusion of header files lead to unnecessary
dependencies. And unnecessary dependencies lead to unnecessary
compilation. Unnecessary compliations lead to unnecessarily long
compilation times. And I hate unnecessarily long compile times.

> It may be possible to introduce other changes as well, e.g. changes to
> the source tree: I might separate the .h files from the .c files,
> separate optional modules from the required part of the interpreter,
> move the parser generator to its own directory. (Anything else?)

The seperation of optional from the required would be great.

I would also like to see this as an opportunity to remove many of the
abbreviation currently in use. Sure abbreviation are easy to type but
I find them difficult to read. If used at all, I would only like to
see them on the left hand side of the underscore (assuming the naming
scheme described in the proposal) and only when that part of the name
starts to get obnoxishly long.

--Don
______ ______
\_\_\_\ /#/#/#/
\_\_\_\ ______
\_\_\_V#/#/#/ Donald Beaudry don@vicorp.com
\_\_/#/#/#/ V. I. Corporation uunet!vicorp!don
\_/#/#/#/ 47 Pleasant Street PHONE: (413) 586-4144
V#/#/#/ Northampton, MA 01060 FAX: (413) 586-3805