El mundo de C++
Tiempo de lectura estimada: 11 minutos
Víctor JáquezEn carrera programé un par de cosas más o menos serias en C++: un toolkit gráfico para MSDOS y un derivador de funciones matriciales en particular. Yo me creía un buen programador de C++. ¡Pobre iluso! En últimas fechas, desde mi involucramiento en el proyecto de cajas populares de Juan José Salgado, que Raúl Vázquez ha venido desarrollando en C++, mis habilidades en C++ han tenido un resurgimiento y me han colocado en mi real perspectiva: sólo se que no se nada. He (re)descubierto el STL, las excepciones, conjugándolo con mi amor por los patrones de diseño de software.
Para mi suerte, en Aritma, han salido una serie de artículos "The Most Important C++ ... Ever" que me han mostrado un mundo mucho más grande y complejo del que había logrado percibir:
- The Most Important C++ Software...Ever
- The Most Important C++ Non-Book Publications...Ever
- The Most Important C++ Books...Ever
- The Most Important C++ People...Ever
- My Most Important C++ Aha! Moments...Ever
Revisando estas referencias, en el artículo non-book publications hay una liga al famoso documento Programming in C++, Rules and Recommendations. Después de revisarlo quedé descorazonado: mi código no sigue varias de la razonables reglas ahí mencionadas.
Fue en esta epifanía cuando me di cuenta del valor de la propuesta de Python: hacer obligatorias la buenas prácticas. Cuando las buenas prácticas son opcionales, el ciclo de aprendizaje para escribir programas de manera profesional resulta muy grande, en muchas ocasiones jamás se logra.
He decido hacer una lista de verificación sobre el código autogenerado por DAOGen con las reglas que este documento indica:
- Rec. 1: Optimize code only if you know that you have a performance problem. Think twice before you begin. No he optimizado nada por que los algoritmos hasta ahora son simples y directos.
- Rec. 2: If you use a C++ compiler that is based on Cfront, always compile with the +w flag set to eliminate as many warnings as possible. Uso -Wall
- Rule 1: Include files in C++ always have the file name extension ".hh". Me gusta más hpp ok
- Rule 2: Implementation files in C++ always have the file name extension ".cc". Me gusta más cpp ok
- Rule 3: Inline definition files always have the file name extension ".icc". No, los tengo en archivo hpp... No se qué tan válido sea esto.
- Rec. 3: An include file should not contain more than one class definition. ok
- Rec. 4: Divide up the definitions of member functions or functions into as many files as possible. ok
- Rec. 5: Place machine-dependent code in a special file so that it may be easily located when porting code from one machine to another. No aplica... aún...
- Rule 12: The identifier of every globally visible class, enumeration type, type definition, function, constant, and variable in a class library is to begin with a prefix that is unique for the library. ok
- Rule 13: The names of variables, constants, and functions are to begin with a lowercase letter. Las variables sí, las constantes aún no uso y las funciones... no, precisamente las acabo de cambiar a mayúsculas y me parece más correcto...
- Rule 14: The names of abstract data types, structures, typedefs, and enumerated types are to begin with an uppercase letter. ok
- Rule 15: In names which consist of more than one word, the words are written together and each word that follows the first is begun with an uppercase letter. Sólo ha ocurrido en funciones. ok
- Rule 16: Do not use identifiers which begin with one or two underscores (_ or __). ok
- Rule 17: A name that begins with an uppercase letter is to appear directly after its prefix. Es igual que en la regla 13
- Rule 18: A name that begins with a lowercase letter is to be separated from its prefix using an underscore (_). Es igual que la regla 13
- Rule 19: A name is to be separated from its suffix using an underscore (_). Es igual que la regla 13
- Rec. 14: Do not use typenames that differ only by the use of uppercase and lowercase letters. Al igual que los items pasados, hay que recordar que esto también depende del esquema de la base de datos. Tendría que seguir esto lineamientos también.
- Rec. 15: Names should not include abbreviations that are not generally accepted. ok
- Rec. 16: A variable with a large scope should have a long name. Creo que no aplica hasta ahora
- Rec. 17: Choose variable names that suggest the usage. ok
- Rec. 18: Write code in a way that makes it easy to change the prefix for global identifiers. ok
- Rec. 19: Encapsulate global variables and constants, enumerated types, and typedefs in a class. ok
- Rule 20: The public, protected, and private sections of a class are to be declared in that order (the public section is declared before the protected section which is declared before the private section). ok
- Rule 21: No member functions are to be defined within the class definition. ¡Not OK! Debo usar inlines.
- Rec. 20: Always provide the return type of a function explicitly. ok
- Rec. 21: When declaring functions, the leading parenthesis and the first argument (if any) are to be written on the same line as the function name. If space permits, other arguments and the closing parenthesis may also be written on the same line as the function name. Otherwise, each additional argument is to be written on a separate line (with the closing parenthesis directly after the last argument). ok
- Rec. 22: In a function definition, the return type of the function should be written on a separate line directly above the function name. ¡Not OK! A mi me gusta como está
- Rec. 23: Always write the left parenthesis directly after a function name. ¡Not OK! A mi me gusta como está
- Rec. 24: Braces ("{}") which enclose a block are to be placed in the same column, on separate lines directly before and after the block. ok
- Rec. 25: The flow control primitives if, else, while, for and do should be followed by a block, even if it is an empty block. ok
- Rec. 26: The dereference operator `-' and the address-of operator `&' should be directly connected with the type names in declarations and definitions. ¡Not OK! me he resistido por mi herencia de C a hacer esto, pero tal vez tengan razón
- Rec. 27: Do not use spaces around `.' or `->', nor between unary operators and operands. ok
- Rec. 28: Use the c++ mode in GNU Emacs to format code. ok, más otras cosillas que rompen algunas cosas aquí recomendadas :S
- Rule 22: Never specify public or protected member data in a class. ok
- Rec. 29: Access functions are to be inline. ¡Not OK!
- Rec. 30: Forwarding functions are to be inline. ¡Not OK!
- Rec. 31: Constructors and destructors must not be inline. ok
- Rec. 32: Friends of a class should be used to provide additional functions that are best kept outside of the class. I don't know... but I suspect that my use of the << overloading is wrong.
- Rule 23: A member function that does not affect the state of an object (its instance variables) is to be declared const. ¡Not always!
- Rule 24: If the behaviour of an object is dependent on data outside the object, this data is not to be modified by const member functions. ¡Not always!
- Rule 25: A class which uses "new" to allocate instances managed by the class, [i.e. instances bound to member variables of pointer or reference type that are deallocated by the object.] must define a copy constructor. Aun no aplica
- Rule 26: All classes which are used as base classes and which have virtual functions, must define a virtual destructor. ok
- Rec. 33: Avoid the use of global objects in constructors and destructors. ok
- Rule 27: A class which uses "new" to allocate instances managed by the class, [i.e. instances bound to member variables of pointer or reference type that are deallocated by the object.] must define an assignment operator. Aun no aplica
- Rule 28: An assignment operator which performs a destructive action must be protected from performing this action on the object upon which it is operating. Aún no aplica
- Rec. 34: An assignment operator ought to return a const reference to the assigning object. ¡Not OK!
- Rec. 35: Use operator overloading sparingly and in a uniform manner. ok
- Rec. 36: When two operators are opposites (such as == and !=), it is appropriate to define both. ok
- Rule 29: A public member function must never return a non-const reference or pointer to member data. ¡No siempre!
- Rule 30: A public member function must never return a non-const reference or pointer to data outside an object, unless the object shares the data with other objects. Creo que ok
- Rec. 37: Avoid inheritance for parts-of relations. ok
- Rec. 38: Give derived classes access to class type member data by declaring protected access functions. ok
- Rec. 39: Do not attempt to create an instance of a class template using a type that does not define the member functions which the class template, according to its documentation, requires. ok
- Rec. 40: Take care to avoid multiple definition of overloaded functions in conjunction with the instantiation of a class template. ok
- Rule 31: Do not use unspecified function arguments (ellipsis notation). ok
- Rec. 41: Avoid functions with many arguments. Cuando se puede
- Rec. 42: If a function stores a pointer to an object which is accessed via an argument, let the argument have the type pointer. Use reference arguments in other cases. ¡Not OK!
- Rec. 43: Use constant references (const &) instead of call-by-value, unless using a pre-defined data type or a pointer. ¡Not OK!
- Rec. 44: When overloading functions, all variations should have the same semantics (be used for the same purpose). ok
- Rule 32: The names of formal arguments to functions are to be specified and are to be the same both in the function declaration and in the function definition. ok
- Rule 33: Always specify the return type of a function explicitly. ok
- Rule 34: A public function must never return a reference or a pointer to a local variable. ok... pero tengo que revisarlo
- Rule 35: Do not use the preprocessor directive #define to obtain more efficient code; instead, use inline functions. No aplica pero es buena idea
- Rec. 45:Use inline functions when they are really needed. ok
- Rec. 46: Minimize the number of temporary objects that are created as return values from functions or as arguments to functions. ok
- Rec. 47: Avoid long and complex functions. ok
- Rule 36: Constants are to be defined using const or enum; never using #define. ok
- Rule 37: Avoid the use of numeric values in code; use symbolic values instead. ok
- Rule 38: Variables are to be declared with the smallest possible scope. ok
- Rule 39: Each variable is to be declared in a separate declaration statement. No ok
- Rule 40: Every variable that is declared is to be given a value before it is used. No ok
- Rule 41: If possible, always use initialization instead of assignment. No ok
- Rule 42: Do not compare a pointer to NULL or assign NULL to a pointer; use 0 instead. [An intensive debate about this has been raging in the news group comp.lang.c++. Future changes in this recommendation may occur.] No aplica hasta ahora
- Rec. 48: Pointers to pointers should whenever possible be avoided. No ok
- Rec. 49: Use a typedef to simplify program syntax when declaring function pointers. No ha aplicado
- Rule 43: Never use explicit type conversions (casts). ok
- Rule 44: Do not write code which depends on functions that use implicit type conversions. ok
- Rule 45: Never convert pointers to objects of a derived class to pointers to objects of a virtual base class. ok
- Rule 46: Never convert a const to a non-const. ok
- Rule 47: The code following a case label must always be terminated by a break statement. no aplica hasta ahora
- Rule 48: A switch statement must always contain a default branch which handles unexpected cases. no aplica hasta ahora
- Rule 49: Never use goto. OK ;)
- Rec. 50: The choice of loop construct (for, while or do-while) should depend on the specific use of the loop. ok
- Rec. 51: Always use unsigned for variables which cannot reasonably have negative values. ¡No ok!
- Rec. 52: Always use inclusive lower limits and exclusive upper limits. ok
- Rec. 53: Avoid the use of continue. ok
- Rec. 54: Use break to exit a loop if this avoids the use of flags. ok
- Rec. 55: Do not write logical expressions of the type if(test) or if(!test) when test is a pointer. ok
- Rec. 56: Use parentheses to clarify the order of evaluation for operators in expressions. ok
- Rule 50: Do not use malloc, realloc or free. ok
- Rule 51: Always provide empty brackets ("[]") for delete when deallocating arrays. ¡Not OK!
- Rec. 57: Avoid global data if at all possible. ok
- Rec. 58: Do not allocate memory and expect that someone else will deallocate it later. ¡not ok in factory!
- Rec. 59: Always assign a new value to a pointer that points to deallocated memory. Check it out!
- Rec. 60: Make sure that fault handling is done so that the transfer to exception handling (when this is available in C++) may be easily made. ok
- Rec. 61: Check the fault codes which may be received from library functions even if these functions seem foolproof. ok
Las portability recommendations & rules las dejaremos para otro día. Estoy ya fue demasiada información.
Mi gran conclusión en este momento es que C++ no es C. Absolutamente. Son cosas distintas. Entonces, ¡Qué gran estupidez es escribir "Se requieren conocimientos de C/C++"! Recursos Humanos no tiene idea de lo que se necesita.