Anda di halaman 1dari 12

GuadeestilodeprogramacinenC++

Pequeosconsejossobrecmoescribirprogramasmslegibles.

ndice
1Introduccin........................................................................................................................................3 1.1Nomenclatura..............................................................................................................................3 2Indicacionesgenerales........................................................................................................................3 3Identificadores....................................................................................................................................4 3.1Identificadoresdeclases.............................................................................................................4 3.2Identificadoresdedatomiembros...............................................................................................5 3.3Identificadoresdeobjetos...........................................................................................................5 3.4Identificadoresdefuncionesmiembro........................................................................................5 3.5Identificadoresdevariableslocalesenfuncionesmiembro.......................................................6 3.5.1Declaracindevariables.....................................................................................................6 4Comentarios........................................................................................................................................7 4.1Comentariosdeiniciodebloque.................................................................................................7 4.2Comentariosaclaratorios............................................................................................................8 4.3Comentariossobrefuncionesmiembroofunciones...................................................................8 5Disposicindeelementos...................................................................................................................9 5.1Clases..........................................................................................................................................9 5.1.1Unidadesdetraduccin........................................................................................................9 5.2Funciones..................................................................................................................................10 5.2.1Estructurasdedecisinyrepeticin..................................................................................11 5.2.1.1Cuerposdeinstruccionesdeunasolalnea................................................................11 5.3Espaciado..................................................................................................................................12

1 Introduccin
Enestedocumentoseexplicabrevemente,yconejemplos,cmoescribirprogramasmslegibles.A lolargodesuvidaprofesional,cualquierprogramadorseplantealapreguntadecmoescribirsus programasdemaneraqueseanmslegibles,yportantoquepuedansermantenidos(correccinde errores, ampliacin de funcionalidad) con facilidad, tanto por l mismo como por otros programadores(unasituacintpicaencualquierempresa). Dado que la misma situacin en cuanto a legibilidad de cdigo suele ser resuelta por distintos programadores de la misma forma, pero con distintos matices de diferenciacin, es interesanteseguirunaguadeestiloquenosexpliquecomootrosresolvieronesemismoproblema, hastaquedichasolucinseconvirtienunestndar.

1.1 Nomenclatura
EnestedocumentosesiguelanomenclaturatpicadeC++,segnlacuallasoperacionesincluidas dentrodelasclasesseconocencomofuncionesmiembro,ylasvariables,tambinincluidas,como datosmiembro.

2 Indicacionesgenerales
Elpropsitodeseguirunanormadeestiloeshacerqueelcdigofuentedeunprogramaseatan legiblecomoseaposible.As,haytrespuntosbsicosquesedebencuidar:elespaciadohorizontal, elespaciadoverticalylaindentacin.Elespaciadohorizontalconsisteenquelaslneasenlasque estdivididoelcdigofuentedebenserdeunalongitudmximalomsprximaposiblea80 caracteres,yaquealimprimirelcdigoenpapelcualquierlneasuperiora80columnassedescarta automticamente. Unodelosproblemasquesepuedeencontraralcodificareslamaneramscorrectapara dividirunalneamuylarga.Respuestascomunesaestapreguntason:antesdeunasubexpresin, antesdeunoperador,oantesdeunparntesis.Porejemplo:
intx=((a*b+c)/(c*d*d)) +(a/(b*c)) +((3.1451927*b)+d) ;

Losoperadoresdebensepararsemedianteespaciosparamayorclaridad,aexcepcinhecha deoperadoresunarioscomoelincrementoodecremento,tantopostfijocomoprefijo,quesuelen colocarsepegadosaloperandoalquemodifican(lomstpico,porclaridad),perotambinpueden colocarseespaciados,aeleccindelprogramador.


intx=++i; inty=j+++++x;

