11.05.2013 Views

Guía de estilo de programación en C++ estructurado

Guía de estilo de programación en C++ estructurado

Guía de estilo de programación en C++ estructurado

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Guía</strong> <strong>de</strong> <strong>estilo</strong> <strong>de</strong> <strong>programación</strong> <strong>en</strong> <strong>C++</strong><br />

<strong>estructurado</strong><br />

Pequeños consejos sobre cómo escribir programas más legibles.


Índice<br />

1Introducción........................................................................................................................................3<br />

2Indicaciones g<strong>en</strong>erales........................................................................................................................3<br />

3I<strong>de</strong>ntificadores....................................................................................................................................4<br />

3.1I<strong>de</strong>ntificadores <strong>de</strong> estructuras.....................................................................................................4<br />

3.2I<strong>de</strong>ntificadores <strong>de</strong> campos..........................................................................................................5<br />

3.3I<strong>de</strong>ntificadores <strong>de</strong> registros.........................................................................................................5<br />

3.4I<strong>de</strong>ntificadores <strong>de</strong> funciones.......................................................................................................5<br />

3.5I<strong>de</strong>ntificadores <strong>de</strong> variables locales <strong>en</strong> funciones.......................................................................5<br />

3.6Ejemplo con estructuras, variables y funciones..........................................................................6<br />

3.7Declaración <strong>de</strong> variables.............................................................................................................7<br />

4Com<strong>en</strong>tarios........................................................................................................................................8<br />

4.1Com<strong>en</strong>tarios <strong>de</strong> inicio <strong>de</strong> bloque................................................................................................8<br />

4.2Com<strong>en</strong>tarios aclaratorios............................................................................................................8<br />

4.3Com<strong>en</strong>tarios sobre funciones y procedimi<strong>en</strong>tos.........................................................................8<br />

5Disposición <strong>de</strong> elem<strong>en</strong>tos.................................................................................................................10<br />

5.1Estructuras................................................................................................................................10<br />

5.1.1Unida<strong>de</strong>s <strong>de</strong> traducción.....................................................................................................10<br />

5.2Funciones..................................................................................................................................11<br />

5.2.1Estructuras <strong>de</strong> <strong>de</strong>cisión y repetición..................................................................................12<br />

5.2.1.1Cuerpos <strong>de</strong> instrucciones <strong>de</strong> una sola línea...............................................................12<br />

5.3Espaciado..................................................................................................................................13


1 Introducción<br />

En este docum<strong>en</strong>to se explica brevem<strong>en</strong>te, y con ejemplos, cómo escribir programas más legibles.<br />

A lo largo <strong>de</strong> su vida profesional, cualquier programador se plantea la pregunta <strong>de</strong> cómo escribir sus<br />

programas <strong>de</strong> manera que sean más legibles, y por tanto que puedan ser mant<strong>en</strong>idos (corrección <strong>de</strong><br />

errores, ampliación <strong>de</strong> funcionalidad) con facilidad, tanto por él mismo como por otros<br />

programadores (una situación típica <strong>en</strong> cualquier empresa).<br />

Dado que la misma situación <strong>en</strong> cuanto a legibilidad <strong>de</strong> código suele ser resuelta por<br />

distintos programadores <strong>de</strong> la misma forma, pero con distintos matices <strong>de</strong> difer<strong>en</strong>ciación, es<br />

interesante seguir una guía <strong>de</strong> <strong>estilo</strong> que nos explique como otros resolvieron ese mismo problema,<br />

hasta que dicha solución se convirtió <strong>en</strong> un estándar.<br />

2 Indicaciones g<strong>en</strong>erales<br />

El propósito <strong>de</strong> seguir una norma <strong>de</strong> <strong>estilo</strong> es hacer que el código fu<strong>en</strong>te <strong>de</strong> un programa sea tan<br />

legible como sea posible. Así, hay tres puntos básicos que se <strong>de</strong>b<strong>en</strong> cuidar: el espaciado horizontal,<br />

el espaciado vertical y la in<strong>de</strong>ntación. El espaciado horizontal consiste <strong>en</strong> que las líneas <strong>en</strong> las que<br />

esté dividido el código fu<strong>en</strong>te <strong>de</strong>b<strong>en</strong> ser <strong>de</strong> una longitud máxima lo más próxima posible a 80<br />

caracteres, ya que al imprimir el código <strong>en</strong> papel cualquier línea superior a 80 columnas se <strong>de</strong>scarta<br />

automáticam<strong>en</strong>te.<br />

Uno <strong>de</strong> los problemas que se pue<strong>de</strong> <strong>en</strong>contrar al codificar es la manera más correcta para<br />

dividir una línea muy larga. Respuestas comunes a esta pregunta son: antes <strong>de</strong> una subexpresión,<br />

antes <strong>de</strong> un operador, o antes <strong>de</strong> un paréntesis. Por ejemplo:<br />

int x = ( (a * b + c ) / ( c * d * d ) )<br />

+ ( a / ( b * c ) )<br />

+ ( ( 3.1451927 * b ) + d )<br />

;<br />

Los operadores <strong>de</strong>b<strong>en</strong> separarse mediante espacios para mayor claridad, a excepción hecha<br />

<strong>de</strong> operadores unarios como el increm<strong>en</strong>to o <strong>de</strong>crem<strong>en</strong>to, tanto postfijo como prefijo, que suel<strong>en</strong><br />

