summaryrefslogtreecommitdiffstats
path: root/kicker/HACKING
blob: c03925cdc9a1b1af439c7601cff39fb1b35e79b2 (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
The Short Story
---------------
Four space tabs, braces on their own lines, 80 character lines.
Code should look something like this:

QString ExtensionManager::uniqueId()
{
    QString idBase = "Extension_%1";
    QString newId;
    int i = 0;
    bool unique = false;

    while (!unique)
    {
        ++i;
        newId = idBase.arg(i);

        unique = true;
        ExtensionList::iterator itEnd = _containers.end();
        for (ExtensionList::iterator it = _containers.begin();
             it != itEnd;
             ++it)
        {
            if ((*it)->extensionId() == newId)
            {
                unique = false;
                break;
            }
        }
    }

    return newId;
}

Full Explanation
----------------
As of 2004 kicker's codebase isn't the prettiest thing in the world. It's seen
a lot of work over a number of years without any sort of consistent coding
style being enforced. We are attempting to change this and bring some order
and consistency to the codebase.

You may (will) notice that there are many discrepencies between the current
code base and this document. All new development should follow the coding style
as described below and one day the codebase will actually be consistent! Also
feel free to clean up the code around code you work on. For example, if you
change a number of lines in a method, reindent the whole method while you
are in there. However, wholescale reformatting of code is not appropriate.
This would make `cvs log` and `cvs ann` far less useful and that information
is even more important than re-indenting old code.

General Principles
------------------
Never use modal dialogs in kicker. This blocks EVERYTHING else in the kicker
UI, not just whatever bit of code has popped up the dialog. Since kicker is
one of the primary means for the user to interact with their desktop
environment, kicker must *always* be available for the user.

NULL vs 0
---------
The use of 0 to express a null pointer is preferred over the use of NULL.
0 is not a magic value, it's the defined value of the null pointer in C++.
NULL, on the other hand, is a preprocessor directive (#define) and not only is
it more typing than '0' but I find preprocessor directives less elegant.

    SomeClass* instance = 0;

Naming Conventions
------------------
Class names start with a capital letter, member variables begin with m_.
Methods and functions start with a lower case letter.

Names should be descriptive. If you can't tell what a variable or a method
does by its name, the name is wrong. Saving a dozen keystrokes today by
using cryptic variable names will only lead to maintenance headaches tomorrow.
Names longer than 20 characters is probably going overboard, however. Just
use your best judgement.

Singletons will use a static method called the() to return the instatiated
object.

Use 'true' and 'false', not 'TRUE' and 'FALSE'

Comments
--------
Code should be written with enough clarity that comments are not needed
above each line. However, if the code does something in a particular way
for a specific reason that may not be obvious to the next person who has to
work on it do provide a short comment describing what it does and why.

Excessive commenting should be avoided since if there are too many comments
they tend to get ignored and won't be maintained, causing the comments and
the actual code to drift apart. Innacurate comments are worse than accurate
comments!

While using the /* style */ of comments is ok, comments should use // wherever
possible.

Comments can also provide notes for future work, including:

    // TODO: this is a todo item
    //       and should explain the todo in detail

    // BIC: this is a binary incompatible change, or a massive change that
    //      should wait until we are doing massive things like breaking binary
    //      compat

    // BUG: this is documenting a bug. It is preferred that they are fixed.
    //      but if you don't fix it, at least document it to save the next
    //      person some time in tracking down the problem.

Indenting
---------
Tabstop is 4 spaces. No tabs, only spaces.

Try to keep lines under 80 characters in width. When wrapping a single
logical line of code across multiple lines, new lines should be indented
at least once and should preferably line up with parentheses, if any, on
the line above. e.g.:

    someMethod(parameterOne, parameterTwo,
               parameterThree, parameterFour);

If a boolean expression is spread out over several lines, the boolean
operator is always the last item on the line, e.g.:

    if ((condition1 || condition2) &&
        condition3 &&
        (condition4 || condition5))
    {

Switch statements should have the case line indented and the case block
itsel further indented, e.g.:

    switch (condition)
    {
        case 1:
            ...
            break;
        case 2:
            ...
            break;
        default:
            ...;
    }

Spaces
------
A single space should appear between keywords and parentheses, eg:

    if (
    while (
    for (

No spaces appear between function/method names and parentheses:

    function(
    someObject->method(

No spaces appear between opening closing parens and the arguments:

    for (int i = 0; i < count; ++i)

Spaces appear between operators, e.g.:

    int i = i + 3;
    someObject.setValue(someObject.currentValue() + 1)


Braces
------
Braces always appear on a line by themself, indented to align with the
above keyword:

    if (foo)
    {
        ...
    }
    else
    {
        ...
    }

Unless it uglifies the code, use braces even for one-liner conditionals:

    if (foo)
    {
        return 1;
    }

Always use braces if the conditional expression wraps across multiple
physical lines.

Braces around case blocks in switch statements are optional.


Constructors
------------
Constructors are written as:

    MyClass::MyClass(...)
        : SuperClass(...),
          m_member1(...),
          m_member2(...),
          ...
    {


Class Definitions
-----------------
Class definitions will follow the following order:

    class <name> : <scope> <superclass>
    {
        <macros[1]>
        <typedefs>

        public:
            <ctors>
            <dtors>
            <operators>
            <other methods>

            <members>

        public slots:
            <methods>

        signals:
            <methods>

        protected:
            <ctors>
            <dtors>
            <operators>

            <members>

        protected slots:
            <methods>

        private:
            <ctors>
            <dtors>
            <operators>

            <members>

        private slots:
            <methods>
    };

Methods implementations may be in the class definition if doing so will
result in a measurable performance enhancement (e.g. it is called very often
from tight loops or is in a hot path) or if it is a simple, one-liner
setter/getter method. Otherwise methods should be implemented outside of
the class definition.

[1] macros include things like Q_OBJECT and K_DCOP. the should ONLY appear in
files where they are actually necessary and not just randomly thrown in there
for fun. ;-)