Elespaciadoverticalconsisteencuntaslneasocupaunafuncinmiembro,ounaclase,en elcdigofuente.Engeneral,estilautoimponerseunlmitedeunahojaporcadafuncinmiembro o funcin. Es extrao, siempre que la funcin miembro no consista en multitud de acciones repetitivas(comoescribirenunarchivo),queunafuncinmiembrobiendiseadaocupemsallde un folio. En caso contrario, ser conveniente considerar que posiblemente sea interesante subdividirloenvariassubfuncionesmiembro(probablementedeaccesoprivado). Adems, en el espaciado vertical intervienen las llaves que se emplean para marcar el comienzoyfindelcuerpodeunafuncin,deunbucle,...cadaunadeesasllavespuedellegara

consumirunalneaporssola,inclusodos.As,parasalvaralgodeespaciovertical,sesuelen mantenerlasllavesdeaperturaycierre,cadaunaenunalnea,paraelcuerpodelasfunciones miembroyfunciones,yencambiocolocarlallavedeaperturaenlamismalneaparabuclesy estructurasdedecisin.Porejemplo:


intdividir(inta,intb) { if(b!=0){ returna/b; } return0; }

...sibienenunprogramarealsermuchomsadecuadoresponderalacontingenciaque suponedividirunnmeroentrecero,queresponderconcerosilenciosamente,locualsuponeun errornodetectado. Laindentacinesvitalparapodercomprenderrpidamenteloselementosfuncionalesdeun programa.As,elcuerpo(lasinstrucciones)deunafuncinofuncinmiembrodebeestaralineado ensumargenizquierdomsaladerechaquelacabeceradeunafuncin,delamismaformaqueun bucledentrodeesafuncinyassucesivamente.Porejemplo:


intelevarA(intx,unsignedinty) { inttoret=x; for(;y>1;y){ toret*=x; } returntoret; }

3 Identificadores
Losidentificadoresseutilizanenvarias(innumerables)ocasionesenprogramacin:clases,datos miembro, funciones miembro, constantes, variables locales ..., y son claves para entender qu valorespuedecontenerunavariable,quhaceunafuncinmiembrooaquobjetosrepresentauna clase.Poreso,hayqueponerespecialcuidadoensueleccin.Tambinserinteresanteseguirunas pequeasreglasalahoradeescribirunidentificadorquehaganqueasuvezpodamosobtenerel mximosignificadodelmismosiseestleyendoenunlistado. Engeneral,losidentificadoresdebensertancortoscomoseaposible,peroalaveztan informativoscomoseaposible.Muchasveces,adems,esimposibleutilizarunsolosustantivopara nombrarunavariable,funcinmiembrooclase;enesecaso,seconcatenarntodosparaformarel identificador final,poniendocadainicialenmayscula.Sibienalgunoslenguajesmodernos lo permiten(comoJava),atravsdelsoporte unicode,evtenselosacentos,lasdiresis...enlos identificadores.

3.1 Identificadoresdeclases
Losidentificadoresdeclasesdeberancorresponderseconsustantivosdelavidarealodelconcepto queseestmodelandoconelprograma.As,identificadoresdeclasespuedenser: Casa, Coche, Barco,Cuenta... Elidentificadordelaclase,encasodeestarcompuestopormsdeunapalabra,seconstruye