colocarse pegados al operando al que modifican (lo más típico, por claridad), pero también pue<strong>de</strong>n<br />

colocarse espaciados, a elección <strong>de</strong>l programador.<br />

int x = ++ i;<br />

int y = j++ + ++ x;<br />

El espaciado vertical consiste <strong>en</strong> cuántas líneas ocupa una función o una estructura, <strong>en</strong> el<br />

código fu<strong>en</strong>te. En g<strong>en</strong>eral, es útil autoimponerse un límite <strong>de</strong> una hoja por cada función o<br />

procedimi<strong>en</strong>to. Es extraño, siempre que la misma no consista <strong>en</strong> multitud <strong>de</strong> acciones repetitivas<br />

(como escribir <strong>en</strong> un archivo), que una función bi<strong>en</strong> diseñada ocupe más allá <strong>de</strong> un folio. En caso<br />

contrario, será conv<strong>en</strong>i<strong>en</strong>te consi<strong>de</strong>rar que posiblem<strong>en</strong>te sea interesante subdividirlo <strong>en</strong> varias<br />

subfunciones (probablem<strong>en</strong>te <strong>de</strong> acceso privado).<br />

A<strong>de</strong>más, <strong>en</strong> el espaciado vertical intervi<strong>en</strong><strong>en</strong> las llaves que se emplean para marcar el<br />

comi<strong>en</strong>zo y fin <strong>de</strong>l cuerpo <strong>de</strong> una función, <strong>de</strong> un bucle, ... cada una <strong>de</strong> esas llaves pue<strong>de</strong> llegar a<br />

consumir una línea por sí sola, incluso dos. Así, para salvar algo <strong>de</strong> espacio vertical, se suel<strong>en</strong><br />

mant<strong>en</strong>er las llaves <strong>de</strong> apertura y cierre, cada una <strong>en</strong> una línea, para el cuerpo <strong>de</strong> las funciones, y <strong>en</strong><br />

cambio colocar la llave <strong>de</strong> apertura <strong>en</strong> la misma línea para bucles y estructuras <strong>de</strong> <strong>de</strong>cisión. Por<br />

ejemplo:


int dividir(int a, int b)<br />

{<br />

if ( b != 0 ) {<br />

return a / b;<br />

}<br />

}<br />

return 0;<br />

... (recuér<strong>de</strong>se que <strong>en</strong> un programa real será mucho más a<strong>de</strong>cuado respon<strong>de</strong>r a la<br />

conting<strong>en</strong>cia que supone dividir un número <strong>en</strong>tre cero, que respon<strong>de</strong>r con cero “sil<strong>en</strong>ciosam<strong>en</strong>te”,<br />

lo cual supone un error no <strong>de</strong>tectado).<br />

La in<strong>de</strong>ntación es vital para po<strong>de</strong>r compr<strong>en</strong><strong>de</strong>r rápidam<strong>en</strong>te los elem<strong>en</strong>tos funcionales <strong>de</strong> un<br />

programa. Así, el cuerpo (las instrucciones) <strong>de</strong> una función o procedimi<strong>en</strong>to <strong>de</strong>be estar alineado <strong>en</strong><br />

su marg<strong>en</strong> izquierdo más a la <strong>de</strong>recha que su cabecera, <strong>de</strong> la misma forma que un bucle <strong>de</strong>ntro <strong>de</strong><br />

esa función y así sucesivam<strong>en</strong>te. Por ejemplo:<br />

int elevarA(int x, int y)<br />

{<br />

int toret = 1;<br />

}<br />

if ( y >= 0 ) {<br />

for(; y > 0; --y) {<br />

toret *= x;<br />

}<br />

} else toret = 0<br />

return toret;<br />

3 I<strong>de</strong>ntificadores<br />

Los i<strong>de</strong>ntificadores se utilizan <strong>en</strong> varias (innumerables) ocasiones <strong>en</strong> <strong>programación</strong>: <strong>en</strong>umeraciones,<br />

funciones, constantes, variables locales ..., y son claves para <strong>en</strong>t<strong>en</strong><strong>de</strong>r qué valores pue<strong>de</strong> cont<strong>en</strong>er<br />

una variable, qué hace una función o a qué valores repres<strong>en</strong>ta un <strong>en</strong>umerado. Por eso, hay que poner<br />

especial cuidado <strong>en</strong> su elección. También será interesante seguir unas pequeñas reglas a la hora <strong>de</strong><br />

escribir un i<strong>de</strong>ntificador que hagan que a su vez podamos obt<strong>en</strong>er el máximo significado <strong>de</strong>l mismo<br />

si se está ley<strong>en</strong>do <strong>en</strong> un listado.<br />

En g<strong>en</strong>eral, los i<strong>de</strong>ntificadores <strong>de</strong>b<strong>en</strong> ser tan cortos como sea posible, pero a la vez tan<br />

informativos como sea posible. Muchas veces, a<strong>de</strong>más, es imposible utilizar un solo sustantivo para<br />

nombrar una variable, función o estructura; <strong>en</strong> ese caso, se concat<strong>en</strong>arán todos para formar el<br />

i<strong>de</strong>ntificador final, poni<strong>en</strong>do cada inicial <strong>en</strong> mayúscula. Si bi<strong>en</strong> algunos l<strong>en</strong>guajes mo<strong>de</strong>rnos lo<br />

permit<strong>en</strong> (como Java), a través <strong>de</strong>l soporte unico<strong>de</strong>, evít<strong>en</strong>se los ac<strong>en</strong>tos, las diéresis ... <strong>en</strong> los<br />

