summaryrefslogtreecommitdiff
path: root/docs/style-guide.html
blob: d0881c5ed32706e3fcc8d9184f0709d6887aa7de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<html>

<head>
<title>Nautilus Coding Style Guide</title>
</head>

<body>

<p>To make code written for Nautilus look and act in a predictable way,
we follow a set of guidelines that specify some details of how we write code.
To start, we follow all the guidelines outlined in the
<a href="http://developer.gnome.org/doc/guides/programming-guidelines/">GNOME Programming Guidelines</a>.</p>

<p>This document covers both things that are not mentioned in the GNOME
Programming Guidelines and things that are mentioned there but need
to be re-emphasized because people don't follow them often enough.</p>

<p>I'm just getting started on this document. Feedback is welcome.
Eventually I'd like better organization and tons of examples.</p>

<blockquote>
<p>- <a href="mailto:darin@eazel.com">Darin</a></p>
</blockquote>

<hr>

<p><b>We use the most-recommended coding style from the GNOME Programming
Guidelines.</b> This means that we use the Linux kernel brace style with
8-character tabs (not the GNU brace style), we put spaces before
the parentheses that introduce function argument lists, we put the
braces that open the block for an if statement on the same line as the
if statement (part of Linux kernel brace style).</p>

<p><b>We prefer to use words rather than acronyms or abbreviations.</b> This means that
we name classes with a prefix like Nautilus, not Ntl, for example. And we use variables
named result rather than retval or rv.</p>

<p><b>We strive to have a minimum number of local variables.</b> This makes it
easier to move pieces of code around. For more on this, read
<a href="recommended-books.html#Refactoring"><i>Refactoring</i></a>.</p>

<p><b>We use type casts as little as possible.</b> There are many places in GTK programming
where you have to cast to make the program work, but we do whatever we can
to avoid this. Also, we prefer to cast data pointers, rather than casting
function pointers, since there's so much more to get wrong with function
pointer casts.</p>

<p><b>We use typedefs from &lt;glib.h&gt; for things like guint, guchar and gpointer,
but not gint, gchar, or gdouble.</b> Using these gives a false sense
of portability. In all three cases, using system calls like printf requires
knowing that these are the "real" int, char, and double, so there's no reason
to use a typedef that's non-standard unless it's a shorter name or clearer
in some way.</p>

<p><b>We avoid in-band signaling.</b> This means that we avoid using special
values to indicate errors, for example. This can lead to subtle bugs when a valid
result is misinterpreted as an error, and can make it hard to tell if the code
handles errors or not.</p>

<p><b>We code for clarity first.</b> Other concerns like efficiency are secondary.
Sometimes they become more important than clarity, but only once they are proven
to be a problem.</p>

<p><b>We use for loops when they make the code easier to read.</b> The alternative
is usually to use a while loop. It's true that
"easy to read" is a subjective thing.</p>

<p><b>We declare local variables at the top of the function.</b> C allows you
to declare variables at the top of any scope, like the scope in a control
flow construct like an if statement. But putting the declarations there makes
it harder to add and delete if statements, since the declarations have to move.
So we just put them all at the top of the function, usually in the order that
they are used in the function.</p>

<p><b>We do not initialize local variables in their declarations.</b> C allows you
to initialize a local variable when declaring it. But no other code can run before
this, because the other statements in a function must be after all the declarations.
If there are lines of code initializing the variables in the declarations, it can
be harder to change the function around, since code must move down from the declaration
if other code needs to run after it. To avoid this, we just don't use the ability
to initialize the variable when it's declared.</p>

<p><b>We always use braces, even for one-statement "blocks".</b> Our consensus is
to do things like this:</p>

<blockquote>
<pre>
if (list != NULL) {
        g_warning ("the list isn't empty");
}
</pre>
</blockquote>

<p>Instead of this:</p>

<blockquote>
<pre>
if (list != NULL)
        g_warning ("the list isn't empty");
</pre>
</blockquote>

<p>This applies to all control structures: if, while, for, do.</p>

<p><b>We make each header "stand alone".</b> Our concept with C header files is
that each one must be written so it can be included without including another file
first. To test that the header files we develop have this property, we always
include the corresponding header file first in each C source file. The only exception
is the include of &lt;config.h>, which goes first. Here's an example:</p>

<blockquote>
<pre>
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
 *
 * nautilus-icon-factory.c: Class for obtaining icons for files and other objects.
 *
 * Copyright (C) 1999, 2000 Red Hat Inc.
 * Copyright (C) 1999, 2000 Eazel, Inc.
 *
 * <i>License agreement goes here.</i>
 *
 * Author: John Sullivan &lt;sullivan@eazel.com>
 */

#include &lt;config.h>
#include "nautilus-icon-factory.h"

#include &lt;string.h>
#include &lt;stdio.h>
<i>Include statements for other header files go here.</i>

<i>Other declarations and code go here.</i>
</pre>
</blockquote>

<hr>

</body>

</html>