concatenandotodaslaspalabras,yponiendolainicialdecadaunadeestaspalabrasenmaysculas. Porejemplo:CuentaCorriente,VehiculoConMotor,VehiculoSinMotor.
classRectangulo{ //mscosas... }; classCuentaCorriente{ //mscosas... };

3.2 Identificadoresdedatomiembros
Losidentificadoresdedatosmiembrosiguenlasmismasnormasquelosdelasclases,peroconla primerainicialenminscula.As,porejemplo,identificadoresvlidossonidentificadorCompleto, precioEuros,...
classCuentaCorriente{ public: //mscosas... private: doublesaldoEuros; };

3.3 Identificadoresdeobjetos
Los identificadores de objetos siguen las mismas reglas que los identificadores de los datos miembro.
intmain(void) { CirculomiCirculoGrande(100); cout<<miCirculoGrande.calcularArea()<<endl; return0; }

3.4 Identificadoresdefuncionesmiembro
Losidentificadoresdefuncionesmiembrosiguenlas mismasreglasqueparadatosmiembro y objetos.Sinembargo,debenescogersedemaneraquesugierandemaneraintuitivaquhacen.As, elidentificadordebeserunverbooalmenosconteneruno.
intgetEdad(Persona); boolesPalindromo(conststring&);

Evtensenidentificadorescomolossiguientes:
intprocesar(constifstream&); stringpasoAuxiliar(conststring&); voidprocesaYCuenta(); //Mal:identificadornointuitivo //Mal:identificadorsimplementeerrneo //Mal:Dividirendosfunciones

Cuandounidentificadorcontieneunaconjuncincomo y,essignoinequvocodequela funcin que nombra realiza ms de una tarea y debe ser por tanto separada en dos funciones separadas. Losmejoresidentificadoressonaquellosquedescribenconunidentificadormscortolo

quehacelafuncinmiembro.Adems,esinteresanteseguirciertaspautas:enelcasodefunciones miembroquedevuelvenunbooleano(unvalorverdaderoofalso),esinteresantenombrarlosconun prefijoformadoporlosverbosseroestar,como:


esPalindromo(conststring&); esPar(int); fueModificada(constPersona&)const;

3.5 Identificadoresdevariableslocalesenfuncionesmiembro
Enelcasodevariableslocalesdefuncionesmiembro,existenvariasparticularidades.Porejemplo, alasvariableslocalesempleadasenbuclesselessueleasignaridentificadoresdeunaletratipo'i'y 'j',tambinenelcasodealgunosargumentossimples(sibienestecasoesmejor,sinembargo, evitarlo,cuandoseaposible,yasignaridentificadoresdescriptivos)defunciones.
stringcnvtMayusculas(string&s) { for(unsignedinti=0;i<numCaracteres;++i){ s[i]=toupper(s[i]); } } returns;

Los identificadores de variables tambin pueden informar sobre para qu se utiliza esa variable,ynorestringirseatansoloinformacinsobrequvaloresalberga.Porejemplo,enel cdigosiguientetoret(aretornar)esunavariablequeseutilizaentodaslasfuncionesparadevolver unvalor.
stringobtenerConsonantes(conststring&s) { staticconststringvocales=aeiou; stringtoret; for(unsignedinti=0;i<s.length();++i){ if(vocales.find(s[i])==string::npos){ //Noencontradoenvocales,aadir toret+=s[i]; } } } returntoret;

3.5.1 Declaracindevariables
Sedebecolocarcadavariableenunalnea,inclusosiendodelmismotipo.Sedebeevitar especialmentedeclararpunterosyvariablesdeunmismotipoenlamismalnea:
intx,y; intx,*p; //Esnecesariaunasegundamiradaparafijarseeny //definitivamentedesaconsejado

intmain() { intx; inty; charc; stringtoret; //mscosas...

return0;

C++ permite minimizar muchsimo ciertas expresiones. Por ejemplo, el siguiente bucle copiaraunacadenadecaracteresdeC(unvectordechar),enotradedestino:
char*copiaCadena(char*ptrDestino,char*ptrOrigen) { while(*ptrDestino++=*ptrOrigen++); } returnptrDestino;

Lasiguientefuncinrealizalamismatareaquelaanterior.Sinembargo,estperfectamente clarocundoelbucletermina(alllegaralamarcadefindecadenadelacadenadeorigen),cundo sehaceexplcitamenteunacopiaytambincuandodespusseincrementanamboscontadores.Es una funcin que se puede comprender de un vistazo, mientras que la anterior, an para un programadorconexperiencia,supondrinvertirunoscuantossegundos.Finalmente,lacalidaddel cdigomquinageneradaeslamismaenamboscasos,sibienesciertoqueelprimerejemplo generaunnmerodeinstruccionesalgomenor.
char*copiaCadena(char*ptrDestino,char*ptrOrigen) { while(*ptrOrigen!=0){ *ptrDestino=*ptrOrigen; ++ptrOrigen; ++ptrDestino; } } returnptrDestino;

4 Comentarios
Un comentario debe ser siempre clarificador, til, y, en cambio, cuanto ms corto mejor. En particular, debe cuidarse en no insultar la inteligencia del lector en determinadas ocasiones, comentando secuencias de cdigo obvias y desesperarlo al encontrarse con construcciones complejasquenotienenningncomentario.
intareaRectangulo=lado1*lado2; areaCirculo=PI*r*r; //calcularea //calculareadelcrculo //PIes3.1415927

En el contexto del ejemplo anterior, el tercer comentario es absolutamente innecesario, mientras que los dos primeros son cuestionables, siempre que los identificadores hayan sido escogidoscuidadosamente,comoeselcaso.

4.1 Comentariosdeiniciodebloque
Existendostipostiposbsicosdecomentarios,losquepodramosdenominarcomentariosencima, y los que podramos denominar comentarios a la derecha. Los ms recomendables son los primeros,puessuelenexplicarunbloquedecdigo,amododeprrafo,aclarandomucholalectura.

stringListaObjetos::toString()const { stringtoret; //Obtenerlasdescripcionesdelosobjetos for(unsignedinti=0;i<v.size();++i){ toret+=v[i]>toString()+'\n'; } //Formatear StringMan::trimCnvt(toret); StringMan::pasarMaysCnvt(toret); } returntoret;

4.2 Comentariosaclaratorios
Loscomentarios aladerecha debenemplearsecomomensajesaclaratorios,intentandomantener especialmenteenelloslaconcisin,puesesfcilquesealcancenrpidamentemsdeochenta caracteresenesalnea.Agravandoanmsesteltimoproblema,debencolocarsealejadosdel cdigoqueaclaranparaqueseanvisibles.
//Clculospreviosalrendering areaRectangulo=lado1*lado2 //encms

4.3 Comentariossobrefuncionesmiembroofunciones
Desde la llegada del lenguaje Java, y su herramienta de documentacin, Javadoc, se han generalizado los comentarios formateados con un determinado estilo, y aceptando unos determinados parmetros de documentacin embebidos en ellos. Para el lenguaje C++, existe tambinunequivalenteaJavadoc,laherramientaDoxygen1,degranaceptacin. As,cuandouncomentario,enlugardeempezarpor/*,comienzapor/**,ouncomentario de lnea, en lugar de empezar por //, comienza por ///, al pasar el cdigo por la herramienta Doxygen,stageneraladocumentacinrecogidaenvariosformatos(incluyendoelHTML,quelo haceidealparalasreferenciascruzadas).Estoscomentariostambinsontilesaldesnudo,porlo quedebencolocarseenlascabeceras(losficherosconextensin.h,dondesedeclaranlasclases; conslteselaseccinsobreunidadesdetraduccin),inmediatamenteantesdecadaclase,funcin miembro,odatomiembro.Sonlascabeceraslasquesernconsultadasporelprogramadorque utilicelaclaseparaconocersuinterfazpblica.
//rectangulo.h /** Laclasequerepresentaalosrectngulos */ classRectangulo{ public: /** *Constructorderectngulos *@parambLabasedelfuturorectngulo *@paramaLaalturadelfuturorectngulo */ Rectangulo(doubleb,doublea);

1 Doxygenpuedeencontrarseen:http://www.doxygen.org

/** *Calculaelreadelrectngulo *@returnElreadelrectngulo,segnsuslafos */ doublecalcularArea(); private: ///Lainformacinsobrelabasedelrectngulo doublebase; ///Lainformacinsobrelaalturadelrectngulo doublealtura; };

Delosparmetrosquesepuedenutilizarenestetipodecomentarios,destacan@param y @return.Elprimerosirveparadocumentarunparmetrodeunafuncinmiembro.talycomoseve enelconstructordelaclaseRectngulodeejemplo,msarriba.Elsegundosirveparadocumentar el valor de retorno de una funcin miembro, tal y como se aprecia en la funcin miembro calcularArea()delaclasedelmismoejemplo.

5 Disposicindeelementos
5.1 Clases
Debe escogerse una forma de disponer los miembros en la clase, y tratar de mantenerla. Por ejemplo,lamsextendidaconsisteencolocarlapartepblicadelaclaselomscercanaalaparte superior.stotienesentidoporquecuandotratedeleerelcdigo,alprogramadorleinteresalaparte pblicadelaclase,queeslaquetendrquemanejar,ynolaparteprivadaoprotegida,delaque slotendrquepreocuparsesieselquelamantiene.Portanto,unbuenesquemaescolocarprimero losmiembrospblicos,despuslosprotegidos,yfinalmentelosprivados.
///Laclasequerepresentaalospuntosdedosdimensiones classPunto{ public: ///@returnlacoordenadahorizontal intgetX()const; ///@returnlacoordenadavertical intgetY()const; private: intx; inty; };

5.1.1 Unidadesdetraduccin
EnterminologaC++,elcompiladortraduceacdigomquinaunidadesdetraduccin,queenel casomshabitualsonficherosconextensin.cpp(aveces,.cc),tambinconocidoscomoficheros deimplementacin,yaqueenellossedefinenlasfuncionesyfuncionesmiembro.Estosficheros normalmentetienenasociadosunosficherosdecabecera(conextensin.h),dondesedeclaranlos miembrospblicos.Esmuyimportanteladisposicindelosprototiposdelasfuncionespblicasy las declaraciones de las clases pblicas en las cabeceras, mientras que las respectivas implementacionesdebenaparecerenlosficherosdeimplementacin.
//punto.h #ifndef_PUNTO_H_ #define_PUNTO_H_ ///Laclasequerepresentaalospuntosdedosdimensiones classPunto{ public:

/** *Constructordeobjetospunto *@paramaLacoordenadahorizontal *@parambLacoordenadavertical */ Punto(inta=0,intb=0) {x=a;y=b;} ///@returnlacoordenadahorizontal intgetX(void)const; ///@returnlacoordenadavertical intgetY(void)const; private: intx; inty; }; externconstPuntopuntoOrigen; #endif //punto.cpp #includepunto.h constPuntoPuntoOrigen; intPunto::getX()const { returnx; } intPunto::getY()const { returny; } //elorigendecoordenadas

Lalnea#ifndef_PUNTO_H_ylasiguienteloquehacenesevitarquesecompilelacabecera punto.h msdeunavez.stopuedesucederinadvertidamenteenunproyectocomplejo,cuando msdeunacabeceraincluyelaprimera.Eldiagnsticodeesteproblemaessencillo,puesenese casoelcompiladorsequejaradeunaredeclaracindelaclasePunto. Ntesequesehaincluidounobjetoconstante.Parapoderserutilizadodebeserdeclarado enelficherodecabecera,sibiennuncadefinido(lacabecerapuedeserincluidaenvariasunidades detraduccin:ponerladefinicinenlacabecerasignificaraquetodasellastendranunobjeto puntoOrigendistinto,aunqueconelmismoidentificador,loqueprovocaraunerrordeenlace).La definicin,comopuedeverse,apareceenelficherodeimplementacin,mientrasqueenelfichero de cabecera aparece una declaracin con extern, de manera que el compilador sepa que est definidaenalgnmdulo(peroslouno). Si,encambio,sedeseaqueunobjetonoseapblico,debeomitirsecualquiermencinsobre lenlacabecera,yenelmomentodeladefinicinenelarchivodeimplementacindebeaadirse elmodificadorstatic(queenestecasodeaplicacinsignificaprivado,ynotiene,explcitamente, elmismosignificadoquecuandoseaplicaaunafuncinmiembrooaundatomiembro).

5.2 Funciones
En las funciones, se debe adoptar como esquema bsico la tpica estructura inicializacin desarrollolimpieza,esdecirelcomienzodelatarea,inicializando(ycreando,cuandoseaoportuno) lasvariablesnecesarias,eldesarrollodelproblema,comoelbucledelejemplosituadomsabajo,y finalmente,cuandoesnecesario,lalimpiezadelosrecursosutilizados.

intsumaFicheroDatos(conststring&idFichero) { intnum; inttoret=0; ifstreamf(idFichero.c_str()); if(f.isopen()){ f>>num; while(!f.eof(){ toret+=num; f>>num; } } } f.close();

returntoret;

5.2.1 Estructurasdedecisinyrepeticin
Es tpico encontrarse con la necesidad de tener que crear estructuras condicionales (if) o de repeticin (while), que se refieren a condiciones complejas. Debe tratarse, en estos casos, de disponerunasubcondicinporlnea,comenzandoporeljuntor(and(&&),or(||),ynot(!)).Sies necesario, una subcondicin puede llevar un comentario "a la derecha". Si existen varias subexpresionescondicionales,sedebenindentarrespectoalaexpresinprincipal.
if(buffer!=NULL &&f.isopen() &&tamMaxBufferDestino>0) { while(!f.eof()){ //mscosas... } if(f.eof() &&bytesLeidos>0) { memcpy(dest,buffer,tamMaxBufferDestino); }

Cuandosecreanestructurasdedecisinconmsdeunaexpresincondicional,nosedebe utilizarlaposibilidaddecrearloscuerposdeinstruccionesdeunasolalneasinlasllavesdeinicio yfindebloque({y}),yaquelasentencianoseravisible.


if(f.eof() &&bytesLeidos>0) f.close();

5.2.1.1 Cuerposdeinstruccionesdeunasolalnea

Engeneral,esmslegibleevitarestaposibilidad.Lassentenciasdeunbloquesinllavescasipasan desapercibidas,yportantoesmejorcambiarlasporbloquessiemprequeseaposible.Recurdese que los bloques de una sola lnea sin llaves de comienzo y fin son una posibilidad, no una obligacin.Encuantoalespaciovertical,colocarlallaveinicioenlamismalneadeunasentencia derepeticinodedecisin(siemprequenohayamltiplessubexpresionescondicionales),esuna medidaquepuedesermuytil. Enelcasodeunasentenciaifthenelseconslounaexpresincondicional,sepuedeutilizar laposibilidaddelosbloquessinllavesdecomienzoyfin,porejemplo:

Persona*VectorPersonas::buscarPersona(conststring&identificador) { unsignedinti; for(i=0;i<vPersonas.size();++i){ if(vPersonas[i]>getidentificador()==identificador){ break; } } if(i<vPersonas.size()) returnvPersonas[i]; else returnNULL;

5.3 Espaciado
Elespaciadoserefiereasepararciertoselementos(operadoresyparntesis,principalmente),delos argumentosparaqueelconjuntoseamslegible.Elusotpicoconsisteensepararconunespacio losargumentosenlaslistasdeparmetrosformalesydeargumentos,loscorchetesdeloperadorde subndice,ylosoperadorescomo=,*./,+y.Porejemplo,comprenselossiguientesejemplos:
intx=a+b; intx=a+b; numRegistros=v.size()+registrosCabecera[i]; numRegistros=v.size()+registrosCabecera[i]; intz=elevarA(x,y); intz=elevarA(x,y);

Estasnormasdeespaciadosehanseguidoalolargodelpresentedocumento.

Anda mungkin juga menyukai