i<strong>de</strong>ntificadores.<br />

3.1 I<strong>de</strong>ntificadores <strong>de</strong> estructuras<br />

Los i<strong>de</strong>ntificadores <strong>de</strong> estructuras <strong>de</strong>berían correspon<strong>de</strong>rse con sustantivos <strong>de</strong> la vida real o <strong>de</strong>l<br />

concepto que se está mo<strong>de</strong>lando con el programa. Así, i<strong>de</strong>ntificadores <strong>de</strong> estructuras típicos pue<strong>de</strong>n<br />

ser: Casa, Coche, Barco, Cu<strong>en</strong>ta ...<br />

El i<strong>de</strong>ntificador <strong>de</strong> la estructura, <strong>en</strong> caso <strong>de</strong> estar compuesto por más <strong>de</strong> una palabra, se<br />

construye concat<strong>en</strong>ando todas las palabras, y poni<strong>en</strong>do la inicial <strong>de</strong> cada una <strong>de</strong> estas palabras <strong>en</strong><br />

mayúsculas. Por ejemplo: Cu<strong>en</strong>taCorri<strong>en</strong>te, Cu<strong>en</strong>taCredito ...


struct Rectangulo {<br />

// más cosas ...<br />

};<br />

struct Cu<strong>en</strong>taCorri<strong>en</strong>te {<br />

// más cosas ...<br />

};<br />

3.2 I<strong>de</strong>ntificadores <strong>de</strong> campos<br />

Los i<strong>de</strong>ntificadores <strong>de</strong> campos (o datos miembro), sigu<strong>en</strong> las mismas normas que los <strong>de</strong> las<br />

estructuras, pero con la primera inicial <strong>en</strong> minúscula. Así, por ejemplo, i<strong>de</strong>ntificadores válidos son<br />

i<strong>de</strong>ntificadorCompleto, precioEuros, ...<br />

struct Cu<strong>en</strong>taCorri<strong>en</strong>te {<br />

double saldoEuros;<br />

};<br />

3.3 I<strong>de</strong>ntificadores <strong>de</strong> registros<br />

Los i<strong>de</strong>ntificadores <strong>de</strong> registros (o variables <strong>de</strong> las estructuras) sigu<strong>en</strong> las mismas reglas que los<br />

i<strong>de</strong>ntificadores <strong>de</strong> los campos.<br />

3.4 I<strong>de</strong>ntificadores <strong>de</strong> funciones<br />

Los i<strong>de</strong>ntificadores <strong>de</strong> funciones sigu<strong>en</strong> las mismas reglas que para campos y registros. Sin<br />

embargo, <strong>de</strong>b<strong>en</strong> escogerse <strong>de</strong> modo que sugieran <strong>de</strong> manera intuitiva qué hac<strong>en</strong>. Así, el<br />

i<strong>de</strong>ntificador <strong>de</strong>be ser un verbo o al m<strong>en</strong>os cont<strong>en</strong>er uno. Las funciones que <strong>de</strong>vuelv<strong>en</strong> un valor<br />

lógico <strong>de</strong>berían t<strong>en</strong>er un verbo copulativo (ser o estar) al comi<strong>en</strong>zo <strong>de</strong>l i<strong>de</strong>ntificador.<br />

double calculaArea(Triangulo);<br />

int esPalindromo(const char *);<br />

Evít<strong>en</strong>s<strong>en</strong> i<strong>de</strong>ntificadores como los sigui<strong>en</strong>tes:<br />

int procesar(Cu<strong>en</strong>taCorri<strong>en</strong>te c); // Mal: i<strong>de</strong>ntificador no intuitivo<br />

void pasoAuxiliar(Rectagulo r); // Mal: i<strong>de</strong>ntificador simplem<strong>en</strong>te erróneo<br />

void procesaYCu<strong>en</strong>ta(); // Mal: Dividir <strong>en</strong> dos funciones<br />

Cuando un i<strong>de</strong>ntificador conti<strong>en</strong>e una conjunción como y, es signo inequívoco <strong>de</strong> que la<br />

función que nombra realiza más <strong>de</strong> una tarea y <strong>de</strong>be ser por tanto separada <strong>en</strong> dos funciones<br />

separadas.<br />

Los mejores i<strong>de</strong>ntificadores son aquellos que <strong>de</strong>scrib<strong>en</strong> con un i<strong>de</strong>ntificador más corto lo<br />

que hace la función. A<strong>de</strong>más, es interesante seguir ciertas pautas: <strong>en</strong> el caso <strong>de</strong> funciones que<br />

<strong>de</strong>vuelv<strong>en</strong> un booleano (un valor verda<strong>de</strong>ro o falso), es interesante nombrarlos con un prefijo<br />

formado por los verbos ser o estar, como:<br />

esPalindromo(const char s[]);<br />

esPar(int);<br />

fueModificada(const Cu<strong>en</strong>taCorri<strong>en</strong>te c);<br />

3.5 I<strong>de</strong>ntificadores <strong>de</strong> variables locales <strong>en</strong> funciones<br />

En el caso <strong>de</strong> variables locales <strong>de</strong> funciones, exist<strong>en</strong> varias particularida<strong>de</strong>s. Por ejemplo, a las<br />

variables locales empleadas <strong>en</strong> bucles se les suele asignar i<strong>de</strong>ntificadores <strong>de</strong> una letra tipo 'i' y 'j',<br />

