~agateau/unity-2d/edge-reveal

246.1.1 by Aurelien Gateau
Added coding guidelines
1
Coding Style
2
============
3
4
5
Naming
6
------
7
246.1.2 by Aurelien Gateau
More recommendations.
8
We try to follow Qt naming convention whenever possible:
9
246.1.1 by Aurelien Gateau
Added coding guidelines
10
Classes are CamelCase.
11
12
Variables are camelCase.
13
14
Files are lowercase.h and lowercase.cpp.
15
16
Members of a class are prefixed with "m_".
17
Rationale: When reading the code of a method, it makes it easy to know whether
18
a variable is a local or a member variable.
19
246.1.2 by Aurelien Gateau
More recommendations.
20
Accessors are named foo() (not getFoo())
21
Setters are named setFoo(...)
22
246.1.1 by Aurelien Gateau
Added coding guidelines
23
24
Formatting
25
----------
26
27
Indentation is 4 spaces, no tabs.
28
29
Opening braces are on the same line as the code, except for classes and
30
functions. Example:
31
32
class Foo
33
{
34
public:
35
    void method();
36
}; 
37
38
void Foo::method()
39
{
40
    if (something()) {
41
        doThis();
42
        doThat();
43
    }
44
}
45
46
Rationale:
47
Having opening braces on the same line ensure we can put more code
48
on a screen. For some reason it seems people highly dislike having opening
49
brace on the same line as class definitions and function implementations, hence
50
they are on their own line in this case.
51
52
Even one-line blocks should be enclosed in braces.
53
54
Do not do that:
55
56
    if (something())
57
        doThis();
58
    else
59
        doThat();
60
61
    for (int x=0; x < 10; ++x)
62
        inLoop(x);
63
64
Do this:
65
66
    if (something()) {
67
        doThis();
68
    } else {
69
        doThat();
70
    }
71
72
    for (int x=0; x < 10; ++x) {
73
        inLoop(x);
74
    }
75
76
Rationale: always having braces is only one line longer and avoids mistakes like that:
77
78
    if (something())
79
        doThis();
80
    else
81
        doThat();
82
        doThatAsWell(); // Always executed, but author probably wanted it 
83
                        // to be run in the else part only
84
85
It also avoids cluttering diffs with the add/removal of braces.
86
87
88
Best Practices
89
==============
90
91
92
Pass arguments by const references instead of values
93
----------------------------------------------------
94
95
Even if some Qt classes like QString are implicitly shared and meant to be used
96
like built-in types, they should be passed as const references instead of
97
values. Do not do that:
98
99
class Foo
100
{
101
    void method(QString);
102
};
103
104
Do this:
105
106
class Foo
107
{
108
    void method(const QString&);
109
};
110
111
Rationale:
112
- It is still faster to pass a reference than to call a constructor
113
- It helps reducing the amount of #include in header files (see "Clean
114
  Headers")
115
- Qt does it this way, so it must be right! ;)
116
117
246.1.4 by Aurelien Gateau
Added a section about const correct-ness
118
Const correctness
119
-----------------
120
121
If a method does not modify an object, mark it const. This is important for (at
122
least) two reasons:
123
- It can potentially help the compiler to produce more efficient code (if the
124
  code is in another .o the compiler has no way to know whether a method is
125
  going to modify an object)
126
- It makes it possible to call this method on a const ref or a const pointer.
127
  For example:
128
129
class Foo
130
{
131
public:
132
    int computeSomething() const;
133
};
134
135
void someOtherFunction(const Foo& foo)
136
{
137
    int result = foo.computeSomething();
138
}
139
140
If computeSomething() had not been declared const, someOtherFunction() would
141
not build.
142
143
246.1.1 by Aurelien Gateau
Added coding guidelines
144
Clean Headers
145
-------------
146
147
Header files should contain the minimum amount of #include.
148
149
This can be done by using forward declarations of classes, passing const
150
references instead of values or using pimpls (see "Pimpls").
151
152
Reducing includes speeds up compilation time because it avoids propagating
153
changes. Consider these files:
154
155
    // a.h
156
    #include <b.h>
157
158
    class A
159
    {
160
        // ...
161
    private:
162
        void function(B);
163
    };
164
165
    // c.cpp
166
    #include <a.h>
167
    ...
168
    
169
When a change is made in b.h, c.cpp has to be rebuild even if it is only used
170
in the private part of the A class.
171
172
If a.h is changed to:
173
174
    class B;
175
176
    class A
177
    {
178
    public:
179
180
    private:
181
        void function(const B&);
182
    };
183
184
Then c.cpp won't be rebuilt when b.h changes.
185
186
Having clean headers also avoids propagating other component include paths. In
187
the previous example, if b.h is in a different installed dir, then c.cpp has to
188
be build with the include path to find b.h, even if it does not need it.
189
190
191
Pimpls
192
------
193
194
Pimpl stands for "Private Implementation". The idea is to put all private code
195
in an opaque class, like this:
196
197
// foo.h
198
class FooPrivate;
199
class Foo
200
{
201
public:
202
    Foo();
203
    ~Foo();
204
205
private:
246.1.3 by Aurelien Gateau
Fixed wrong class name in Pimpl example
206
    FooPrivate* const d;
246.1.1 by Aurelien Gateau
Added coding guidelines
207
};
208
209
// foo.cpp
210
class FooPrivate
211
{
212
public:
213
    int m_abc;
214
    QString m_def;
215
}
216
217
Foo::Foo()
218
: d(new FooPrivate)
219
{}
220
221
Foo::~Foo()
222
{
223
    delete d;
224
}
225
226
Rationale:
227
- It makes it possible to add/remove private members to a class without
246.1.2 by Aurelien Gateau
More recommendations.
228
  breaking binary compatibility (BC). This is *very* important for libraries.
246.1.1 by Aurelien Gateau
Added coding guidelines
229
- It helps reducing compilation time because modifying the private part of a
230
  class only requires changes in the .cpp file.
231
232
Drawback:
233
Slots cannot easily be put in a pimpl so they must still be private members of
234
the class (but adding/removing them does not break BC).
235
236
Note: Using "d" as the name of the pimpl is common practice in Qt and KDE code
237
(It stands for "data" IIRC).
238
Being a one letter variable reduces the cluttering when public and protected
239
code accesses private members and methods.
240
241
242
QT_NO_KEYWORD
243
-------------
244
245
Qt provides two ways to define signals/slots:
246
247
class Foo
248
{
249
    Q_OBJECT
250
signals:
251
    void somethingHappened();
252
public slots:
253
    void doSomething();
254
};
255
256
class Foo
257
{
258
    Q_OBJECT
259
Q_SIGNALS:
260
    void somethingHappened();
261
public Q_SLOTS:
262
    void doSomething();
263
};
264
265
The first version is problematic because "signals" is actually a #define for
266
"protected". This can cause build failures with at least some of the latest gio
267
stuff, which has a structure containing a field named "signals".
268
269
To avoid this, one can build with the QT_NO_KEYWORD #define, which disable the
270
"signals" and "slots" #defines. Instead one has to use Q_SIGNALS and Q_SLOTS.
271
272
We should ensure our code builds with the QT_NO_KEYWORD #define.