0
|
1 |
Galadriel coding style
|
|
2 |
|
|
3 |
Lluís Batlle i Rossell
|
|
4 |
viric@vicerveza.homeunix.net
|
|
5 |
|
|
6 |
Iniciat el 11/08/2003
|
|
7 |
|
|
8 |
|
|
9 |
Aquest és un petit document que descriu l'estil d'escriptura de codi pel
|
|
10 |
projecte Galadriel. L'estil d'escriptura és molt personal, i no s'han de forçar
|
|
11 |
aquestes idees sobre ningú, però ja que és una cosa que hem de mantenir entre
|
|
12 |
tots, seria bo que l'estil no ens dificultés aquesta feina. Així que, si més no,
|
|
13 |
tingueu en compte els punts que aquí es mencionen.
|
|
14 |
|
|
15 |
Aquest document no està ni revisat ni acabat. En alguns llocs hi ha comentaris
|
|
16 |
de la forma (MAJUSCULES ?!), que significa que no sé què posar-hi, i algú de
|
|
17 |
vosaltres segur que ho sabrà millor i abans que jo.
|
|
18 |
|
|
19 |
Aquest document també està molt influenciat per la guia de Linus Torvalds:
|
|
20 |
"Linux kernel coding style". El google us donarà la referència a aquest escrit.
|
|
21 |
|
|
22 |
Espero comentaris ben aviat...
|
|
23 |
|
|
24 |
|
|
25 |
1. Indentació (sagnat)
|
|
26 |
|
|
27 |
Els tabuladors estan pensats per ser d'una longitud de 8 caràcters. Si volem
|
|
28 |
respectar a la resta de món, aquest és l'esquema que hauriem de seguir. Però
|
|
29 |
segur que s'aixecarà protestant molta gent si pretenem tabulacions d'aquesta
|
|
30 |
mida. Això és perquè molta gent troba excessius 8 caràcters per a indentar; bé,
|
|
31 |
indentar serveix per diferenciar quan comença i acaba un bloc de control, així
|
|
32 |
que si fem indentacions grans diferenciarem molt més aquests blocs, sobretot
|
|
33 |
quan alguns de nosaltres portem més de 15 hores davant de codi.
|
|
34 |
|
|
35 |
Molts direu, tot i això, que 8 caràcters és una indentació massa gran, i que
|
|
36 |
mouen el codi massa cap a la dreta... bé, tal com diu el senyor Torvalds, "if
|
|
37 |
you need more than 3 levels of indentation, you're screwed anyway, and should
|
|
38 |
fix your program". Això vol dir que utilitzar 8 caràcters també ens dóna una
|
|
39 |
idea de quant bo és el nostre codi.
|
|
40 |
|
|
41 |
Fer servir tabuladors de menys de 8 caràcters també porta problemes entre
|
|
42 |
editors... sobretot per discernir quan s'indenta amb tabuladors o bé amb espais.
|
|
43 |
|
|
44 |
De tota manera, podem justificar l'ús d'indentacions més petites perquè no és el
|
|
45 |
mateix escriure en C++ que amb C; sembla una excusa, però és amb l'únic que ens
|
|
46 |
podem recolzar. Queda doncs establert, tal com es va decidir a l'explicació d'en
|
|
47 |
Shadow el dissabte, que s'utilitzarà indentació amb espais de 3 caràcters.
|
|
48 |
|
|
49 |
|
|
50 |
2. Ample de pantalla
|
|
51 |
|
|
52 |
Molts utilitzem GUIs per escriure el nostre codi, i el fet d'estar allunyat de
|
|
53 |
l'antic mode de 80x25, tenir resolucions més grans i fonts més petites ens ha
|
|
54 |
permès arribar a pantalles de 170x60. De tota manera, tot i que ens pensem que
|
|
55 |
la majoria de gent ja utilitza resolucions superiors a 1024x768, no és bo
|
|
56 |
imposar als programadors la nostra manera d'escriure codi. Encara són molts els
|
|
57 |
que programen en 80x25, més que res perquè són les dimensions dels terminals més
|
|
58 |
comuns. Són amb la que els terminals VT servien les lletres més grans
|
|
59 |
(ideals per programadors cansats), les que ens dóna la BIOS abans de l'arrencada
|
|
60 |
del sistema, i la de la majoria d'emuladors de terminal de X. A més a més,
|
|
61 |
facilita molt el tenir diferents porcions de codi a la pantalla alhora. I donat
|
|
62 |
que suposem que tothom disposa de monitors de diagonal poc superior a 14", les
|
|
63 |
mides de caràcter no són massa petites per passar llargues hores davant la
|
|
64 |
pantalla.
|
|
65 |
|
|
66 |
|
|
67 |
3. Claus {}
|
|
68 |
|
|
69 |
Un altre assumpte que sol portar confusions i incomoditats només perquè hi ha
|
|
70 |
diferents estils d'escriptura de codi és la col·locació de les claus d'inici i
|
|
71 |
fi de bloc. Seguint les indicacions de Kernighan i Ritchie, l'estil preferit és
|
|
72 |
el de posar la clau d'obertura a final de línia, i la de tancament indentada a
|
|
73 |
la mateixa columna que el que ha iniciat el bloc:
|
|
74 |
|
|
75 |
if (x == 1) {
|
|
76 |
printf("Hola");
|
|
77 |
}
|
|
78 |
|
|
79 |
Tot i això hi ha un cas especial, les funcions. Tenen la clau d'obertura a
|
|
80 |
l'inici de la següent línia, així:
|
|
81 |
|
|
82 |
int funcio(int x)
|
|
83 |
{
|
|
84 |
return 2*x;
|
|
85 |
}
|
|
86 |
|
|
87 |
A molts no ens agrada aquesta aquesta inconsistència, però té una justificació:
|
|
88 |
les funcions no es poden aniuar. El fet d'utilitzar sempre l'obertura de clau a
|
|
89 |
la pròxima línia també fa que en aquesta línia no hi hagi res més escrit mai, i
|
|
90 |
porta a problemes de lectura, com en els casos:
|
|
91 |
|
|
92 |
do
|
|
93 |
{
|
|
94 |
printf( "%i\n", i );
|
|
95 |
}
|
|
96 |
while( i < 10 );
|
|
97 |
|
|
98 |
o bé,
|
|
99 |
|
|
100 |
if( i > 10 )
|
|
101 |
{
|
|
102 |
printf( "i gran\n" );
|
|
103 |
}
|
|
104 |
else
|
|
105 |
{
|
|
106 |
printf( "i petita\n" );
|
|
107 |
}
|
|
108 |
|
|
109 |
coses que evidentment queden molt més clares així:
|
|
110 |
|
|
111 |
do {
|
|
112 |
printf( "%i\n", i );
|
|
113 |
} while( i < 10 );
|
|
114 |
|
|
115 |
o bé
|
|
116 |
|
|
117 |
if( i > 10 ) {
|
|
118 |
printf( "i gran\n" );
|
|
119 |
} else {
|
|
120 |
printf( "i petita\n" );
|
|
121 |
}
|
|
122 |
|
|
123 |
El més important és que no quedin línies buides, ja que hem de pensar en les 25
|
|
124 |
línies, a part de les 80 columnes. Al deixar menys línies buides permet
|
|
125 |
reaprofitar aquestes línies de pantalla que no perdem per a afegir comentaris.
|
|
126 |
|
|
127 |
|
|
128 |
4. Espaiat d'expressions
|
|
129 |
|
|
130 |
Les expressions poden arribar a ser molt críptiques si no estan ben espaiades (o
|
|
131 |
gens). Per tant, adoptarem la regla general de posar un espai entre cada valor
|
|
132 |
(immediat o variable) i el seu operador binari, i no posar cap espai entre un
|
|
133 |
operador unari i el valor a què afecta. Si les variables no fan servir caràcters
|
|
134 |
més enllà dels alfanumèrics, això no hauria de suposar cap problema de lectura.
|
|
135 |
|
|
136 |
El pas de paràmetres en una crida a una funció, així com a la seva definició, es
|
|
137 |
farà enganxant el parèntesi d'obertura al nom de la funció, i els paràmetres el
|
|
138 |
seguiran començant amb un espai de separació entre aquest parèntesi i el primer,
|
|
139 |
i els següents aniran succeint com si d'un text redactat es tractés. Entre
|
|
140 |
l'últim paràmetre i el parèntesi de tancament hi haurà, com en l'obertura, un
|
|
141 |
espai de separació.
|
|
142 |
|
|
143 |
En el cas de no haver-hi paràmetres, podem utilitzar () enganxat al nom de la
|
|
144 |
funció.
|
|
145 |
|
|
146 |
|
|
147 |
5. Definició de variables
|
|
148 |
|
|
149 |
Alguns caràcters especials defineixen variables com a punters o referències als
|
|
150 |
tipus de dades amb què les declarem. Considerarem que aquests caràcters no són
|
|
151 |
operadors unaris, i són una dada més alhora de definir el paràmetre. Per tant,
|
|
152 |
s'escriuran un espai després del tipus de dades a què apunten o referencien, i
|
|
153 |
separats tans espais com calgui del nom de la variable (en el cas que alineem
|
|
154 |
definicions). Això s'aplicarà tan al cos de les funcions com a la declaració
|
|
155 |
dels seus paràmetres o valors de retorn.
|
|
156 |
|
|
157 |
|
|
158 |
6. Nomenclatura
|
|
159 |
|
|
160 |
Queda clar que totes les funcions i variables han de tenir noms clarament
|
|
161 |
descriptius. Això sol implicar que aquests noms estiguin composats de més d'una
|
|
162 |
paraula. Seguint l'estil dels de QT, utilitzarem la tècnica de que les paraules
|
|
163 |
que composen el nom d'una class comencen totes amb majúscula (Amb una G
|
|
164 |
majúscula de Galadriel a davant en el codi del kernel). Els mètodes
|
|
165 |
s'escriuran igual que les classes, però amb la lletra de la primera paraula en
|
|
166 |
minúscula. Les variables, igual que els mètodes (moltes vegades, en programació
|
|
167 |
a objectes, no sabem si referenciem a mètodes o a variables. Això ha de
|
|
168 |
mantenir-se transparent).
|
|
169 |
|
|
170 |
class Tree
|
|
171 |
{
|
|
172 |
int * firstLeaf;
|
|
173 |
|
|
174 |
public:
|
|
175 |
void addLeaf();
|
|
176 |
};
|
|
177 |
|
|
178 |
En el cas de parlar de comptadors o altres estructures de codi en què l'ús de
|
|
179 |
les variables queda molt clar, podem utilitzar variables d'una sola lletra (i,
|
|
180 |
j, k, ...), preferiblement comptant per la i i sempre en minúscula.
|
|
181 |
|
|
182 |
En implementar algoritmes matemàtics també podem utilitzar variables d'una sola
|
|
183 |
lletra sempre i quan hi hagi un extens comentari amb el codi expressat
|
|
184 |
matemàticament.
|
|
185 |
|
|
186 |
|
|
187 |
7. Classes i estructures
|
|
188 |
|
|
189 |
Entenem l'idea de Classe amb C++ com a una definició d'objectes que conté
|
|
190 |
variables i -indispensablement- mètodes. Si ens trobem davant del típic ús de C
|
|
191 |
d'una 'struct', ho declararem com a 'struct'. Queda despreciada l'estructura:
|
|
192 |
|
|
193 |
class MyClass
|
|
194 |
{
|
|
195 |
public:
|
|
196 |
int a;
|
|
197 |
int b;
|
|
198 |
int * c;
|
|
199 |
}
|
|
200 |
|
|
201 |
Evidentment, només utilitzarem aquest concepte d'estructura si la idea d'una
|
|
202 |
"classe amb els seus mètodes" fa complicat l'ús d'aquestes dades. També hem de
|
|
203 |
preveure si farà o no falta una futura encapsulació; en aquest cas declararem
|
|
204 |
una classe amb mètodes senzills.
|
|
205 |
|
|
206 |
El tipus de definicions (public, protected o private, així com slots i signals)
|
|
207 |
es faran al nivell d'indentació de la funció, ja que la indentació serveix per
|
|
208 |
indicar 'blocs', i això és el que volem aquí. Podem utilitzar vàris entorns de
|
|
209 |
public, protected o private per afegir claredat a la definició de la classe,
|
|
210 |
utilitzant-los de separadors en les definicions de membres.
|
|
211 |
|
|
212 |
Quan declarem una classe també espaiarem el nom de la classe, els
|
|
213 |
dobles dos punts i el nom del mètode. Igualment amb l'herència en la definició
|
|
214 |
de classes i en la crida a constructors de la mare.
|
|
215 |
|
|
216 |
|
|
217 |
8. Mètodes senzills
|
|
218 |
|
|
219 |
És fàcil trobar-nos amb mètodes (i sobretot constructors) que simplement
|
|
220 |
assignen els valors dels paràmetres a variables privades de la classe. Per
|
|
221 |
evitar codi redundant, utilitzarem el mètode ja disponible en C i que s'ha
|
|
222 |
arrossegat fins a la crida de constructors de classes mare. Així que
|
|
223 |
utilitzarem:
|
|
224 |
|
|
225 |
void MyClass :: Constructor( int _myVar )
|
|
226 |
: mother( _myVar ), classVar( _myVar ),
|
|
227 |
{
|
|
228 |
//.... codi (si cal!)....
|
|
229 |
}
|
|
230 |
|
|
231 |
Aquestes declaracions es poden fer fins i tot (preferiblement) -inline- dins
|
|
232 |
la definició de la classe.
|
|
233 |
|
|
234 |
La nomenclatura dels paràmetres de mètodes d'aquest tipus es farà utilitzant
|
|
235 |
exactament el mateix nom que la variable interna, fet amb què s'evitarà
|
|
236 |
utilitzar caràcters no alfanumèrics en la definició de variables (o altres
|
|
237 |
invents) i s'aconseguirà l'ús de l'estructura anterior. En qualsevol altre cas,
|
|
238 |
s'utilitzaran recursos de 'namespace' per diferenciarles (que és el que realment
|
|
239 |
fem mentalment quan llegim codi que no compleix això).
|
|
240 |
|
|
241 |
|
|
242 |
9. Funcions
|
|
243 |
|
|
244 |
Igual que amb l'indentació, hem d'evitar les funcions amb molts de paràmetres,
|
|
245 |
ja que la definició i les crides ocuparien moltes columnes.
|
|
246 |
Això significa que la funció és molt complexa; s'ha de derivar en funcions més
|
|
247 |
senzilles. Qualsevol ha de poder entendre una funció pel seu nom, i qualsevol
|
|
248 |
funció ha de ser prou senzilla com per ser reutilitzada al màxim. En casos en
|
|
249 |
què necessitem un codi molt ràpid, podem demanar al compilador que ens posi les
|
|
250 |
funcions 'inline'.
|
|
251 |
|
|
252 |
Una funció ha de ser prou senzilla com per tenir poques variables locals. Masses
|
|
253 |
variables locals indiquen que estem fent una funció que fa masses coses. Hem de
|
|
254 |
tenir en compte que una funció és una cosa que el nostre cap ha de poder
|
|
255 |
entendre al 100% en un mateix instant; no val a haver d'entendre el codi d'una
|
|
256 |
funció per parts. El límit de variables locals el posa el nostre cervell.
|
|
257 |
A més, sempre ens ho hem d'imaginar amb la perspectiva amb què veiem un codi fet
|
|
258 |
fa dues setmanes, no amb la del moment d'escriure'l.
|
|
259 |
|
|
260 |
|
|
261 |
10. Comentaris
|
|
262 |
|
|
263 |
És molt bo que hi hi hagi comentaris en el que escrivim, sobretot per
|
|
264 |
ajudar-nos a entendre què fa un tall de codi. Això és molt important si volem
|
|
265 |
agafar una idea de com resol un problema una funció, sense haver d'entendre al
|
|
266 |
100% com ho fa.
|
|
267 |
|
|
268 |
És molt típic el problema de posar més comentaris del compte, sobretot en
|
|
269 |
programadors novells. Només s'ha de tenir en compte una regla: no expliqueu COM
|
|
270 |
resol el problema el vostre tall de codi. Simplement expliqueu QUÈ resol, o fins
|
|
271 |
i tot doneu una referència a un mètode conegut. Però sobretot, no expliqueu mai
|
|
272 |
COM ho feu. El codi ha de ser prou bo com perquè el que vulgui saber COM es fa,
|
|
273 |
ho entengui llegint-lo.
|
|
274 |
|
|
275 |
(MANIES DE FER LLARGS SEPARADORS HORITZONTALS ENTRE COSES !? )
|
|
276 |
(CAPÇALERES DE FITXERS, GPL, ... )
|
|
277 |
|
|
278 |
|
|
279 |
11. Definicions i doxygen
|
|
280 |
|
|
281 |
Tots els comentaris del doxygen (així com els comentaris de mètodes, variables,
|
|
282 |
funcions, classes i enumeracions) estaran a les definicions o prototipus.
|
|
283 |
Aquests seran els més restrictius; inclouran els paràmetres per defecte, i
|
|
284 |
altres informacions sobre les funcions: virtuals, estàtiques, constants...
|
|
285 |
|
|
286 |
Tots els mètodes que siguin correctes en un objecte constant, ho indicaran. Les
|
|
287 |
definicions dels que siguin reimplementables en herència, indicaran virtualitat.
|
|
288 |
I les que no depenguin de les dades, indicaran estàtica.
|
|
289 |
|
|
290 |
(EXPLICIT ?)
|
|
291 |
|
|
292 |
Tots els mètodes i variables que puguin ser utilitzats en herència, seran
|
|
293 |
declarats sota 'protected' en comptes de 'private'
|
|
294 |
(possiblement serà en la majoria de casos).
|
|
295 |
|
|
296 |
|
|
297 |
12. Encoding
|
|
298 |
|
|
299 |
Tot el codi que escrivim ha d'estar en ASCII.
|
|
300 |
Això significa oblidar els accents i caràcters per l'estil. De tota manera, de
|
|
301 |
moment podem ser menys restrictius en els comentaris i les sortides de texte; en
|
|
302 |
aquest cas utilitzarem ISO-8859-1 (aka Latin1), i totes les sortides de texte
|
|
303 |
aniran dins del pertinent mètode estàtic 'tr' de QObject (mirar docs de QT).
|