también <strong>en</strong> el caso <strong>de</strong> algunos argum<strong>en</strong>tos simples (si bi<strong>en</strong> este caso es mejor, sin embargo, evitarlo,


cuando sea posible, y asignar i<strong>de</strong>ntificadores <strong>de</strong>scriptivos) <strong>de</strong> funciones.<br />

void cnvtMayusculas(char s[])<br />

{<br />

int i = 0;<br />

}<br />

for(; s[ i ] != 0; ++i) {<br />

s[ i ] = toupper( s[ i ] );<br />

}<br />

Los i<strong>de</strong>ntificadores <strong>de</strong> variables también pue<strong>de</strong>n informar sobre para qué se utiliza esa<br />

variable, y no restringirse a tan solo información sobre qué valores alberga. Por ejemplo, <strong>en</strong> el<br />

código sigui<strong>en</strong>te toret (a retornar) es una variable que se utiliza <strong>en</strong> todas las funciones para <strong>de</strong>volver<br />

un valor.<br />

int calcularLongitud(const char s[])<br />

{<br />

int toret = 0;<br />

}<br />

for(; s[ toret ] != 0; ++toret) {<br />

}<br />

return toret;<br />

3.6 Ejemplo con estructuras, variables y funciones<br />

A continuación, se muestra un ejemplo completo:<br />

#inclu<strong>de</strong> <br />

const double PI = 3.1415927;<br />

struct Circulo {<br />

double radio;<br />

double perimetro;<br />

double area;<br />

};<br />

void calcularDatos(const Circulo &c)<br />

/* Completar la estructura círculo con los datos a<strong>de</strong>cuados */<br />

{<br />

c.area = c.radio * c.radio * PI;<br />

c.perimetro = 2 * PI * c.radio;<br />

}<br />

int main(void)<br />

{<br />

Circulo miCirculo;<br />

}<br />

printf( “Introduzca el radio <strong>de</strong>l círculo: “ );<br />

scanf( “%f”, &miCirculo.radio );<br />

calcularDatos( miCirculo );<br />

printf( “Círculo <strong>de</strong> radio: %f\n\tÁrea: %f\n\tPerímetro: %f\n”,<br />

miCirculo.radio,<br />

miCirculo.area,<br />

miCirculo.perimetro<br />

);


3.7 Declaración <strong>de</strong> variables<br />

Se <strong>de</strong>be colocar cada variable <strong>en</strong> una línea, incluso si<strong>en</strong>do <strong>de</strong>l mismo tipo.<br />

int x, y; // Es necesaria una segunda mirada para fijarse <strong>en</strong> 'y'<br />

int main()<br />

{<br />

int x;<br />

int y;<br />

char c;<br />

char toret[128];<br />

}<br />

// más cosas ...<br />

return 0;<br />

C permite minimizar muchísimo ciertas expresiones. Por ejemplo, el sigui<strong>en</strong>te bucle copiaría<br />

una ca<strong>de</strong>na <strong>de</strong> caracteres <strong>de</strong> C (un vector <strong>de</strong> char), <strong>en</strong> otra <strong>de</strong> <strong>de</strong>stino:<br />

void copiaCa<strong>de</strong>na(char cadDestino[], const char cadOrig<strong>en</strong>[])<br />

{<br />

int i = 0;<br />

while( cadDestino[ i ] = cadOrig<strong>en</strong>[ i++ ] );<br />

}<br />

Esto es bu<strong>en</strong>o <strong>en</strong> cuanto a espaciado vertical, <strong>de</strong>s<strong>de</strong> luego, pero <strong>de</strong>be valorarse cuándo el<br />

ahorro <strong>de</strong> espaciado merma la legibilidad <strong>de</strong>l código.<br />

void copiaCa<strong>de</strong>na(char cadDestino[], const char cadOrig<strong>en</strong>[])<br />

{<br />

int i = 0;<br />

for(; cadOrig<strong>en</strong>[ i ] != 0; ++i) {<br />

cadDestino[ i ] = cadOrig<strong>en</strong>[ i ];<br />

}<br />

}<br />

La anterior función realiza la misma tarea que la pre<strong>de</strong>cesora. Sin embargo, está<br />

perfectam<strong>en</strong>te claro cuándo el bucle termina (al llegar a la marca <strong>de</strong> fin <strong>de</strong> ca<strong>de</strong>na <strong>de</strong> la ca<strong>de</strong>na <strong>de</strong><br />

orig<strong>en</strong>), cuándo se hace explícitam<strong>en</strong>te una copia y también cuándo, <strong>de</strong>spués, se increm<strong>en</strong>tan ambos<br />

contadores. Es una función que se pue<strong>de</strong> compr<strong>en</strong><strong>de</strong>r <strong>de</strong> un vistazo, mi<strong>en</strong>tras que la anterior, aún<br />

para un programador con experi<strong>en</strong>cia, supondrá invertir unos cuantos segundos. Finalm<strong>en</strong>te, la<br />

calidad <strong>de</strong>l código máquina g<strong>en</strong>erada es la misma <strong>en</strong> ambos casos, si bi<strong>en</strong> es cierto que el primer<br />

ejemplo podría g<strong>en</strong>erar, según el compilador, un número <strong>de</strong> instrucciones máquina algo m<strong>en</strong>or.<br />

4 Com<strong>en</strong>tarios<br />

Un com<strong>en</strong>tario <strong>de</strong>be ser siempre clarificador, útil, y, <strong>en</strong> cambio, cuanto más corto mejor. En<br />

particular, <strong>de</strong>be cuidarse <strong>en</strong> no insultar la intelig<strong>en</strong>cia <strong>de</strong>l lector <strong>en</strong> <strong>de</strong>terminadas ocasiones,<br />

com<strong>en</strong>tando secu<strong>en</strong>cias <strong>de</strong> código obvias y <strong>de</strong>sesperarlo al <strong>en</strong>contrarse con construcciones<br />

complejas que no ti<strong>en</strong><strong>en</strong> ningún com<strong>en</strong>tario.


int areaRectangulo = lado1 * lado2; // calcula área<br />

areaCirculo = PI * r * r; // calcula área <strong>de</strong>l círculo<br />

// PI es 3.1415927<br />

En el contexto <strong>de</strong>l ejemplo anterior, el tercer com<strong>en</strong>tario es absolutam<strong>en</strong>te innecesario,<br />

mi<strong>en</strong>tras que los dos primeros son cuestionables, siempre que los i<strong>de</strong>ntificadores hayan sido<br />

escogidos cuidadosam<strong>en</strong>te, como es el caso.<br />

4.1 Com<strong>en</strong>tarios <strong>de</strong> inicio <strong>de</strong> bloque<br />

Exist<strong>en</strong> dos tipos básicos <strong>de</strong> com<strong>en</strong>tarios, los que podríamos <strong>de</strong>nominar com<strong>en</strong>tarios <strong>en</strong>cima, y los<br />

que podríamos <strong>de</strong>nominar com<strong>en</strong>tarios a la <strong>de</strong>recha. Los más recom<strong>en</strong>dables son los primeros,<br />

pues suel<strong>en</strong> explicar un bloque <strong>de</strong> código, a modo <strong>de</strong> párrafo, aclarando mucho la lectura.<br />

void listarPersonas(char buffer[], const Persona &vp[MaxPersonas])<br />

/**<br />

@param buffer vector <strong>de</strong> caracteres para listado<br />

@param vp vector <strong>de</strong> personas a listar<br />

*/<br />

{<br />

*buffer = 0;<br />

int i = 0;<br />

}<br />

// Obt<strong>en</strong>er los nombres <strong>de</strong> cada persona<br />

for(; i < MaxPersonas; ++i) {<br />

strcat( buffer, vp[ i ].nombre );<br />

strcat( buffer, “\n” );<br />

}<br />

return buffer;<br />

Como pue<strong>de</strong> observarse, el com<strong>en</strong>tario <strong>de</strong> la función sigue un formato específico, que se discutirá<br />

<strong>en</strong> las sigui<strong>en</strong>tes secciones.<br />

4.2 Com<strong>en</strong>tarios aclaratorios<br />

Los com<strong>en</strong>tarios a la <strong>de</strong>recha <strong>de</strong>b<strong>en</strong> emplearse como m<strong>en</strong>sajes aclaratorios, int<strong>en</strong>tando mant<strong>en</strong>er<br />

especialm<strong>en</strong>te <strong>en</strong> ellos la concisión, pues es fácil que se alcanc<strong>en</strong> rápidam<strong>en</strong>te más <strong>de</strong> och<strong>en</strong>ta<br />

caracteres <strong>en</strong> esa línea. Agravando aún más este último problema, <strong>de</strong>b<strong>en</strong> colocarse alejados <strong>de</strong>l<br />

código que aclaran para que sean visibles.<br />

// Cálculos previos al r<strong>en</strong><strong>de</strong>ring<br />

areaRectangulo = lado1 * lado2; // <strong>en</strong> cms<br />

4.3 Com<strong>en</strong>tarios sobre funciones y procedimi<strong>en</strong>tos<br />

Des<strong>de</strong> la llegada <strong>de</strong>l l<strong>en</strong>guaje Java, y su herrami<strong>en</strong>ta <strong>de</strong> docum<strong>en</strong>tación, Javadoc, se han<br />

g<strong>en</strong>eralizado los com<strong>en</strong>tarios formateados con un <strong>de</strong>terminado <strong>estilo</strong>, y aceptando unos<br />

<strong>de</strong>terminados parámetros <strong>de</strong> docum<strong>en</strong>tación embebidos <strong>en</strong> ellos. Para el l<strong>en</strong>guaje C, existe también<br />

un equival<strong>en</strong>te a Javadoc, la herrami<strong>en</strong>ta Doxyg<strong>en</strong> 1 , <strong>de</strong> gran aceptación.<br />

Así, cuando un com<strong>en</strong>tario, <strong>en</strong> lugar <strong>de</strong> empezar por /*, comi<strong>en</strong>za por /**, al pasar el código<br />

por la herrami<strong>en</strong>ta Doxyg<strong>en</strong>, ésta g<strong>en</strong>era la docum<strong>en</strong>tación recogida <strong>en</strong> varios formatos (incluy<strong>en</strong>do<br />

el HTML, que lo hace i<strong>de</strong>al para las refer<strong>en</strong>cias cruzadas). Estos com<strong>en</strong>tarios también son útiles al<br />

<strong>de</strong>snudo, por lo que <strong>de</strong>b<strong>en</strong> colocarse <strong>en</strong> las cabeceras (los ficheros con ext<strong>en</strong>sión .h, don<strong>de</strong> se<br />

1 Doxyg<strong>en</strong> pue<strong>de</strong> <strong>en</strong>contrarse <strong>en</strong>: http://www.doxyg<strong>en</strong>.org


<strong>de</strong>claran las clases; consúltese la sección sobre unida<strong>de</strong>s <strong>de</strong> traducción), inmediatam<strong>en</strong>te antes <strong>de</strong><br />

cada estructura, función, o campo. Son las cabeceras las que serán consultadas por el programador<br />

que utilice el módulo para conocer su interfaz pública.<br />

// rectangulo.h<br />

/**<br />

La estructura que repres<strong>en</strong>ta a los rectángulos<br />

*/<br />

struct Rectangulo {<br />

/// La información sobre la base <strong>de</strong>l rectángulo<br />

double base;<br />

/// La información sobre la altura <strong>de</strong>l rectángulo<br />

double altura;<br />

};<br />

/**<br />

* Creador <strong>de</strong> rectángulos<br />

* @param b La base <strong>de</strong>l futuro rectángulo<br />

* @param a La altura <strong>de</strong>l futuro rectángulo<br />

*/<br />

Rectangulo creaRectangulo(double b, double a);<br />

/**<br />

* Calcula el área <strong>de</strong>l rectángulo<br />

* @return El área <strong>de</strong>l rectángulo, según sus lados<br />

*/<br />

double calcularArea(const Rectangulo &r);<br />

// rectangulo.cpp<br />

/*<br />

Implem<strong>en</strong>tación <strong>de</strong>l TDA rectángulo.<br />

*/<br />

#inclu<strong>de</strong> “rectangulo.h”<br />

Rectangulo creaRectangulo(double b, double a)<br />

{<br />

Rectangulo toret;<br />

toret.base = b;<br />

toret.altura = a;<br />

return toret;<br />

}<br />

double calcularArea(const Rectangulo &r)<br />

{<br />

return ( r.base * r.altura );<br />

}<br />

De los parámetros que se pue<strong>de</strong>n utilizar <strong>en</strong> este tipo <strong>de</strong> com<strong>en</strong>tarios, <strong>de</strong>stacan @param y<br />

@return. El primero sirve para docum<strong>en</strong>tar un parámetro <strong>de</strong> una función o procedimi<strong>en</strong>to, tal y<br />

como se ve <strong>en</strong> la función crearRectángulo() <strong>de</strong>l módulo Rectángulo <strong>de</strong> ejemplo, más arriba. El<br />

segundo sirve para docum<strong>en</strong>tar el valor <strong>de</strong> retorno <strong>de</strong> una función, tal y como se aprecia <strong>en</strong> la<br />

función calcularArea() <strong>de</strong>l módulo <strong>de</strong>l mismo ejemplo. Por último, con @see es posible hacer<br />

refer<strong>en</strong>cias cruzadas <strong>en</strong>tre funciones y estructuras <strong>de</strong> datos, por ejemplo.


5 Disposición <strong>de</strong> elem<strong>en</strong>tos<br />

5.1 Estructuras<br />

Al igual que al tratar con variables locales, <strong>de</strong>b<strong>en</strong> colocarse los miembtos <strong>de</strong> una estructura uno <strong>en</strong><br />

cada línea. Debe aprovecharse para docum<strong>en</strong>tar a<strong>de</strong>cuadam<strong>en</strong>te la <strong>en</strong>tidad. Si el significado <strong>de</strong> los<br />

miembros no es obvio, <strong>en</strong>tonces, <strong>de</strong>b<strong>en</strong> añadirse com<strong>en</strong>tarios para cada campo.<br />

/// Estructura que repres<strong>en</strong>ta a puntos <strong>de</strong> dos dim<strong>en</strong>siones<br />

struct Punto {<br />

double x;<br />

double y;<br />

};<br />

5.1.1 Unida<strong>de</strong>s <strong>de</strong> traducción<br />

En terminología C, el compilador traduce a código máquina unida<strong>de</strong>s <strong>de</strong> traducción, que son<br />

ficheros con ext<strong>en</strong>sión .cpp, también conocidos como ficheros <strong>de</strong> implem<strong>en</strong>tación, ya que <strong>en</strong> ellos<br />

se <strong>de</strong>fin<strong>en</strong> las funciones y variables globales. Estos ficheros normalm<strong>en</strong>te ti<strong>en</strong><strong>en</strong> asociados unos<br />

ficheros <strong>de</strong> cabecera (con ext<strong>en</strong>sión .h), don<strong>de</strong> se <strong>de</strong>claran los miembros públicos. Es muy<br />

importante la disposición <strong>de</strong> los prototipos <strong>de</strong> las funciones públicas y las <strong>de</strong>claraciones <strong>de</strong> las<br />

estructuras públicas <strong>en</strong> las cabeceras, mi<strong>en</strong>tras que las respectivas implem<strong>en</strong>taciones <strong>de</strong>b<strong>en</strong> aparecer<br />

<strong>en</strong> los ficheros <strong>de</strong> implem<strong>en</strong>tación.<br />

/* punto.h */<br />

#ifn<strong>de</strong>f _PUNTO_H_<br />

#<strong>de</strong>fine _PUNTO_H_<br />

/** Estructura que repres<strong>en</strong>ta a puntos <strong>de</strong> dos dim<strong>en</strong>siones **/<br />

struct Punto {<br />

double x;<br />

double y;<br />

};<br />

/** Orig<strong>en</strong> <strong>de</strong> coor<strong>de</strong>nadas **/<br />

extern const Punto puntoOrig<strong>en</strong>;<br />

/** Creador <strong>de</strong> registros Punto<br />

* @param a La coor<strong>de</strong>nada horizontal<br />

* @param b La coor<strong>de</strong>nada vertical<br />

*/<br />

Punto crearPunto(double a, double b);<br />

/// @return la coor<strong>de</strong>nada horizontal<br />

double calculaDistancia(const Punto &p1, const Punto &p2);<br />

#<strong>en</strong>dif<br />

/* punto.cpp */<br />

#inclu<strong>de</strong> “punto.h”<br />

#inclu<strong>de</strong> <br />

const Punto PuntoOrig<strong>en</strong> = { 0, 0 };<br />

static double calculaDistanciaOrig<strong>en</strong>(const Punto &p1)<br />

/** Calcula distancia a orig<strong>en</strong> – Privada **/<br />

{<br />

return sqrt( ( p1.x * p1.x ) + ( p1.y * p1.y) );<br />

}


inline Punto crearPunto(double a, double b)<br />

{<br />

Punto p = { a, b };<br />

return p;<br />

}<br />

double calculaDistancia(const Punto &p1, const Punto &p2)<br />

{<br />

return abs( calculaDistanciaOrig<strong>en</strong>( p1 )<br />

– calculaDistanciaOrig<strong>en</strong>( p2 ) )<br />

;<br />

}<br />

La línea #ifn<strong>de</strong>f _PUNTO_H_ y la sigui<strong>en</strong>te lo que hac<strong>en</strong> es evitar que se compile la cabecera<br />

punto.h más <strong>de</strong> una vez. Ésto pue<strong>de</strong> suce<strong>de</strong>r inadvertidam<strong>en</strong>te <strong>en</strong> un proyecto complejo, cuando<br />

más <strong>de</strong> una cabecera incluye la primera. El diagnóstico <strong>de</strong> este problema es s<strong>en</strong>cillo, pues <strong>en</strong> ese<br />

caso el compilador se quejaría <strong>de</strong> una re<strong>de</strong>claración <strong>de</strong>l módulo Punto.<br />

Nótese que se ha incluido un objeto constante. Para po<strong>de</strong>r ser utilizado <strong>de</strong>be ser <strong>de</strong>clarado<br />

<strong>en</strong> el fichero <strong>de</strong> cabecera, con extern, si bi<strong>en</strong> nunca <strong>de</strong>finido (la cabecera pue<strong>de</strong> ser incluida <strong>en</strong><br />

varias unida<strong>de</strong>s <strong>de</strong> traducción: poner la <strong>de</strong>finición <strong>en</strong> la cabecera significaría que todas ellas<br />

t<strong>en</strong>drían un objeto puntoOrig<strong>en</strong> distinto, aunque con el mismo i<strong>de</strong>ntificador, lo que provocaría un<br />

error <strong>de</strong> <strong>en</strong>lace). La <strong>de</strong>finición, como pue<strong>de</strong> verse, aparece <strong>en</strong> el fichero <strong>de</strong> implem<strong>en</strong>tación,<br />

mi<strong>en</strong>tras que <strong>en</strong> el fichero <strong>de</strong> cabecera aparece una <strong>de</strong>claración con extern, <strong>de</strong> manera que el<br />

compilador sepa que está <strong>de</strong>finida <strong>en</strong> algún módulo (pero sólo <strong>en</strong> uno, claro, <strong>en</strong> otro caso se<br />

produce otro error).<br />

Si, <strong>en</strong> cambio, se <strong>de</strong>sea que un objeto no sea público, <strong>de</strong>be omitirse cualquier m<strong>en</strong>ción sobre<br />

él <strong>en</strong> la cabecera, y <strong>en</strong> el mom<strong>en</strong>to <strong>de</strong> la <strong>de</strong>finición <strong>en</strong> el archivo <strong>de</strong> implem<strong>en</strong>tación <strong>de</strong>be añadirse<br />

el modificador static (que <strong>en</strong> este caso <strong>de</strong> aplicación significa privado, y no ti<strong>en</strong>e, explícitam<strong>en</strong>te,<br />

el mismo significado que cuando se aplica a una variable local <strong>de</strong> una función).<br />

5.2 Funciones<br />

En las funciones, se <strong>de</strong>be adoptar como esquema básico la típica estructura inicialización<strong>de</strong>sarrollo­limpieza,<br />

es <strong>de</strong>cir el comi<strong>en</strong>zo <strong>de</strong> la tarea, inicializando (y creando, cuando sea oportuno)<br />

las variables necesarias, el <strong>de</strong>sarrollo <strong>de</strong>l problema, como el bucle <strong>de</strong>l ejemplo situado más abajo,y<br />

finalm<strong>en</strong>te, cuando es necesario, la limpieza <strong>de</strong> los recursos utilizados.<br />

int sumaFicheroDatos(const char nombreFichero[])<br />

/**<br />

Lee el cont<strong>en</strong>ido <strong>de</strong> un archivo <strong>de</strong> texto, <strong>en</strong> el que cada línea es un<br />

número <strong>en</strong>tero, y lo suma.<br />

@param nombreFichero El nombre <strong>de</strong> fichero a cargar<br />

@return La suma <strong>de</strong> todos los valores <strong>en</strong> el fichero.<br />

**/<br />

{<br />

int num;<br />

int toret = 0;<br />

FILE * f = fop<strong>en</strong>( nombreFichero, “rt” );<br />

if ( f != NULL ) {<br />

fscanf( f, “%d\n”, &num );<br />

while( !feof( f ) ) {<br />

toret += num;<br />

fscanf( f, “%d\n”, &num );<br />

}<br />

fclose( f );


}<br />

}<br />

return toret;<br />

5.2.1 Estructuras <strong>de</strong> <strong>de</strong>cisión y repetición<br />

Es típico <strong>en</strong>contrarse con la necesidad <strong>de</strong> t<strong>en</strong>er que crear estructuras condicionales (if) o <strong>de</strong><br />

repetición (while), que se refier<strong>en</strong> a condiciones complejas. Debe tratarse, <strong>en</strong> estos casos, <strong>de</strong><br />

disponer una subcondición por línea, com<strong>en</strong>zando por el juntor (and (&&), or(||), y not(!)). Si es<br />

necesario, una subcondición pue<strong>de</strong> llevar un com<strong>en</strong>tario "a la <strong>de</strong>recha". Si exist<strong>en</strong> varias<br />

subexpresiones condicionales, se <strong>de</strong>b<strong>en</strong> in<strong>de</strong>ntar respecto a la expresión principal.<br />

if ( buffer != NULL<br />

&& feof( f )<br />

&& tamMaxBufferDestino > 0 )<br />

{<br />

while( !feof( f ) ) {<br />

/* más cosas ... */<br />

}<br />

}<br />

if ( feof( f )<br />

&& bytesLeidos > 0 )<br />

{<br />

memcpy( <strong>de</strong>st, buffer, tamMaxBufferDestino );<br />

}<br />

Cuando se crean estructuras <strong>de</strong> <strong>de</strong>cisión con más <strong>de</strong> una expresión condicional, no se <strong>de</strong>be<br />

utilizar la posibilidad <strong>de</strong> crear los cuerpos <strong>de</strong> instrucciones <strong>de</strong> una sola línea sin las llaves <strong>de</strong> inicio<br />

y fin <strong>de</strong> bloque ( { y } ), ya que la s<strong>en</strong>t<strong>en</strong>cia no sería visible, como se muestra a continuación.<br />

if ( feof( f )<br />

&& bytesLeidos > 0 )<br />

f.close();<br />

5.2.1.1 Cuerpos <strong>de</strong> instrucciones <strong>de</strong> una sola línea<br />

En g<strong>en</strong>eral, es más legible evitar esta posibilidad. Las s<strong>en</strong>t<strong>en</strong>cias <strong>de</strong> un bloque sin llaves casi pasan<br />

<strong>de</strong>sapercibidas, y por tanto es mejor cambiarlas por bloques siempre que sea posible. Recuér<strong>de</strong>se<br />

que los bloques <strong>de</strong> una sola línea sin llaves <strong>de</strong> comi<strong>en</strong>zo y fin son una posibilidad, no una<br />

obligación. En cuanto al espacio vertical, colocar la llave inicio <strong>en</strong> la misma línea <strong>de</strong> una s<strong>en</strong>t<strong>en</strong>cia<br />

<strong>de</strong> repetición o <strong>de</strong> <strong>de</strong>cisión (siempre que no haya múltiples subexpresiones condicionales), es una<br />

medida que pue<strong>de</strong> ser muy útil.<br />

En el caso <strong>de</strong> una s<strong>en</strong>t<strong>en</strong>cia if­th<strong>en</strong>­else con sólo una expresión condicional, se pue<strong>de</strong> utilizar<br />

la posibilidad <strong>de</strong> los bloques sin llaves <strong>de</strong> comi<strong>en</strong>zo y fin, por ejemplo:<br />

int buscarPersona(const char nombre[], const Persona &vp[MaxPersonas])<br />

/**<br />

@param nombre vector <strong>de</strong> caracteres con el nombre a buscar<br />

@param vp vector <strong>de</strong> personas don<strong>de</strong> buscar<br />

@return<br />

*/<br />

{<br />

int i = 0;<br />

// Buscar <strong>en</strong> el nombre <strong>de</strong> cada persona<br />

for(; i < MaxPersonas; ++i) {<br />

if ( vp[ i ].nombre == nombre ) {<br />

break;


}<br />

}<br />

5.3 Espaciado<br />

}<br />

if ( i < MaxPersonas )<br />

return i;<br />

else return -1;<br />

El espaciado se refiere a separar ciertos elem<strong>en</strong>tos (operadores y paréntesis, principalm<strong>en</strong>te), <strong>de</strong> los<br />

argum<strong>en</strong>tos para que el conjunto sea más legible. El uso típico consiste <strong>en</strong> separar con un espacio<br />

los argum<strong>en</strong>tos <strong>en</strong> las listas <strong>de</strong> parámetros formales y <strong>de</strong> argum<strong>en</strong>tos, los corchetes <strong>de</strong>l operador <strong>de</strong><br />

subíndice, y los operadores como =, *. /, + y ­. Por ejemplo, compár<strong>en</strong>se las sigui<strong>en</strong>tes muestras:<br />

int x=a+b;<br />

int x = a + b;<br />

numRegistros=v.size()+registrosCabecera[i];<br />

numRegistros = v.size() + registrosCabecera[ i ];<br />

int z=elevarA(x,y);<br />

int z = elevarA( x, y );

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!