Está en la página 1de 241

C++

STL, Plantillas, Excepciones, Roles y Objetos.

por

Ricardo Devis Botella INFOPLUS, S.L.


devis@ieee.org

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 2

A Consol, Richi y Andrea.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 3

AGRADECIMIENTOS
Este libro es el resultado de casi dos aos de trabajo, en los cuales he aadido, corregido, modificado y aun eliminado captulos enteros. En tal perodo han cabido artculos, conferencias, mesas redondas, intercambios de correo y cientos de horas de lectura tcnica; como tambin muchas personas que han influido directa o indirectamente en el trabajo que el lector tiene ahora en sus manos. Los amigos y colegas de APTO2 (Juan Manuel Cueva, Csar Prez-Chirinos, Miguel Katrib, Luis Joyanes, Pablo Pelez y otros muchos) han contribuido con sus inestimables ideas y su espritu crtico, en las diversas conferencias en que hemos coincidido (as como en largusimas conversaciones telefnicas), a refinar algunos de los puntos expuestos en el texto. Ha resultado valiossima tambin la colaboracin de muchos annimos lectores (ya no tan annimos) que mandaron correos con sugerencias y crticas. Antonio Vzquez corrigi el texto con una celeridad y diligencia impresionantes, y Jos Bernabu busc un hueco entre viaje y viaje para leerlo: mi gratitud para ambos. A Daniel Alonso le debo un mucho de amabilidad y ayuda. A Mara Teresa Gmez-Mascaraque, de Editorial Paraninfo, quisiera agradecerle, por fin, su paciencia con un original que ha sufrido retraso tras retraso. Mi familia merece una mencin aparte: mis hijos, Ricardo y Andrea, se han acostumbrado a que los besara entre prrafo y prrafo, y para mi esposa, Consol, es como si me hubiera trasladado durante mucho tiempo a otro huso horario. Al menos me ha librado de pasear al perro, Spock, durante algunos meses. Espero, en definitiva, que el lector disfrute tanto leyendo este libro como yo disfrut escribindolo.

Alicante, julio 1996. Ricardo Devis Botella

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 4

i
NDICE
AGRADECIMIENTOS................................................................................................................................................. 4 NDICE............................................................................................................................................................................ 5 INTRODUCCIN.......................................................................................................................................................12 A QUIN VA DIRIGIDO ESTE LIBRO?.............................................................................................................12 SOBRE EL AUTOR.................................................................................................................................................13 UNA VISIN PANORMICA ....................................................................................................................................13 Captulo 1 - Objetos: Hitos, Mitos y Ritos...................................................................................................13 Captulo 2 - Contenedores en C++ .............................................................................................................14 Captulo 3 - C++ STL: La Biblioteca Estndar de Plantillas en C++.................................................14 Captulo 4 - Manejo de Excepciones en C++............................................................................................14 Captulo 5 - Asignacin en C++ ..................................................................................................................15 Captulo 6 - Patrones de Diseo: La Calidad Sin Nombre .....................................................................15 Captulo 7 - Roles y Objetos en C++...........................................................................................................15 Captulo 8 - Bases de Datos Orientadas-a-Objetos...................................................................................16 Captulo 9 - Consideraciones Prcticas.....................................................................................................16 Captulo 10 - Gestin de Proyectos Orientados-a-Objetos.....................................................................16 Captulo 11 - Modelos de Roles: El Mtodo Ooram.................................................................................16 Captulo 12 - Bibliografa Comentada .......................................................................................................17 GARANTA .............................................................................................................................................................17 OBJETOS: HITOS, MITOS Y RITOS ...................................................................................................................18
MITO 1: UN LENGUAJE ORIENTADO-A-OBJETOS PURO ES MEJOR QUE OTRO HBRIDO......................18 MITO 2: PARA APRENDER A USAR ADECUADAMENTE C++ HAY QUE EMPEZAR POR SMALLTALK. ......19 MITO 3: C++ ES MS FCIL DE ASIMILAR PARA LOS PROGRAMADORES DE C. ............................................19 MITO 4: LAS HERRAMIENTAS OOCASE INTEGRADAS GENERAN CDIGO ORIENTADO-A-OBJETOS FIABLE. .....................................................................................................................................................................20 MITO 5: LA HERENCIA ES UNA CUALIDAD ESENCIAL DE LOS SISTEMAS ORIENTADOS-A-OBJETOS........20 MITO 6: LA HERENCIA ES UN MECANISMO INDISPENSABLE EN LOS LENGUAJES DE PROGRAMACIN ORIENT ADOS-A-OBJETOS.......................................................................................................................................21 MITO 7: LA HERENCIA NICAMENTE SE PUEDE APLICAR CUANDO SE DA UNA RELACIN ES-UN....21 MITO 8: EXISTEN DEMASIADAS METODOLOGAS DE ANLISIS Y DISEO ORIENTADAS-A-OBJETOS.....22 MITO 9: CADA EMPRESA DEBE ADAPTAR A SU MANERA LOS MTODOS EXISTENTES PARA CONSTRUIRSE UNO A MEDIDA..........................................................................................................................22 MITO 10: LO PRIMERO QUE HAY QUE HACER ES CREAR UNA BIBLIOTECA DE CLASES REUTILIZABLES.23

CONTENEDORES Y PLANTILLAS.......................................................................................................................24 DISEO DE CONTENEDORES.............................................................................................................................25

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 5

LA OPCIN INGENUA: CUESTIN DE MBITOS.........................................................................................26 LA TRAMPA DEL PREPROCESADOR..............................................................................................................27 CUANDO LA HERENCIA ES DISPUTADA ......................................................................................................30 HERENCIA MLTIPLE: MS DE LO MISMO?..............................................................................................41 ITERADORES..........................................................................................................................................................42 LAS PLANTILLAS: CON HERENCIA, SIN ELLA O A SU PESAR................................................................43 C++ STL.......................................................................................................................................................................46 ESTRUCTURA DE LA BIBLIOTECA..................................................................................................................47 CONTENEDORES ...................................................................................................................................................48 ITERADORES..........................................................................................................................................................50 ALGORITMOS........................................................................................................................................................56 FUNCIONES-OBJETO U OBJETOS-FUNCIONES?.........................................................................................57 DE LOS PELIGROS DE LA EXTENSIBILIDAD.................................................................................................59 LEVES CRTICAS...................................................................................................................................................62 APRENDIZAJE Y DOCUMENTACIN..............................................................................................................63 REFERENCIAS DIRECTAS...................................................................................................................................64 MANEJO DE EXCEPCIONES EN C++...................................................................................................................65 LOS CDIGOS DE ERROR....................................................................................................................................65 CONCEPTOS BSICOS.........................................................................................................................................68 MANOS A LA OBRA ............................................................................................................................................70 CLASES DE EXCEPCIONES .................................................................................................................................73 JERARQUAS DE CLASES DE EXCEPCIONES ................................................................................................73 EL DESBOBINADO DE LA PILA.........................................................................................................................74 CONSISTENCIA DE ESTADOS...........................................................................................................................75 ADQUISICIN DE RECURSOS VA INICIALIZACIN..................................................................................76 ESPECIFICACIN DE INTERFACES ..................................................................................................................78 EL FINAL DE LA CUERDA ..................................................................................................................................79 VULNERACIN DE LA ESPECIFICACIN DE EXCEPCIONES ....................................................................80 CONCLUSIONES ....................................................................................................................................................81 REFERENCIAS DIRECTAS...................................................................................................................................81 ASIGNACIN EN C++..............................................................................................................................................83 CONCEPTOS BSICOS.........................................................................................................................................83 EL OPERADOR DE ASIGNACIN POR DEFECTO..........................................................................................84 LOS LMITES EXPLCITOS DE LA ASIGNACIN IMPLCITA....................................................................85 LA COPIA DE UN PUNTERO GENERA ... OTRO PUNTERO! ......................................................................87 ASIGNACIN NO ES INICIALIZACIN...........................................................................................................87 EL OPERADOR POR DEFECTO RESULTA DEFECTUOSO............................................................................88 EL OPERADOR DE ASIGNACIN EXPLCITO................................................................................................89 DESIGNACIN NO ES ASIGNACIN................................................................................................................90 LO QUE LA ASIGNACIN PRODUCE...............................................................................................................91 CONVERSIN, CONSTRUCCIN Y ASIGNACIN.........................................................................................92 LA ASIGNACIN EN JERARQUAS DE HERENCIA......................................................................................93 ASIGNACIN NO ES TRANSMUTACIN.......................................................................................................93 RECURSIVIDAD EXPLCITA: CSAR O NADA..............................................................................................94 CUIDADO CON LA AUTO-ASIGNACIN .......................................................................................................95 IDENTIDAD, IGUALDAD Y ... FRATERNIDAD? ..........................................................................................97 SOBRE LA ASIGNACIN BIDIRECCIONAL....................................................................................................98 POLIMORFISMO EN ASIGNACIN ................................................................................................................100 CUANDO LA ASIGNACIN ES INDESEABLE..............................................................................................101 LA ASIGNACIN CON CLASES BASE VIRTUALES ...................................................................................102

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 6

ALGUNOS CONFUSOS CONSEJOS..................................................................................................................103 REFERENCIAS DIRECTAS.................................................................................................................................103 PATRONES DE DISEO........................................................................................................................................105 LA CALIDAD SIN NOMBRE .............................................................................................................................105 PATRONES DE DISEO SOFTWARE .............................................................................................................106 CATLOGOS DE PATRONES ...........................................................................................................................108 PATRONES ORIENTADOS-A-OBJETOS?.....................................................................................................109 TELEPREDICADORES DE SOFTWARE ..........................................................................................................109 PATRONES ELECTRNICOS ............................................................................................................................110 ROLES Y OBJETOS EN C++ ................................................................................................................................113 CLASES DE ROLES..............................................................................................................................................114 UNA BUENA HERENCIA LO ARREGLA TODO? ........................................................................................115 DINMICA DE CLASES.....................................................................................................................................116 LA HERENCIA INNECESARIA .........................................................................................................................117 DIVIDE Y HEREDARS......................................................................................................................................120 EL PATRON DE ROLES INTERCAMBIABLES...............................................................................................123 EL PATRON DE ESTADOS ................................................................................................................................124 EL PATRN PROXY DE SUBROGACIN.......................................................................................................125 CONVERSIONES E INDIRECCIN....................................................................................................................126 CONCURRENCIA Y SECUENCIACIN DE ROLES .......................................................................................129 EN LA ASOCIACIN EST LA FUERZA.......................................................................................................130 LA CITA DEL DESASOSIEGO ...........................................................................................................................135 REFERENCIAS DIRECTAS.................................................................................................................................135 BASES DE DATOS ORIENTADAS-A-OBJETOS ............................................................................................137 DEGRADADO DE BASES DE DATOS.............................................................................................................137 LOS DESEOS DEL PROGRAMADOR...............................................................................................................139 PERSISTENCIA, TRANSITORIEDAD Y MATRICES ....................................................................................140 ORTOGONALIDAD DE PERSISTENCIA Y TIPO...........................................................................................140 CRTICA DE LA RAZN PRCTICA ..............................................................................................................142 INTERNET: CMO NO? ....................................................................................................................................142 CONSIDERACIONES PRCTICAS ....................................................................................................................144 PANORAMA PARA MATAR...........................................................................................................................145 REFLEXIONES REBAJADAS.............................................................................................................................146 Distribucin Jerrquica Csmica de Clases............................................................................................146 El Paradigma M2VC.....................................................................................................................................147 Arquitectura Grfica MultiModal..............................................................................................................148 Gestin de Concurrencias............................................................................................................................151 Gestin de Objetos a travs de Vistas........................................................................................................155 Incidencias de Usuarios...............................................................................................................................160 Actualizacin de Vistas ................................................................................................................................162 Seguridad del Sistema ..................................................................................................................................166 Gestin de Objetos mediante Colecciones................................................................................................171 Esquema de Consultas..................................................................................................................................172 Gestin de Dependencias entre Vistas.......................................................................................................178 GESTIN DE PROYECTOS ..................................................................................................................................181 EL SNDROME DE ESTOCOLMO.....................................................................................................................181 ANLISIS Y DISEO ORIENTADOS-A-OBJETOS.......................................................................................182 MTODOS COMERCIALES DE OOA/OOD....................................................................................................182

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 7

SOBRE LISTAS Y COMPARACIONES ............................................................................................................184 CSAR O NADA ..................................................................................................................................................185 LA SOLUCIN ECLCTICA...............................................................................................................................186 HERRAMIENTAS OOCASE...............................................................................................................................187 GESTIN DE PROYECTOS ORIENTADOS-A-OBJETOS..............................................................................187 SSIFO REDIVIVO.................................................................................................................................................188 MODELOS DE ROLES ...........................................................................................................................................189 ESCENARIOS Y APREHENSIONES ..................................................................................................................190 TRAS DIVIDIR HAY QUE MULTIPLICAR......................................................................................................192 EL LIBRO................................................................................................................................................................194 IDEAS PRINCIPALES ..........................................................................................................................................194 MODELADO DE ROLES .....................................................................................................................................195 SNTESIS DE MODELOS DE ROLES ................................................................................................................195 PUENTE A LA IMPLEMENTACIN................................................................................................................196 CREACIN DE COMPONENTES REUTILIZABLES ......................................................................................196 LEA, LECTOR: LEA..............................................................................................................................................197 REFERENCIAS DIRECTAS.................................................................................................................................197 BIBLIOGRAFA COMENTADA ...........................................................................................................................201 LIBROS BSICOS SOBRE C++..........................................................................................................................201 The C++ Workbook, por Richard S. Wiener & Lewis J. Pinson, 1990, Addison-Wesley, 0-20150930-X, 349 pg. .........................................................................................................................................201 A C++ Toolkit, por Jonathan S. Shapiro, 1990, Prentice Hall............................................................202 On to C++, por Patrick Henry Winston, 1994, Addison-Wesley, 0-201-58043-8.............................203 C++ Primer, 2 nd Edition, por Stanley B. Lippman, 1991, Addison-Wesley, 0-201-54848-8, 614 pg. ...........................................................................................................................................................................203 Mastering Object-Oriented Design in C++, por Cay S. Horstmann, 1995, John Wiley & Sons, 0471-59484-9. ..................................................................................................................................................204 Object-Oriented Design for C++, por Tsvi Bar-David, 1993, Prentice-Hall, 0-13-630260-2. .......204 The C++ Programming Language, 2 nd Edition, por Bjarne Stroustrup, 1991, Addison-Wesley, 0201-53992-6, 669 pg. .................................................................................................................................205 The Annotated C++ Reference Manual, por Margaret A. Ellis & Bjarne Stroustrup, 1990, Addison-Wesley, 0-201-51459-1, 447 pg................................................................................................206 The Design and Evolution of C++, por Bjarne Stroustrup, 1994, Addison-Wesley, 0-201-54330-3.206 Algorithms in C++, por Robert Sedgewick, 1992, Addison-Wesley, 0-201-51059-6.......................207 LIBROS DE ESTILO EN C++...............................................................................................................................207 Effective C++: 50 Specific Ways to Improve Your Programs and Designs, por Scott Meyers, 1992, Addison-Wesley, 0-201-56364-9.................................................................................................................207 C++ Programming Style, por Tom Cargill, 1992, Prentice Hall, 0-201-56365-7............................208 C++ Programming Guidelines, por Thomas Plum & Dan Saks, 1991, Plum Hall, 0-911537-10-4, 274 pg............................................................................................................................................................208 Taligents Guide To Designing Programs: Well-Mannered Object-Oriented Design in C++, por Taligent Inc., 1994, Addison-Wesley, 0-201-40888-0.............................................................................209 LIBROS DE PROGRAMACIN MEDIA Y AVANZADA EN C++...............................................................210 C++ IOStreams Handbook, por Steve Teale, 1993, Addison-Wesley, 0-201-59641-5.....................210 Advanced C++ Programming Styles and Idioms, por James O. Coplien, 1992, Addison-Wesley, 0201-54855-0. ..................................................................................................................................................210 The Power of Frameworks for Windows and OS/2 Developers, por Taligent Inc., 1995, AddisonWesley, 0-201-48348-3. ................................................................................................................................211 Data Abstraction and Object-Oriented Programming in C++, por Keith E. Gorlen, Sanford M. Orlow & Perry S. Plexico, 1990, John Wiley & Sons, 0-471-92346-X, 403 pg...............................212

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 8

C++ Strategies and Tactics, por Robert B. Murray, 1993, Addison-Wesley, 0-201-56382-7, 273 pg....................................................................................................................................................................213 Designing and Coding Reusable C++, por Martin D. Carroll y Margaret A. Ellis, 1995, AddisonWesley, 0-201-51284-X.................................................................................................................................213 Taming C++: Pattern Classes and Persistence for Large Projects, por Jiri Soukup, 1994, AddisonWesley, 0-201-52826-6. ................................................................................................................................214 LIBROS SOBRE SMALLTALK.................................................................................................................................214 Programacin Orientada a Objetos: Aplicaciones con Smalltalk, Angel Morales & Francisco J. Segovia, 1993, Paraninfo, 84-283-2019-5. ..............................................................................................215 Smalltalk Programming for Windows, Dan Shafer con Scott Herndon y Laurence Rozier, 1993, Prisma Publishing, 1-55959-237-5............................................................................................................215 Object Oriented Programming, Peter Coad & Jill Nicola, 1993, Prentice-Hall, 0-13-032616-X, con disquete del cdigo C++ y Smalltalk................................................................................................215 Discovering Smalltalk, Wilf LaLonde, 1994, Benjamin Cummings, 0-8053-2720-7.........................216 Smalltalk -80: The Language, Adele Goldberg & David Robson, 1989, Addison-Wesley, 0-20113688-0............................................................................................................................................................216 Smalltalk -80: The Interactive Programming Environment, Adele Goldberg, 1984, Addison-Wesley, 0-201-11372-4................................................................................................................................................217 Inside Smalltalk I, Wilf LaLonde & John Pugh, 1990, Prentice-Hall, 0-13-468414-1. ...................217 Inside Smalltalk II, Wilf LaLonde & John Pugh, 1990, Prentice-Hall, 0-13-465964-3...................217 Smalltalk/V: Practice and Experience, Wilf LaLonde & John Pugh, 1994, Prentice-Hall, 0-13814039-1, con disquete. ...............................................................................................................................218 IBM Smalltalk: The Language, por David N. Smith, 1994, Addison-Wesley, 0-8053-0908-X........218 Smalltalk Best Practice Patterns - Volume 1: Coding, por Kent Beck................................................218 LIBROS SOBRE JAVA .........................................................................................................................................219 Hooked on Java: Creating Hot Web Sites with Java Applets, por Arthur van Hoff, Sami Shaio y Orca Starbuck, 1995, Addison-Wesley, 0-201-48837-X, con CD-ROM. .............................................219 Mecklermedias Official Internet World 60 Minute Guide to Java, por Ed Tittel y Mark Gaither, 1995, IDG Books, 1-56884-711-4...............................................................................................................220 Java!, por Tim Ritchey, 1995, New Riders Publishing, 1-556205-533-X. ..........................................220 The Java Handbook: The Authoritative Guide to the Java Revolution, por Patrick Naughton, 1996, Osborne McGraw Hill, 0-07-882199-1. .........................................................................................220 The Java Primer Plus: Supercharging Web Applications with the Java Programming Language, por Paul M. Tma, Gabriel Torok y Troy Downing, 1996, Wayte Group Press, 1-57169-062-X. ..221 LIBROS SOBRE SOFTWARE ORIENTADO-A-OBJETOS............................................................................221 Object-Oriented Software Construction, por Bertrand Meyer, 1988, Prentice Hall, 0-13-6290310,534 pg.........................................................................................................................................................221 A Book of Object-Oriented Knowledge, por Brian Henderson-Sellers, 1991, Prentice Hall, 0-13059445-8, 297 pg. .......................................................................................................................................222 Object-Oriented Methods, 2 nd Edition, por Ian M. Graham, 1994, Addison-Wesley, 0-201-59371-8, 473 pg............................................................................................................................................................223 Object-Oriented Programming, por Peter Coad y Jill Nicola, 1993, Prentice Hall-Yourdon Press, 0-13-032616-X, 582 pgs. y disquete incluido........................................................................................223 LIBROS DE ANLISIS Y DISEO ORIENTADO-A-OBJETOS (OOA & OOD) ........................................224 Designing Object-Oriented Software, por Rebecca Wirfs-Brock, Brian Wilkerson & Lauren Wiener, 1990, Addison-Wesley, 0-13-629825-7, 368 pg.....................................................................................224 Using CRC Cards: An Informal Approach to Object-Oriented Development, por Nancy M. Wilkinson, 1995, SIGS Books, 1-884842-07-0 (Prentice-Hall 0-13-374679-8), 226 pgs.............225 Object-Oriented Modeling and Design, por James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy & William Lorensen, 1991, Prentice Hall, 0-13-629841-9, 528 pg. ....................226 Object-Oriented Analysis and Design with Applications, 2 nd Edition, por Grady Booch, 1994, Benjamin/Cummings, 0-8053-5340-2, 589 pg. ......................................................................................227

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 9

Migrating to Object Technology, por Ian M. Graham, 1994, Addison-Wesley, 0-201-59389-0, 552 pg....................................................................................................................................................................228 Object-Oriented Analysis, 2nd Edition, por Peter Coad & Edward Yourdon, 1991, Yourdon Press/Prentice Hall, 233 pg.......................................................................................................................228 Object-Oriented Design, por Peter Coad & Edward Yourdon, 1991, Prentice Hall, 0-13-630070-7.229 Object-Oriented Analysis: Modeling the World in Data, por Sally Shlaer & Stephen J. Mellor, 1988, Yourdon Press/Prentice Hall, 144 pg...........................................................................................229 Object Lifecycles: Modeling the World in States, por Sally Shlaer & Stephen J. Mellor, 1991, Prentice Hall, 0-13-629940-7. ....................................................................................................................229 Object-Oriented Systems Analysis: A Model-Driven Approach, por David W. Embley, Barry D. Kurtz & Scott N. Woodfield, 1992, Prentice Hall, 0-13-629973-3, 302 pg......................................230 Object-Oriented Software Engineering: A Use Case Driven Approach, por Ivar Jacobson, Magnus Christerson, Patrik Jonsson y Gunnar vergaard, 1992, Addison-Wesley, 0-201-54435-0, 524 pgs. .................................................................................................................................................................230 Object Oriented Program Design with Examples in C++, por Mark Mullin, 1990, Addison-Wesley, 0-201-51722-1, 303 pg...............................................................................................................................231 A Complete Object-Oriented Design Example, por Joseph E. Richardson, Ronald C. Schultz & Edward V. Berard, 1992, Berard Software Engineering Inc, 1-881974-01-4, 350 pg...................231 Working With Objects: The OOram Software Engineering Method, por Trygve Reenskaug con Per Wold y Odd Arild Lehne, 1996, Manning Publications, 1 -884777-10-4 (Prentice Hall: 0-13452930-8)........................................................................................................................................................232 LIBROS SOBRE PATRONES DE DISEO .............................................................................................................232 Notes on the Synthesis of Design, de Christopher Alexander, 1964, Harvard University Press. ...232 A Pattern Language: Towns/Building/Construction, de Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King y Shlomo Angel, 1977, Oxford University Press, 0-19-501919-9....................................................................................................................................232 The Oregon Experiment, de Christopher Alexander, 1978, Oxford University Press.......................233 The Timeless Way of Building, de Christopher Alexander, 1979, Oxford University Press.............233 The Production of Houses, de Christopher Alexander, 1985, Oxford University Press. ..................233 Advanced C++ Programming Styles and Idioms, por James O. Coplien, 1992, Addison-Wesley, 0201-54855-0. ..................................................................................................................................................233 Design Patterns: Elements of Reusable Object-Oriented Software, de Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides, 1995, Addison-Wesley, 0-201-63361-2. .........................................234 Design Patterns for Object-Oriented Software Development, de Wolfgang Pree, 1995, Addison Wesley...............................................................................................................................................................234 Pattern Languages of Program Design, editado por James O. Coplien y Douglas C. Schmidt, 1995, Addison-Wesley, 0-201-60734-4.................................................................................................................235 LIBROS SOBRE BASES DE OBJETOS......................................................................................................................235 Object-Oriented Concepts, Databases, and Applications, editado por Won Kim & Frederick H. Lochovsky, 1989, Addison-Wesley, 0-201-14410-7. ...............................................................................235 Object-Orientation: Concepts, Languages, Databases, User Interfaces, Setrag Khoshafian & Razmik Abnous, 1990, John Wiley & Sons, 0-471-51801-8..................................................................235 Object Data Management: Object-Oriented and Extended Relational Database systems, R.G.G. Catell, 1991, Addison-Wesley, 0-201-53092-9. .......................................................................................236 Object-Oriented Databases, Setrag Khoshafian, 1993, John Wiley & Sons, 0-471-57056-7.........236 Sistemas de Bases de Datos Orientadas a Objetos: Conceptos y Arquitecturas, Elisa Bertino & Lorenzo Martino, 1993 (traduccin 1995), Addison-Wesley Iberoamericana, 0-201-65356-7. ...236 The Object Database Standard: ODMG-93, editado por R.G.G. Catell, 1994, Morgan Kaufmann Publishers, 1-55860-302-6. .........................................................................................................................237 Object-Oriented Databases: Technology, Appllications and Products, Bindu R. Rao, 1994, McGraw-Hill, 0-07-051279-5......................................................................................................................237 Object Databases: The Essentials, Mary E. S. Loomis, 1995, Addison-Wesley, 0-201-56341-X.....237

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 10

Modern Database Systems: The Object Model, Interoperability, and Beyond, editado por Won Kim, 1995, Addison-Wesley, 0-201-59098-0......................................................................................................237 LIBROS SOBRE INGENIERA DE PROCESOS.................................................................................................238 Reengineering the Corporation: A Manifesto for Business Revolution, por Michael Hammer & James Champy, New York: HarperCollins Publishers, 1993, 0-88730-640-3...................................238 The Object Advantage: Business Process Reengineering with Object Technology, por Ivar Jacobson, Maria Ericsson y Agneta Jacobson, ACM Press, 1994.......................................................238 Business Engineering with Object Oriented Technology, por David A. Taylor, John Wiley & Sons, 1995..................................................................................................................................................................238 LIBROS SOBRE GESTIN DE PROYECTOS...........................................................................................................239 Succeeding with Objects: Decision Frameworks for Project Management, por Adele Goldberg & Kenneth S. Rubin, 1995, Addison-Wesley, 0-201-62878-3, 542 pgs. ................................................239 Pitfalls of Object-Oriented Development, por Bruce F. Webster, 1995, M&T -Books, 1-55851-3973.........................................................................................................................................................................239 Object Lessons: Lessons Learned in Object-Oriented Development Projects, por Tom Love, 1993, SIGS Books, 0-9627477-3-4 (Prentice-Hall 0-13-472432-1)...............................................................240 LIBROS CONTRA LA TONTERA ....................................................................................................................240 201 Principles of Software Development, por Alan M. Davis, 1995, McGraw-Hill, 0-07-015840-1.241 Software Requirements & Specifications: A Lexicon of Practice, Principles and Prejudices, por Michael Jackson, 1995, Addison-Wesley, 0-201-87712-0.....................................................................241

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 11

ii
INTRODUCCIN

tro libro sobre C++? Bueno, al menos no otro libro del tipo Aprenda C++ por smosis o Los secretos de C++ por fin revelados!. La pretensin de este texto es mucho ms modesta: se trata de comunicar al lector que tambin en C++ existen ciertas normas de estilo, y que tales normas se desprenden tanto de la sintaxis del lenguaje como de prudentes decisiones de diseo ntimamente relacionadas con la Tecnologa de Objetos que anida tras el lenguaje. La intencin es, pues, colocar al lector en una posicin ms elevada a la de la mera mecnica del lenguaje, donde el CO2 de la tontera quede bien abajo. A QUIN VA DIRIGIDO ESTE LIBRO? Podra decirse que al programador de C++, pero lo cierto es que la mayor parte del material que en el mismo aparece ha sido impartida con xito a postulantes a la Tecnologa de Objetos con muy distinto bagaje: desde programadores de RPG hasta expertos en C++, pasando por analistas y diseadores de todo tipo y condicin. Y es que un buen programador de C++ sobre todo lee y decide, lee y estructura, lee y modifica, lee y vuelve a leer para, al final, codificar. En esa tnica, el presente libro muestra arquitecturas, mtodos, formas-de-hacer y tcnicas de codificacin en C++ que el lector difcilmente encontrar reunidas en un solo libro. Se explicitan, a la vez, errores frecuentes de uso del lenguaje y otros ms sutiles relacionados con decisiones de diseo que sobrepasan el mbito de la especificacin sintctica. Pero, con todo, no se trata de procurar recetas ni brebajes m ilagrosos, sino ms bien de argumentar, en continua evolucin, las posibles estrategias respecto de distintas caractersticas del lenguaje, as como sus defectos, ventajas y carencias, para conducir de esta manera al lector hacia soluciones razonadas de probada eficacia. Espero, pues, que el libro resulte tan til a los programadores de C++ como a los que quieren introducirse en el proceloso mundo de la codificacin en C++.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 12

SOBRE EL AUTOR Ricardo Devis es, adems de miembro del Comit ANSI X3J16 C++ para la estandarizacin del lenguaje de programacin C++, presidente nacional de APTO2, la Asociacin Espaola para la Promocin de las Tecnologas Orientadas-a-Objetos; miembro con voto de ACM y ACM SigPlan; fellow de la Institution of Analysts and Programmers (IAP); miembro con voto de IEEE e IEEE Computer Society; miembro de The British Computer Society; miembro del Grupo de Planificacin de Mtodos Orientados-a-Objetos de IEEE (Object-Oriented Methods Planning Group), Objetos de Negocio, para la normalizacin y estandarizacin de los mtodos orientados-a-objetos; coordinador de INFOOP, la conferencia espaola de OOP y C++; y miembro del IEEE CS&E Critics Circle. Es editor del texto INFOOP 93: I Congreso Espaol de Programacin Orientada-a-Objetos y C++ (Alicante, 1993, 84-604-6533-0), autor del libro Programacin Orientada-a-Objetos en C++ (Editorial Paraninfo, Madrid, 1993, 320 pginas, 84-283-2056-X), y editor de The Object Oriented Page (La Pgina Orientada-a-Objetos) en el World Wide Web para Tradewaves Galaxy. Ricardo Devis es el presidente y fundador de INFOPLUS, S.L., consultora de Tecnologa de Objetos, C++ y Smalltalk, y ha estado trabajando en el rea informtica desde 1.982, y fuertemente focalizado en Tecnologa de Objetos desde 1.987. Como reconocida autoridad en Orientacin-a-Objetos, ha formado a muchsimos ingenieros de software en C++, Smalltalk y mtodos de OORA/OOA/OOD, a la vez que (co)dirigido multitud de proyectos orientados-a-objetos, principalmente para grandes corporaciones y compaas institucionales. UNA VISIN PANORMICA Una cierta visin de conjunto suele beneficiar la comprensin de estructuras compuestas por piezas aparentemente inconexas. As, en lo que sigue, se detallan la esencia de los captulos del libro y las relaciones que observan entre ellos, de forma que el lector puede compartir y evaluar las pretensiones del autor, para bien o para mal. Captulo 1 - Objetos: Hitos, Mitos y Ritos En torno a ciertos popularmente entendidos hitos se han conjugado una larga serie de inexactitudes conformando lo que, con la adicin de fantasa tecnolgica, se han convertido rpidamente en mitos, alrededor de los cuales ha surgido un cmulo de ritos, a cual ms atroz, ridculo o profano. Hablo, naturalmente, de la Tecnologa de Objetos y la parafernalia que la rodea. En el presente captulo me ocupo de algunos de ellos, a los que trato de imponer la luz de la razn o, cuando menos, del pragmatismo sentido, pretendiendo insuflar al lector cierto nimo crtico respecto de la ingente (des)informacin generada por la explosin comercial de la Programacin Orientada-a-Objetos. La idea subyacente es similar a la que

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 13

anima las oberturas de las obras musicales, cuyo antiguo objetivo era tranquilizar al ruidoso pblico y prepararlo para el comienzo de la representacin. Aparece claro, con todo, que sta no es la obertura de Tannhuser, pero espero que surta un parecido poderoso efecto. Captulo 2 - Contenedores en C++ La parametrizacin de tipos respecto de estructuras agregativas es el caballo de batalla (el tamao es lo de menos) de los modernos lenguajes de programacin: colas, listas, conjuntos, etc., son algunos de los contenedores de uso frecuente en cualquier cdificacin no trivial. En este captulo se muestran las ventajas y mayormente inconvenientes del uso de contenedores en C++ mediante su codificacin expresa (a mano). As, a pesar de mostrar distintas tcnicas, ms o menos sofisticadas, para el manejo de relaciones parametrizables continente-contenido, la conclusin final es que las plantillas son la mejor solucin genrica. Captulo 3 - C++ STL: La Biblioteca Estndar de Plantillas en C++ Quin no ha usado en C++ macros genricas, o aun cierto tipo de derivacin o las relativamente nuevas plantillas, para reutilizar cdigo ligado a ciertos tipos de datos, determinados iteradores o tiles algoritmos? Debemos recurrir a bibliotecas comerciales para encontrar clases contenedoras bsicas (vector, bolsa, etc.) o, peor an, codificar a-mano las estructuras de datos necesitadas, cuando el lenguaje debiera, en un alarde de prudencia, procurarlas? La STL (Biblioteca Estndar de Plantillas) es una adicin al estndar del lenguaje C++, ya consolidada, que soluciona todas estas cuitas, adems de mostrar un muy elegante, eficaz y extensible entorno-marco de algoritmos reutilizables. Este captulo es lgica continuacin del anterior y expone la solucin de C++ al problema de la parametrizacin de contenedores. Captulo 4 - Manejo de Excepciones en C++ C++ proporciona soporte explcito para el tratamiento de las excepciones que puedan surgir en el flujo normal de computacin de una aplicacin dada, pero la sintaxis, comportamiento y, sobre todo, implementacin de las soluciones provistas son relativamente nuevos. C++ es, por otro lado, un lenguaje excepcionalmente prolijo en sutilezas, as que parece conveniente una revisin del fondo y forma de las excepciones, que en esta ocasin se convierten en regla. No se dan en este captulo, con todo, instrucciones paso-a-paso para la insercin de las excepciones de C++ en aplicaciones complejas (pues esto ms bien corresponde a un manual de arquitectura de aplicaciones), sino ms bien se argumentan y explicitan ciertos mecanismos que inducen determinadas decisiones de diseo cuyo conocimiento resulta imprescindible para cualquier programador de C++.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 14

Captulo 5 - Asignacin en C++ Qu se esconde tras una aparentemente simple asignacin en C++? En esencia la voluntad de copiar un objeto en otro. Pero en C++ la complejidad se esconde en casi todos los recovecos del lenguaje, de forma que una simple expresin de asignacin puede generar gravsimos errores muy difciles de depurar. Naturalmente el remedio es el conocimiento exacto no slo de la sintaxis del lenguaje, sino tambin de la precisa actuacin semntica que se agazapa tras aqulla. Cuando yo planteo esto ante algn auditorio, suele preguntrseme: no se puede obviar toda esta complejidad? Mi respuesta suele ser: Para permitirse ser escptico hay que haber credo mucho antes. Esto es, slo simplifica quien comprende. Captulo 6 - Patrones de Diseo: La Calidad Sin Nombre El viejo sueo de la comunidad software ha sido emular a la arquitectura tradicional utilizando similares esquemas, procesos, herramientas, elementos y componentes en la construccin de sistemas software. A lo largo del tiempo el desarrollo de tales sistemas ha ido ajustndose de forma metdica a este propsito: las bibliotecas reutilizables, los mdulos interconectables, la formalizacin de fases, etc. muestran distintos aspectos de este acercamiento. Los patrones, al fin, ejemplifican el ltimo estadio de esta relacin: bloques que, organizados en catlogos, encapsulan la experiencia de excelentes diseos software. Pero el lector puede objetar: Qu tienen que ver los patrones con la programacin C++? Oh, cielos! Mucho! Resulta, por un lado, que el grueso de los patrones est ejemplificado en C++, mientras que por otro lado cabe recordarle al olvidadizo lector que en C++ se lee mucho y se codifica poco, y los patrones son una excelente lectura si no se quiere reinventar la rueda constantemente. Adems los patrones observan una relacin directa con los importantes modelos de roles e, incidental pero expresamente, su conocimiento ser necesario para abordar el siguiente captulo. Captulo 7 - Roles y Objetos en C++ Los sistemas software generalmente procuran simular sistemas reales en los que distintas entidades interactan usualmente de forma no trivial. No resulta raro, pues, que las conceptualizaciones ms frecuentes en el mundo real hayan intentado ser trasladadas al dominio software, con mayores o menores fortuna, fidelidad o eficacia, generando, en cualquier caso, un acervo de soluciones que pueden ser reutilizadas por analistas, diseadores y programadores. En el presente captulo abordamos (como corsarios, naturalmente), aun de forma elemental, uno de los problemas de modelado software ms comunes: el de los roles, esto es, el de los papeles que determinadas entidades fsicas o conceptuales asumen respecto de otras. La exposicin se enfoca a nivel de lenguaje y, por tanto, se obvian bastantes de los aspectos metodolgicos propios de las reas de anlisis y diseo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 15

Captulo 8 - Bases de Datos Orientadas-a-Objetos Qu es un objeto? Dices mientras clavas en mi pupila tu pupila azul Qu es un objeto! Y t me lo preguntas? Un objeto ... eres t! Y es que en Tecnologa de Objetos (como en otros muchos mbitos de la vida y la poltica) cualquier entidad con lmites conceptuales bien definidos es un objeto. Y como todo son objetos surge, de forma natural, la idea de repositorios que mantengan estas entidades respetando sus identidades: las Bases de Objetos. En el presente captulo examino, desde la ptica pragmtica del programador (u OODA, como veremos), algunos aspectos de esta tecnologa, fundamentalmente basada en los productos comerciales que la sustentan. Pero, atencin: no se pretende ensear a codificar en C++ los accesos a bases de objetos, si no ms bien explicitar ciertos conceptos bsicos que, adems, servirn perfectamente al lector para seguir con exactitud el siguiente captulo. Captulo 9 - Consideraciones Prcticas Cmo se enfrenta el programador de C++ a la conjuncin de entornos grficos con bases de objetos y bibliotecas multiplataforma? Pues usualmente con miedo, resignacin o imprudencia temeraria. Para cubrir este cierto vaco, en el presente captulo se exponen varias tcnicas de acercamiento a la codificacin de aplicaciones basadas en entornos grficos. El enfoque es decididamente elemental y se basa en resaltar ciertas ideas y formas de abordar problemas suficientemente genricos en la codificacin diaria de aplicaciones: el paradigma MVC, la gestin de vistas, la gestin de concurrencias, etc. Captulo 10 - Gestin de Proyectos Orientados-a-Objetos En este captulo se pretende mostrar, aun muy sucintamente, el estado actual de la Tecnologa de Objetos respecto de su aplicacin en proyectos reales de desarollo software. Es imposible, naturalmente, resumir y condensar en tan pocas pginas tamaa nebulosa tecnolgica, pero al menos se expondrn algunas consideraciones prcticas extradas de la aplicacin por el autor de lenguajes, tcnicas y mtodos orientados-a-objetos en proyectos reales. El lector avisado ya supondr que el captulo no va a ser, precisamente, un rosario de elogios y recetas, sino ms bien lo contrario: un toque de atencin referente a las dificultades de eleccin de mtodos, herramientas y, al fin, de arquitecturas sobre las que basar los sistemas software. Captulo 11 - Modelos de Roles: El Mtodo Ooram La arena del anlisis y diseo orientados-a-objetos est llena de luchadores repletos de trucos y estrategias comerciales, pero que sorprendentemente usan de armas muy parecidas, de forma que el lastimero enfoque final parece venir de la mano de alianzas, mixturas y refritos comerciales de distintos mtodos existentes.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 16

Ante tamaa impostura cabe sealar que realmente existen metodologas serias y, de entre ellas, destaca por su originalidad, solidez y probada aplicacin en la construccin de grandes sistemas la representada por OOram y que se basa en modelos de roles, la unidad natural de composicin de sistemas software. En este captulo se dan algunas pistas y se exponen ciertas ideas que pretenden redimir al lector de tanta comercialidad metdica. Captulo 12 - Bibliografa Comentada Si yo tuviera que vender mi gato (al menos a un informtico) no dira que es amable y autosuficiente y que se alimenta de ratones: ms bien argira que est orientado-a-objetos (Roger King). Oh, oh, hay que protegerse de la tontera! Lo que aparece en este captulo es una cuidada y actualizada seleccin bibliogrfica (casi completamente en ingls) que abarca el grueso de las reas de la Tecnologa de Objetos. He preferido comentar preferentemente los textos de indiscutible calidad, pero tambin he incluido alguno sectorialmente interesante o histricamente importante. Definitivamente se trata de ayudar al lector a evitar tanto perder el tiempo como ser vctima de imposturas cometidas por autores infames o simplemente inicuos. GARANTA Todos los errores que el lector encuentre en el presente texto son nicamente mos, como lo son las carencias, deslices e inexactitudes que en el mismo se puedan dar. Los comentarios, elogios, sugerencias y crticas son, cmo no, bienvenidos: el lector puede localizarme bien en INFOPLUS S.L., voz/fax (96) 5930017, bien mediante correo electrnico en Internet (devis@ibm.net) o Compuserve(100140.1435), mientras que la URL de mis pginas en el WWW es http://www.well.com/user/ritchie.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 17

1
OBJETOS: HITOS, MITOS Y RITOS

o hay que subestimar la fuerza de la repeticin y la estulticia de los medios de comunicacin: si una barbaridad se repite con insistencia en los lugares adecuados, en breve pasar a ser considerada como una realidad incontestable. Les pondr un ejemplo: cuando se habla de objetos mucha gente perpetra con demasiada facilidad vocablos como paradigma, entorno/marco (por framework), etc. Pero, cul es su significado preciso? Humm, mejor no preguntar. Pregunten sin miedo, empero, sobre la orientacin a objetos y obtendrn: tal, tal ... y polimorfismo. Demonios! La traduccin literal del griego, muchasformas, no genera excesivas luces, la verdad, as que la mayora de los encuestados tiende a suplir sus carencias formales con su autoexaltado sentido comn, de forma que los resultados vienen a ser como la traduccin al castellano de las pelculas extranjeras: un dislate sin sentido. Es polimrfico Felipe Gonzlez? Es polimrfica la plastilina? En fin, como el lector puede apreciar el panorama es agotadoramente desolador. En lo que sigue intentar resear algunas de las supersticiones ms extendidas, pero el tema en absoluto queda completamente cubierto, as que a lo largo del libro irn apareciendo ideas parecidas que intentar sean oportunamente desenmascaradas. MITO 1: UN LENGUAJE ORIENTADO-A-OBJETOS PURO ES MEJOR QUE OTRO HBRIDO. Esto es lo mismo que decir que un veneno puro es ms beneficioso para el cuerpo que otro convenientemente rebajado. Cualquier mente no enferma entiende que la idoneidad de un lenguaje, en cualquier mbito, se basa en las facilidades que provee para acometer las tareas a que se destina. Parece, adems, prudente suponer que, como bien afirma Stroustrup, un lenguaje de propsito general ha de soportar ms de un estilo (paradigma) de programacin. Oh, naturalmente esto no es slo una defensa de C++ frente a Smalltalk (que lo es, por cierto), sino una llamada al sentido comn: si preguntamos a diez dentistas cules son los pilares de la orientacin-a-objetos, al menos nueve de ellos respondern encapsulacin, herencia y polimorfismo, para despus aadir y no provoca caries. Ah, pero esto no es cierto. La verdad es que todava no hay consenso respecto de las

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 18

caractersticas esenciales de la orientacin-a-objetos. Y no digamos de otras caractersticas: En los lenguajes orientados-a-objetos todo son objetos? Las clases han de ser por fuerza objetos? Son los sistemas orientados-a-objetos en realidad sistemas de objetos, para los objetos y con los objetos? La herencia mltiple es una bendicin o ms bien un artefacto del infierno que requiere vender primero el alma para ser manejado con acierto? El chequeo esttico de tipos es una hereja? Vaya, demasiadas incertidumbres. As que si Smalltalk o Eiffel son qumicamente puros, C++ podra ser fsicamente hbrido. Bah, tonteras! MITO 2: PARA APRENDER A USAR ADECUADAMENTE C++ HAY QUE EMPEZAR POR SMALLTALK. En ms de una ocasin Stroustrup oportunamente ha sealado: C++ no es un buen Smalltalk; nunca se pretendi que lo fuera. De igual manera Smalltalk no es un buen C++, pues evidentemente nunca se pretendi tal. El mensaje es claro: Smalltalk conduce a una particular forma de disear y codificar, basada esencialmente en la estructuracin mediante herencia de clases en jerarquas csmicas (derivadas de Objeto), que trasladada a C++ usualmente genera un estilo particularmente ineficiente e inseguro. Quin en su sano juicio usara en C++ de forma masiva, a no ser por imperativos fsicos, las colecciones de Smalltalk pudiendo hacer uso de la Biblioteca Estndar de Plantillas de C++ (que obvia completamente la herencia, dicho sea de paso)? Mi experiencia en direccin de proyectos y formacin me seala, en contrapartida, que la realidad es exactamente la inversa: un buen programador de C++ se convierte con mucha facilidad, y normalmente a su pesar, en un buen programador de Smalltalk. Pero, claro, sta es una broma prctica. MITO 3: C++ ES MS FCIL DE ASIMILAR PARA LOS PROGRAMADORES DE C. Este lugar comn casa perfectamente con aquel otro que afirma Para estudiar C++ hay que empezar estudiando C. En general habra que decir, con Stroustrup, que si vas a usar C++, estudia C++. Desmond DSouza acertadamente expone que el hecho que la enseanza de C++ no sea trivial en absoluto implica que C++ sea difcil de aprender (o al menos un cierto subconjunto de uso del lenguaje): otra cuestin es que lo parezca, y esto se debe ms a lo que se adivina no saber que a lo que en realidad se ha aprendido (C++ es un lenguaje ciertamente prolijo). En general el segmento de C++ que intersecta con C no posee el mismo comportamiento en ambos lenguajes: esto es, C ensea a codificar estructuras de cdigo preparadas para utilizar los recursos del lenguaje, bien distintos a los de C++; y a la inversa. As una buena parte de las tcnicas que se ensean en excelentes textos de C resultan inservibles o inadecuadas en C, mientras que el uso de ciertas caractersticas del subconjunto C de C++ no es en absoluto trasladable al puro C.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 19

Resulta, pues, que en la prctica los programadores que arrostran un cierto estilo C tienden a observar un lapso de tiempo ms prolongado para el aprendizaje de C++ que los que, sin bagaje previo de C, empiezan por C++. MITO 4: LAS HERRAMIENTAS OOCASE INTEGRADAS GENERAN CDIGO ORIENTADO-A-OBJETOS FIABLE. Bueno, hay que distinguir dos vertientes: la generacin de cdigo de implementacin y la generacin de cabeceras, frecuentemente llamadas esqueletos de la aplicacin y que usualmente adquieren en la prctica su sentido ms mrbido. En cuanto a las cabeceras, refirindose al cdigo de descripcin de clases, bueno, como la mayora de las herramientas OOCASE requieren una completa informacin de nombres y tipos de mtodos y atributos, la generacin de tales protocolos, unidos a lo sumo por una relacin de herencia, resulta aparentemente trivial; en lo referido al cdigo de los mtodos, bueno, esta es otra historia: cualquier programador de C++ sabe que tras una simple lnea de cdigo pueden esconderse cientos de lneas en absoluto triviales o evidentes. Y es que cmo asume una herramienta CASE idiomas y estilos estrictos de codificacin para cada lenguaje particular? Pues como murio mi abuela: con mucho dolor y dificultad. Si el detalle no excesivamente prolijo del uso del operador de asignacin en C++ puede llevar ms de 20 pginas, podra permitirse una herramienta CASE su particularizacin hasta tal extremo, teniendo en cuenta, adems, que muchas decisiones de implementacin dependen de la arquitectura y patrones del diseo a codificar? Naturalmente no estoy hablando de generacin de cdigo para la construccin de interfaces grficos, pues existen entornos/marcos y bibliotecas de clases perfectamente estables y fiables sobre los que construir con facilidad y seguridad clases concretas de uso. MITO 5: LA HERENCIA ES UNA CUALIDAD ESENCIAL DE LOS SISTEMAS ORIENTADOS-A-OBJETOS. Cules son los pilares de la Orientacin-a-Objetos? Henderson-Sellers los estableci en un tringulo: abstraccin, encapsulacin y polimorfismo. Y la herencia? Bueno, parece que hay poco patrimonio que transmitir. Y es que, pese a lo que se pueda pensar, la herencia es bsicamente un mecanismo que utilizan los lenguajes de programacin orientados-a-objetos para implementar el polimorfismo, y como tal mecanismo puede ser perfectamente sustituido por otro que procure la misma suerte de funcionalidad, siempre a nivel de lenguaje. Oh, ya veo temblar al lector, que atnito observa como desdigo y mortifico a multitud de gurus (un barbarismo, aunque no lo crea) y expertos que basan la construccin de sistemas software fundamentalmente en la herencia. Bien, Alan Davis afirma que hay que seguir a los lemmings con cuidado: la herencia, en tales sistemas, pertrecha causa comn con los tipos abstractos de datos, jerarquas de subtipado y con algu-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 20

nos aspectos de simplificacin del diseo, para terminar con cuestiones de reutilizacin: todo un completo panorama que parece trocar a la herencia en piedra angular. Nada ms lejos de lo deseable, empero: por qu distinguir la herencia, como relacin entre clases, de las relaciones de agregacin, composicin o uso que tambin se dan en tales sistemas? Por qu la herencia suele aplicarse a clases y no a objetos/instancias? Pues porque es una componenda esencialmente esttica que procura una estructura lgica recorrible sobre la que basar bien la un esquema de reutilizacin bien la resolucin de operadores (por mtodos) en tiempo de ejecucin. Pero componenda no es panacea, as que nos quedaremos con que la herencia es una cualidad accesoria de los sistemas orientados-aobjetos. MITO 6: LA HERENCIA ES UN MECANISMO INDISPENSABLE EN LOS LENGUAJES DE PROGRAMACIN ORIENTADOS-A-OBJETOS Oh, este es un mito especialmente peligroso. Ciertamente la aplicacin de la herencia en los lenguajes de programacin constituy, en su da, un importante hito en el dominio de la modularidad software. La herencia, o derivacin, ha incurrido, empero, en generar una larga serie de despropsitos que la acompaan dondequiera que va. Resultara, de acuerdo con lo expuesto, que un lenguaje orientadoa-objetos prototpico y basado en delegacin, como es Self, no estara realmente orientado-a-objetos. Se oye frecuentemente, tambin, que una buena codificacin ha de hacer uso intensivo de la herencia, y se obvian otras caractersticas como contenedores parametrizables, algoritmos reutilizables, etc. Con todo cuando en alguna mesa redonda yo afirmo que en algunos proyectos prohibo la herencia (y por prohibir indico que cualquier relacin de herencia necesitar la aprobacin de un arquitecto), mis colegas me miran con sospecha. Y es que realmente la herencia es un mecanismo poderoso, pero tambin peligroso y difcil de controlar en grandes equipos humanos. MITO 7: LA HERENCIA NICAMENTE SE PUEDE APLICAR CUANDO SE DA UNA RELACIN ES-UN. La dictadura de las jerarquas de subtipacin se ha convertido, en muy breve tiempo, en una absurda tecnocracia. En el mundo Smalltalk (universo, le llaman sus postulantes) es frecuente, por ejemplo, usar la derivacin de clases como mtodo puro de reutilizacin, haciendo caso omiso de consideraciones estrictas de subtipado. Y es que si se piensa que los lenguajes son herramientas imperfectas de modelado en el dominio software de problemas reales, cmo no se ha de ser esencialmente pragmtico tanto en el diseo como en la codificacin? Los mixins, por ejemplo, son clases resultantes de la aplicacin de la herencia mltiple que se usan como componentes de implementacin de otras clases, bien mediante herencia bien mediante composicin (layering). Tiende a olvidarse con

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 21

facilidad que la finalidad de las actividades de desarrollo es la construccin de sistemas software, y no la aplicacin de mtodos o tcnicas en s. MITO 8: EXISTEN DEMASIADAS METODOLOGAS DE ANLISIS Y DISEO ORIENTADAS-A-OBJETOS. Bien al contrario, prcticamente no existen en la actualidad metodologas orientadas-a-objetos. Observe el lector que metodologa es ciencia de los mtodos, y con lo que mayormente contamos es con mtodos: OMT, Coad/Yourdon, WirfsBrock, Jacobson, Booch, etc. son, pura y simplemente, mtodos en el mejor de los casos, aderezados con algunos heursticos y bastantes trucos, varios ejemplos y un demasiado de filosofa genrica. Claro que en informtica se soluciona todo con rapidez, de forma que se ha redefinido metodologa para ajustar el vocablo a las carencias del rea: as que en informtica metodologa significa mtodo (y si el lector se sorprende, rase de la locucin ingeniera de software). Con todo, no existen tantos mtodos orientados-a-objetos: casi todos ellos se basan en alguna extensin del modelo entidad-relacin de Chen, sobre la base de clases/objetos, a la que se adicionan notaciones sospechosamente parecidas entre s y algunos componentes de comportamiento sustanciados en el modelado de escenarios arbitrarios y en el control y gestin de estados de las entidades/clases/objetos. Realmente con los mtodos OO se sustancia la vox populi sobre los polticos: conocido uno, conocidos todos. Bueno, casi todos: s existe alguna metodologa orientada-a-objetos (y seguro que no es la que el lector pueda pensar), pero eso es materia de un prximo libro. MITO 9: CADA EMPRESA DEBE ADAPTAR A SU MANERA LOS MTODOS EXISTENTES PARA CONSTRUIRSE UNO A MEDIDA. Piense el lector, en primer lugar, si no es ridculo pensar que un mtodo dado pueda manejar cualquier problema de la realidad, sobre todo teniendo en cuenta que la mayora de los mtodos observa una estructuracin secuencial a la vez breve y establecida en fases inamovibles. Oh, esto no es sino mirar la realidad, como hizo Freud respecto del sexo, por un tubito tan pequeo como el mtodo usado. Examine el lector seguidamente la desafortunadamente extendida suposicin que una conjuncin particular de varios mtodos, encajados en razn del discutible criterio de una empresa, pudiera modelar todos los problemas. Es como si, una vez desechado el esperanto, la solucin viniera de la mano de un refrito de lenguas: I taime mucho! Y lo curioso es que este enfoque se ha convertido en una de esas verdades difusas que casi nadie cuestiona: ahora cojo OMT de Rumbaugh, le aado un tanto de casos de uso (use cases) de Jacobson, lo aderezo con algo de fichas CRC y Diseo Orientado-a-Responsabilidades de WirfsBrock, lo agito en la coctelera, le doy un nombre nuevo, fabrico una herramienta pseudo-CASE que lo soporta y ... voil el mtodo universal. Es como si se anun-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 22

ciara: sobre gustos no hay nada escrito. Mentira! Hay muchsimo escrito, pero seguramente usted no lo ha ledo, cabra contestar. La solucin, a mi entender, no pasa por el refrito de mtodos, ni tampoco por la solucin que proponen los autodenominados mtodos de segunda generacin, abanderados por Fusion, de Coleman y otros, y que se basa en la utilizacin de un mtodo cualquiera (OMT, Jacobson, Wirfs-Brock, etc.) como informacin de entrada para un marco formal que regule y distribuya adecuadamente los resultados. El modelado genrico de sistemas de informacin habra ms bien de pasar, segn mi opinin, por lo que se conocen como marcos referenciales metodolgicos: esto es, un adecuado conjunto de herramientas metodolgicas y de mtodos que conforman un arsenal de vistas aplicables de forma segmentada y no necesariamente completa sobre el dominio de los problemas a modelar. Existen tales marcos? Por supuesto, pero esto es otra historia. MITO 10: LO PRIMERO QUE HAY QUE HACER ES CREAR UNA BIBLIOTECA DE CLASES REUTILIZABLES. Esta frase se oye mucho en cursillos y se lee por doquier en las revistas del ramo. La cuestin es: cmo puede crearse de la nada una clase reutilizable? Esto es, puede reutilizarse una clase que todava no ha sido utilizada? Naturalmente que no! Primero hay que generar a la vez poltica y ambiente de reutilizacin en la empresa, de forma que cuando se creen clases con un diseo prudente tales clases sean utilizadas por el equipo humano y la informacin que se desprenda de tal uso pueda revertir en la mejora de tales clases, que volvern a ser utilizadas de nuevo en un ciclo involutivo. Se entiende por reutilizacin no el uso (una clase Ventana se usar por varias aplicaciones, pero tal no es reuso), sino los usos distintos en distintos contextos. Por supuesto que el (re)uso se da tanto a nivel de aplicativos como de las propias bibliotecas de clases, pero aqu, como ya se expres anteriormente, la herencia juega un papel usualmente desdichado: si nos dedicamos a insertar las clases a reutilizar en jerarquas no-triviales de herencia, cuando queremos hacer uso de una determinada clase arrastraremos con ellas buena parte del arbol de derivacin, con lo que el nivel de aprovechamiento, si posible, dejar mucho que desear.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 23

2
CONTENEDORES Y PLANTILLAS

esafortunadamente el trmino "contenedor" no existe -si no es un armazn metlico- como sustantivo en castellano, pero para eso est la informtica: para alterar los nervios de los puristas y modificar, de facto, para bien o mejor para mal, el lenguaje. As diremos, parafraseando a la Real Academia, que un objeto contenedor (o de tipo contenedor) es el que lleva o encierra objetos dentro de s. De la misma manera afirmaremos que una clase contenedora es una clase cuyas instancias pueden contener otras instancias. Obviaremos, pues, expresamente, el exacto vocablo continente, cuya acepcin como cosa que contiene en s a otra es en realidad lo que necesitamos, pues aqu la ortodoxia del lenguaje deber ceder frente a la costumbre establecida: la prctica totalidad de los asistentes a cursos prefiere el neologismo, pues continente ofrece unas connotaciones de uso restrictivo de la continencia no deseadas. Pero, qu inters tienen estas baratijas pseudo-lingsticas? Pues resulta que, como el perspicaz lector ya habr adivinado, continuamente estamos usando clases y objetos contenedores; de hecho existen muchos libros que, de forma mayormente lastimosa, dedican casi todo su espacio a la ejemplificacin de los mismos: pilas, bolsas, conjuntos, vectores, matrices, listas, listas enlazadas, colas, etc. Su utilizacin es tan frecuente que la circunstancia de que, hasta hace poco, C++ no incluyera clases contenedoras como parte del lenguaje indudablemente ha perjudicado la extensin de su adopcin. Pinsese, por ejemplo, que el esperanto es un lenguaje bienintencionado (y recordemos aqu a Valle-Incln, buen ilustrador de la materia con que est empedrado el infierno) dotado de una sintaxis y pronunciacin racionales que en teora facilitaran su urgente adopcin universal. Sin embargo algo falla, pues es evidente que estas lneas no estn en esperanto 1. Pasemos a otro escenario: si yo me siento bien con RPG, me he acostumbrado a l, le he cogido cario con el tiempo y no creo en la muerte asistida, por qu demonios he de cambiar a un lenguaje pretendidamente mejor, como anuncian pueda ser C++? Y lo mismo puedo pensar si estoy cuidando de Cobol, Visual Basic, C, Pascal, etc.: No es demasiado presumida la asuncin de que si no cambio es debido a un cmulo de incapacidades? Bueno, un lenguaje se usa en la prctica,

En Espaol (castellano <sic>) en el original.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 24

independientemente de los bienintencionados motivos que lo amparen, en tanto que proporciona facilidades para el tipo de programacin para el que se pretende utilizar como herramienta. En este sentido cabe destacar que C++ es -en la actualidad- un lenguaje de extensa sintaxis y gran prolijidad semntica (slo hay que contar que el borrador del estndar del lenguaje consta de aproximadamente 700 pginas en formato A-4, y en l "slo" se describe el lenguaje C++), y su concepcin y desarrollo se han ligado, sobre casi todo lo dems, a su practicidad como herramienta de programacin, de tal forma que si realmente se necesitaba una facilidad sta se aada al acervo del lenguaje. Pero, proporciona C++, por ejemplo, las facilidades sobre contenedores que necesitamos? Pues bien, s. Resulta que ANSI X3J16 ha incorporado recientemente como parte del lenguaje una biblioteca de plantillas de contenedores2 (STL, The Standard Template Library: La Biblioteca Estndar de Plantillas), que en el captulo siguiente diseccionaremos pedaggicamente. Pero yendo ms all descubriramos, en palabras de Stroustrup, que la gnesis de las plantillas se basa "en el deseo de expresar la parametrizacin de clases contenedoras"3, situando de esta manera en un lugar privilegiado, por su importancia, al diseo y uso de tales contenedores. En realidad C++ se convierte, as, en uno de los lenguajes mejor preparados para la gestin de contenedores. Y aunque esto pueda tildarse de opinin subjetiva, a lo que sigue me remito, pues la intencin primera de este captulo es, adems de ponderar la importancia de los contenedores, llegar a explicitar los mecanismos, sintaxis, sutilezas y carencias que animan el soporte conceptual en que se apoyan las plantillas (templates) en C++. Pero el tema es largo, muy largo, as que al grano!. DISEO DE CONTENEDORES Aparte de lo anteriormente expresado, los contenedores son vitales para los programadores por una razn adicional: virtualmente todas las actuales bases de objetos (OODBSs: Object-Oriented Database Systems) gestionan buena parte de los accesos a objetos mediante estas estructuras. Pero a esto atenderemos ms adelante. Por ahora simplemente consideraremos las distintas estrategias que, de forma inexorable, nos conducirn al empleo de plantillas en C++. En principio para el diseo de contenedores en C++ podemos tener en cuenta, bsicamente, cuatro enfoques distintos: lo obvio, el preprocesado, la herencia y las plantillas. Pero vayamos paso a paso.

En verdad la adicin de caractersticas en C++ es tan importante, en comparacin con lo mostrado por la mayora de compiladores comercializados en la actualidad, que realmente sorprende. Algn colega ha llegado a decir que C++ ha dejado de ser un lenguaje para transformarse en un entorno. Bueno, es una idea. 3 Bjarne Stroustrup, The Design and Evolution of C++, 1994, Addison-Wesley, Pgina 337.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 25

LA OPCIN INGENUA: CUESTIN DE MBITOS Una primera solucin elemental consiste en usar un pequeo truco para sustituir en cada ocasin nicamente el tipo de objetos a usar por el contenedor, sin tener que modificar la definicin de ste. De esta manera, al definir la siguiente clase en un fichero denominado "coleccio.h":
class Coleccion { public: bool inserta( TIPO ); Coleccion& operator|=( TIPO ); // etc., etc. };

si queremos una coleccin de enteros deberamos codificar algo de la siguiente guisa:


#define TIPO int #include "coleccio.h" Coleccion coleccionDeEnteros; coleccionDeEnteros.inserta( 17 );

Si por otra parte queremos -puro capricho- una coleccin de decimales, podramos codificar, en un mbito diferente, as:
typedef double TIPO; #include "coleccio.h" Coleccion coleccionDeDecimales; coleccionDeDecimales.inserta( 1.1235813 );

Lo que en ambos casos hemos hecho es, en primer lugar, asignar una sustitucin del identificador TIPO con sentido para el lenguaje, para despus, usando del preprocesador, incluir el cdigo de definicin de la clase coleccin (mediante la directiva "#include"). Seguidamente se define una variable (objeto) del tipo Coleccion (que en realidad, en ese momento, no es una clase coleccin genrica, sino que es ya, de hecho, una coleccin de enteros en el primer caso y otra de doubles en el segundo). Por ltimo se llama a una funcin miembro de la clase con el argumento adecuado en cada caso. Ea, parece que esto funciona!, podra aqu exclamar el incauto lector. Pero no, desafortunadamente esto no funciona! En primer lugar la clase Coleccion depende, para su compilacin, de una definicin exterior a la misma, de forma que se genera una necesidad de secuencialidad bien difcil de documentar. Por otro lado resulta que si compilamos las lneas:
#define TIPO double #include "coleccio.h"

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 26

Coleccion unaColeccionDeDecimales; double unDecimal = 1.23456 unaColeccionDeDecimales.inserta( unDecimal ); #define TIPO Cliente #include "coleccio.h" #include cliente.h /* nuestra clase Cliente */ Coleccion unaColeccionDeClientes; Cliente unCliente( Fulano y Cia ); unaColeccionDeClientes.inserta( unCliente );

aparecer en primer lugar un aviso indicndonos que la redefinicin de TIPO como Cliente no es idntica a su anterior definicin como double (naturalmente!). Pero, atencin, se trata de un aviso, no de un error, y esto quiere decir que el compilador simplemente ignorar esta nueva redefinicin, de forma que al llegar a la lnea en que se incluye de nuevo el fichero coleccio.h, con la ingenua intencin de reprocesar el identificador TIPO, podrn pasar dos cosas: si el fichero de cabecera incluye la tpica construccin
#ifndef coleccio_h #define coleccio_h // definicin de clase #endif /* coleccio_h */

entonces, dado que se ha definido coleccio_h en la pasada anterior del preprocesador, se ignorar en la prctica la nueva lectura del fichero; si, por el contrario, no se incluyesen estas instrucciones (con la vaga y fatal idea de forzar el nuevo preprocesamiento de la clase) entonces aparecera un error por mltiple declaracin de la clase Coleccion. En cualquier caso la ltima lnea originar un error por desajuste de tipo en el parmetro: se espera un double, y aqu se le pasa un Cliente (recordemos que el compilador ha ignorado nuestros infantiles deseos). De aqu se colige que, con este esquema, no podramos usar dos colecciones que manejen distintos tipos en el mismo mbito. Y esto es inaceptable. Debemos encontrar una forma de compatibilizar tales dos distintas colecciones. Y qu tal -preguntara aqu el lector inquieto- si definimos la primera clase con el identificador "doubleColeccion" y la segunda con el de "ClienteColeccion"? Bueno, querido lector, esto puede funcionar. Vemoslo. LA TRAMPA DEL PREPROCESADOR Bueno, necesitamos un fichero "ppcolecc.h" en el que escribiremos lo siguiente, usando de la sintaxis del preprocesador:
// la siguiente lnea crea un nuevo identificador

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 27

// como yuxtaposicin de dos identificadores dados. 4 #define concatenar(a,b) a##b // seguidamente se codifica la macroinstruccin que // generar un nombre especfico para cada coleccin. #define Coleccion(tipo) concatenar(tipo,Coleccion) // y aqu viene la definicin "genrica" de nuestra // clase contenedora. #define declara(Coleccion,tipo) \ class Coleccion(tipo) { \ public: \ Coleccion(tipo)(); \ Coleccion(tipo)(const Coleccion(tipo)&); \ bool inserta(tipo); \ // etc., etc. \ };

De esta forma si codificamos


#include <ppcollec.h> declara(Coleccion,int) Coleccion(int) miColeccionDeEnteros;

el preprocesador realizar el siguiente trabajo por nosotros:


class intColeccion { public: intColeccion(); intColeccion(const intColeccion&); bool inserta(int); // etc., etc. 5 }; intColeccion miColeccionDeEnteros;

y, de la misma manera, si codificamos


declara(Coleccion,double)

Este cdigo para concatenar identificadores no es, como resulta fcil suponer, portable entre sistemas, de tal manera que tambin se usan lindezas como las siguientes: #define concatenar(a,b) a/**/b #define concatenar(a,b) a\ b 5 Atencin: la macroexpansin de la definicin de la clase se producir en una sola lnea (noten los caracteres "\" al final de cada lnea de la definicin de la macro del preprocesador). Aqu se ha mejorado la presentacin debido a razones tipogrficas, pero hay que tener en cuenta que a lgunos editores -afortunadamente muy pocos hoy en da- pueden truncar lneas demasiado largas, ocasionando errores de compilacin difciles de detectar y, por ende, corregir.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 28

Coleccion(double) miColeccionDeDoubles; miColeccionDeDoubles.inserta( 1.1135917 );

obtendremos la definicin de una clase con identificador "doubleColeccion", as que ahora ya podemos usar en el mismo mbito dos colecciones que, con el mismo funcionamiento interno, contienen objetos de tipos distintos: ints y doubles, pues sus identificadores respectivos son tambin distintos. Vaya, -exclamar aqu el lector de antes- mi idea ha funcionado perfectamente! Pues no, reincidente lector. Ha fallado de nuevo, y esto se est convirtiendo en un hbito. Resulta que, al fin, esta idea puede devenir mala malsima de la muerte. Echmosle, si no, un vistazo a la siguiente galera de horrores:
declara(Coleccion,flota) /* aqu empiezan los problemas */ Coleccion(fluat) miRaraColeccion; // error! Declara(Coleccion,*int) /* aqu la tipografa intimida */ Coleccion(Coleccion,int*) misInts; // nuevo error! declara(Coleccion,const Fecha) /* horror! */ Coleccion(const Fecha) misFechas; // la hecatombe! declara(Coleccion,char*) /* ?! */ Coleccion(char*) misCaracteres; // qu pasar aqu?

Se deja como ejercicio al lector la comprobacin individual de los errores en cada lnea. En definitiva, se puede fcilmente apreciar que las macrosustituciones del preprocesador ("macros", si usamos un flagrante neologismo) no entienden de tipos: su "inteligencia" est limitada a la mera sustitucin lxica. As, por ejemplo, la lnea
declara(Coleccion,char*)

intentara generar el cdigo de una clase con un identificador tal que as:
char*Coleccion

lo que, naturalmente, generara un error en compilacin sobre una lnea que en realidad no est visible en el cdigo fuente. Claro que esto podra arreglarse de la siguiente forma:
typedef char* punteroAChar; declara(Coleccion,punteroAChar)

pero lo que aqu estamos haciendo es ... suplir el trabajo que usualmente el lenguaje hace por nosotros, reconociendo a la vez la incapacidad del preprocesador respecto de los tipos y su alejamiento del lenguaje. Una de las mejores caractersticas de C++ es su fuerte chequeo de tipos que, en el caso de las macrosustitu-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 29

ciones, se pierde como se perdi Cuba: de forma irremediable. Hyase, pues, del preprocesador siempre que sea posible ("Me gustara ver abolido el Cpp"6, Stroustrup dixit). Pero, entonces, qu hacer respecto de los contenedores genricos? Bueno, la mayora de bibliotecas de C++ se basan en un uso ms o menos intensivo de la herencia mediante la derivacin de clases. Qu tal si aplicamos la derivacin y los mecanismos de conversin, implcitos o no, de C++ para procurar la genericidad deseada? Al grano. CUANDO LA HERENCIA ES DISPUTADA Si deseamos un contenedor genrico (esto es, que admita objetos de cualesquiera de los tipos que usamos, o de un subconjunto de estos), necesitamos que todos los objetos que hayan de formar el "contenido" deriven de una misma clase base, usualmente llamada "Objeto". Volvamos a nuestra clase:
class Coleccion { public: bool inserta( Objeto* ); // etc., etc. };

Si deseamos una coleccin en la que insertar libros, lo nico que necesitamos es hacer derivar la clase "Libro" de "Objeto":
class Libro : public Objeto { public: Libro( char* titulo = 0 ); // sigue resto descripcin clase };

de forma que ahora podramos codificar lo siguiente:


Coleccion miBiblioteca; Libro* miPreferido = new Libro( "The Devil's Dictionary" ); miBiblioteca.inserta( miPreferido );

y esto funciona perfectamente, pues aunque en la ltima lnea se ha usado como argumento un puntero a un objeto Libro donde se esperaba un puntero a un objeto de clase Objeto, dado que aqul deriva pblicamente de ste, se produce -como el lector ya sabe- una conversin implcita de tipos, y el puntero a Libro se trans-

Cpp es el acrnimo de "C Preprocessor" -o sea, "Preprocesador de C"-, lo que indica suficientemente su carcter bsico de herencia de C adquirida por C++. Como en las malas herencia de la vida jurdica real, no hay ms remedio que resignarse: se trata de una deuda.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 30

forma en un puntero a Objeto, y todo funciona como en los cuentos de Perrault. Bien, sigamos. Pero antes una consideracin adicional: y si deseramos mantener una coleccin de bibliotecas -o sea, una coleccin de colecciones? Pues no tendramos ms que volver a aplicar el esquema derivativo. Esto es, necesitaramos que la misma clase Coleccion derivara tambin, directa o indirectamente, de la clase Objeto:
class Coleccion : public Objeto { // sigue descripcin de la clase };

para as poder codificar lo siguiente:


Coleccion misBibliotecas; Coleccion* miBibliotecaErotica = new Coleccion; misBibliotecas.inserta( miBibliotecaErotica );

Por otro lado ahora podemos mantener perfectamente en el mismo mbito varias colecciones conteniendo tipos distintos, pues en realidad se tratar de objetos del mismo tipo: una coleccin de enteros es exactamente del mismo tipo que otra de caracteres (ambas son instanciaciones de la clase Coleccion). Resulta as que todas nuestras clases derivarn de Objeto: o sea todas las instancias que manejemos sern Objetos (no olvidemos que la derivacin pblica en C++ representa relaciones "ES-UN"). Y aqu nos enfrentamos con el primer problema. Qu pasa si codificamos lo siguiente?
Coleccion misEnteros; int* pEntero = 7; misEnteros.inserta( pEntero );

pues que obtendremos un bonito error! Pasamos como argumento un puntero a un int, pero "int" no es un tipo derivado de "Objeto", y por lo tanto el compilador se queja. Qu hacer, entonces? Pues tenemos dos soluciones: bien codificamos una serie de funciones miembros sobrecargadas que puedan manejar los tipos predefinidos:
class Coleccion : public Objeto { public: bool inserta( int ); bool inserta( float ); // ... resto tipos predefinidos bool inserta( Objeto* ); // sigue resto descripcin clase };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 31

bien encapsulamos tales tipos en sendas clases derivadas, stas s, de la clase Objeto, de la forma:
class Entero : public Objeto { friend Entero operator+( const Entero&, const Entero& ); private: int valor; public: Entero( int entero = 0 ) : valor( entero ) {} // etc., etc., };

de tal manera que ahora s se podr escribir


Entero* pEntero = new Entero( 4019 ); Coleccion* misEnteros = new Coleccion(); misEnteros->inserta( pEntero );

Cul es la mejor opcin? Bueno, pinsese que codificar una clase simuladora de un tipo predefinido no es un ejercicio trivial, y habra que hacerlo para cada uno de los tipos definidos en el sistema: float, long, char, etc. En contrapartida, si nos hacemos con el conjunto de tales clases en el futuro podremos utilizarlos sin codificacin adicional en cualquiera de los contenedores que manejen Objetos, pero a costa de obligar al programador a no usar los tipos predefinidos, de tal manera que se influye en el posible cdigo ya existente cuando se intentan usar estos contenedores, so pena de usar una mixtura de operadores de conversin y de sobrecarga, algo que casi nunca funciona totalmente de la forma deseada. La opcin de la sobrecarga de las funciones miembros es, por otro lado, menos intrusiva, pero obliga a la codificacin repetitiva de las funciones en cada nueva clase contenedora, de forma que cada nueva funcin miembro que se adicione y contenga punteros a Objeto en su signatura deber ser replicada para cada uno de los tipos predefinidos. Si suponemos una jerarqua estable de contenedores esta sera la opcin menos desventajosa: de hecho es la elegida por la mayora de bibliotecas comerciales. Ya hemos visto que el enfoque derivativo en contenedores presenta problemas respecto de los tipos predefinidos. Ahora veremos que tales problemas persisten en los tipos definidos-por-el-usuario (las clases): nuestro enfoque se basa en que los objetos de una determinada clase podrn ser insertados en nuestros contenedores si derivan de la clase Objeto, pero qu ocurre si necesitamos utilizar objetos de clases pertenecientes a una biblioteca comercial aparte? Imaginemos, por ejemplo, que una jerarqua de clases comercial nos proporciona una clase "Politico" que deseamos usar en nuestra aplicacin: qu sabe tal jerarqua de nuestra clase Objeto? Probablemente nada, as que aadir a tal clase una nueva clase base (Objeto) va a resultar, si no imposible, s ciertamente costoso, porque, en

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 32

cualquier caso, la biblioteca comercial no est preparada para conjuntarse con la nuestra. Y adems habra que modificar el cdigo de la biblioteca comercial: algo calificado como anatema, pues habra que repetir tales modificaciones (y volver a comprobar su repercusin) en cada versin de la misma. Y, con todo, suponemos que disponemos del cdigo fuente de la biblioteca para poder modificar las clases, algo que no siempre ocurre. De lo anterior se infiere la necesidad -al menos hasta que examinemos esta cuestin bajo la luz de la herencia mltiple- que todos los contenidos hayan de ser "Objetos", pero la misma naturaleza polimrfica del contenedor fuerza el siguiente corolario: "cualquier Objeto (instancia de una clase derivada de Objeto) puede insertarse en nuestro contenedor". Esto significa que no podemos garantizar la homogeneidad de los tipos que maneje un contenedor dado. Examinemos el siguiente cdigo:
class ColeccionOrdenada : public Coleccion { public: Objeto* primero(); Objeto* ultimo(); // etc., etc. }; class Persona : public Objeto { public: Persona( char* = 0 ); int edad(); // etc., etc. }; class ElementoQuimico : public Objeto { public: ElementoQuimico(); ElementoQuimico( char*, char* ); char* nomenclatura(); // etc., etc. }; ColeccionOrdenada miBolsa; Persona analista( "Ricardo Lara" ); ElementoQuimico analito( "Sodio", "Na" ); miBolsa.inserta( analito ); miBolsa.inserta( analista );

Estamos introduciendo indiscriminadamente en la misma coleccin tanto objetos de tipo Persona como objetos de tipo ElementoQuimico. Qu ocurrir si escribimos lo siguiente?
cout << miBolsa.ultimo()->edad();

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 33

El lector pensar que si el ltimo elemento es una Persona la lnea funcionar perfectamente. Pues no. Resulta que la funcin miembro "ultimo()" devuelve un puntero a Objeto (en realidad un puntero a la porcin de Objeto contenida en el objeto accedido), y sobre este puntero se aplica la funcin "edad()", pero la clase Objeto no tiene definida tal funcin, por lo que el compilador arrojar un lgico error. Necesitamos, pues, un cast que troque el puntero a Objeto en un puntero a nuestra clase deseada (esta es, Persona), y explicitar la sintaxis con profusin de parntesis:
cout << ( (Persona*)(miBolsa.ultimo()) )->edad();

Esto es lo que se denomina un "downcast" (o sea, un cast de una clase base a una clase derivada de sta). As, claro, la lnea funciona si el ltimo elemento es una Persona. Pero qu ocurre si tal elemento es un ElementoQuimico? Pues que se estar aplicando un cast sin sentido a tal objeto, obteniendo resultados impredecibles. Y encima este error no lo puede detectar el compilador (es un tp ico error de ejecucin). Pero la cosa se puede complicar an ms: imaginemos la siguiente jerarqua:
class Ente : virtual public Objeto { /* ... */ }; class Elemento : virtual public Objeto { /* ... */ }; class Persona : public Ente, public Elemento { /* ... */ };

En este caso Persona derivara "virtualmente" de Objeto, y entonces ... la lnea con el cast originara un error en compilacin!, pues resulta que el lenguaje no permite un "downcasting" de una clase base virtual a una clase derivada de sta (y el lector que dude de esta afirmacin debera urgentemente consultar el ARM). La biblioteca NIH (cuya referencia encontrar ms adelante el lector) dispone, sin embargo, de una triquiuela para salvar esta imposibilidad, facilitando un conjunto de funciones estticas con identificador "castdown(...)" que, mediante macrosubstituciones del preprocesador, se generan automticamente para cada clase del sistema. Pero, como ya sabe el lector, las soluciones del cpp no nos gustan, as que ... al saco! Naturalmente una posible solucin es evitar la aplicacin de moldeos (casts) en contenedores de este tipo (y no es una idea descabellada intentar evitarlos en general), para lo cual deberamos dotar a la clase base de funciones virtuales (usualmente puras) que debern ser redefinidas en cada clase derivada, con independencia de que tales sean efectivamente usadas o no por la clase derivada. De todas formas, a pesar que Persona y ElementoQuimico comparten algn que otro elemento comn, la edad no puede aplicarse a un ElementoQuimico, por lo

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 34

que el cast aparece inevitable 7. Para poder aplicar una cierta validacin de tipos necesitaramos un contenedor como el siguiente:
class ColeccionDePersonas : public Objeto { public: bool inserta( Persona* ); // etc., etc. };

Lo que ocurre es que de esta manera ... perdemos por completo la genericidad objeto de las presentes disquisiciones! Podramos, por otra parte, intentar la siguiente desgraciada triquiuela, usando del mecanismo de identificacin de tipos en tiempo de ejecucin (el esquema se ha simplificado de forma grosera para evitar perdernos en profundidades que ahora mismo resultan un poco lejanas, sobre todo teniendo en cuenta que la clase "typeid" est pendiente todava de definicin en el estndar del lenguaje 8):
#include <typeinfo.h> class Coleccion : public Objeto { public: Coleccion( Objeto* = 0 ); type_info& tipo() { return typeid( tipoDeColeccion ); } bool inserta( Objeto* ); private: // el siguiente objeto se usar para determinar // el tipo de la coleccin, en razn del tipo // del argumento usado en su creacin. Objeto* tipoDeColeccion; // etc., etc. }; Coleccion::Coleccion( Objeto* tipoDeObjeto ) : tipoDeColeccion( 0 ) { if ( tipoDeObjeto ) tipoDeColeccion = tipoDeObjeto->clone(); // sigue resto del constructor

A no ser que creemos lo que se denomina una "Flat Base Class", o sea, una clase base dotada de un abrumador nmero de funciones virtuales puras, comprehensivas de toda la posible funcionalidad de sus clases derivadas, presentes y futuras. Esto suele dar lugar, en jerarquas poco meditadas, a verdaderos pastiches formales. 8 El ejemplo siguiente se basa en lo que se denomina RTTI (Run-Time Type Identification: Identificacin de Tipos en Tiempo de Ejecucin), y a pesar de la actual indefinicin del estndar, ya se pueden encontrar implementaciones concretas en compiladores, como por ejemplo en Borland C++ 4.XX.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 35

} bool Coleccion::inserta( Objeto* candidato ) { if ( tipoDeColeccion && !( tipo().before( typeid( candidato ) ) ) return FALSE; // aqu se efecta la operacin de insercin return TRUE; }

Con esta esquema se dara la posibilidad de crear "Colecciones con Tipo" (o "Colecciones Tipificadas") pasando un argumento en el constructor que, copiado a un dato miembro de la clase, mantenga la informacin del tipo de objeto que se desea manejar. En cada llamada a la funcin de insercin se comparara el tipo del objeto candidato a insertar con el tipo del objeto con el que se cre, en su caso, la coleccin, de manera que si el objeto candidato pertenece a la misma clase que tal objeto, o a una clase derivada de sta (de ah el before(...)), entonces se proceder a la insercin; en otro caso no se efectuar la insercin y la funcin devolver un valor de FALSE. Bien, parece que esto puede funcionar, pero ... no convence del todo!, pues recuerda los tan denostados campos selectores de tipo (con mejoras, naturalmente). Resulta, as, que la rapidez y efectividad de nuestro cdigo quedan efectivamente mermadas, el tamao de la coleccin aumenta al aadir un nuevo dato miembro, y se nos fuerza a codificar en cada clase derivada de Objeto una funcin virtual de clonacin que devuelva un puntero a un nuevo objeto copia de se al que se aplica. Aparte de que, al producirse la comparacin en tiempo de ejecucin, se pierde el chequeo esttico de tipos, tan propio de C++. Adems, a los inconvenientes expresados se aaden los debidos a la derivacin forzosa desde la clase Objeto. Tenemos, en general, que en el tipo de contenedores que ahora nos ocupa "todo son Objetos". Esto significa que, al forzar un grado mnimo de derivacin en cada clase y en virtud de los mecanismos de derivacin propios de C++, cada vez que se llame a un constructor de un objeto "contenido" se llamar tambin, de forma dirigida por la lista de inicializacin o no, a cada uno de los constructores de las clases base de esa a la que el objeto pertenece. En todo caso siempre se llamar al constructor de la clase Objeto, y si ste no es trivial entonces una lnea como
Persona multitud[ 100000 ];

originar cien mil llamadas al constructor por defecto de Objeto, y, francamente, el asunto puede resultar muy costoso. Adems cada porcin de la clase base Objeto contenida en objetos de clases derivadas de sta incluir un puntero a la tabla de funciones virtuales de Objeto, utilizando as una memoria en ocasiones valiossima.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 36

Bueno, lo estamos pintando muy negro, pero la verdad es que los problemas del enfoque derivativo no acaban aqu: pasemos a un nuevo captulo de molestias. Dado que la conversin implcita de tipos exige el paso de argumentos mediante punteros y las referencias son desechadas, las funciones miembros de nuestros contenedores que manejen elementos no pueden trabajar con objetos. Al trabajar con punteros aparecen, pues, una serie de errores, relacionados con lo que se denomina CRUD 9, demasiado comunes para considerarlos meras curiosidades, casi todos ellos basados en los desajustes de gestin de memoria entre contenedores y contenidos. As, por ejemplo, un esquema muy extendido es el siguiente:
void afiliate() { Coleccion partidoPolitico; partidoPolitico.inserta(new Persona("Juan Nadie")); // aqu, por terminar el mbito de la funcin // se destruye el objeto partidoPolitico }

Vemos que se destruye el contenedor, pero qu pasa con el objeto Persona que hemos insertado? Pues que, al serle asignada memoria del almacenamiento libre, queda sin destruir ocupando memoria til del sistema, y adems sin posibilidad evidente de ser accedido. Estamos suponiendo, naturalmente, que el contenedor no suprime al destruirse los objetos que contiene, porque si as fuera nos veramos abocados a errores an ms peligrosos:
void afiliateYMuere() { Persona* incauto = new Persona( "Pepe Prez" ); Coleccion* partidoMinimalista = new Coleccion; partidoMinimalista->inserta( incauto ); Coleccion* partidoNeologista = new Coleccion; partidoNeologista->inserta( incauto ); // se ejecuta aqu algn proceso irregular // y se disuelve el partido Neologista // y con ste se "disuelven" tambin todos // sus afiliados, incluido nuestro "incauto" delete partidoNeologista; // seguidamente la caida del partido Neologista // arrastra a la disolucin al partido Minimalista // (temas de empata poltica, ya saben) delete partidoMinimalista; // el desastre! }

CRUD es el acrnimo de "Create, Read, Update & Delete" (Crear, Leer, Actualizar y Borrar) y se refiere a las operaciones ms usuales que pueden aplicarse a objetos.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 37

Cul es el problema aqu? Pues que al destruirse el partido Minimalista intenta destruir a todos sus miembros, pero resulta que el objeto al que apunta el identificador "incauto" ya ha sido destruido anteriormente, por lo que el resultado de aplicar el operador "delete" a tal puntero es impredecible. Naturalmente obtendramos el mismo desastroso resultado si destruyramos "a mano" los objetos contenidos. Esta es, de hecho, la poderosa razn por la que los contenedores de la mayora de bibliotecas comerciales no destruyen a sus objetos contenidos cuando se destruyen ellos mismos. Otra solucin muy socorrida es proveer a la clase Objeto de las siguientes funciones:
class Objeto { public: // copia superficial o referencial de objetos virtual Objeto* shallowCopy(); // copia profunda o estructural de objetos Objeto* deepCopy(); // convierte una deepCopy en una shallowCopy virtual void deepenShallowCopy(); // etc., etc., como siempre };

de forma que shallowCopy() copia "bit a bit" un objeto (usando normalmente el constructor de copia por defecto), mientras que deepCopy() replica completamente el objeto obteniendo uno nuevo sin referencias del original. Se deja, as, a criterio del usuario de las clases el tipo de copia deseado, de manera que, por ejemplo, puede manejarse un contenedor que destruya su contenido usando de la funcin deepCopy() y duplicando, por tanto, los objetos antes de insertarlos. Pero los peligros de los punteros no acaban aqu. Consideren, si no, el siguiente cdigo:
Coleccion partidoContrapopular; void afiliateYVeras() { Persona personaDePaso( "Eutimio" ); // atencin: seguidamente se inserta en la coleccin // un puntero a un objeto de mbito local. partidoContrapopular.inserta( &personaDePaso ); // aqu se acaba el mbito de la funcin y se // destruye el objeto automtico "personaDePaso" }

Nos encontramos con una coleccin que contiene, como en el caso anterior, un puntero a un objeto que ya no existe. Cualquier operacin sobre la coleccin que afecte a tal puntero originar ... cualquier cosa, usualmente muy desagradable.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 38

Vemos, pues, que se dan muchos problemas pero, demonios, no todo es tan malo en el esquema de diseo de contenedores por derivacin. Despus de todo es un enfoque que funciona en Smalltalk <sic> y en las jerarquas de clases C++ consideradas como un "idioma" o "patrn" (pattern) Smalltalk, casi todas ellas descendientes de la biblioteca NIH de Keith Gorlen et al.10, aunque en sta el mecanismo de identificacin de tipos recae, de una forma muy propia de Smalltalk, en una clase denominada Class. Adems estas jerarquas csmicas (pues as se denominan las jerarquas de clases que tienen una nica clase base) son muy prcticas cuando se trata de obtener una adecuada granulacin de objetos en base a sus relaciones de herencia. Vamos a intentar explicarlo con un ejemplo: supongamos la siguiente jerarqua (que respeta escrupulosamente la directriz ESUN, aunque de estas cuitas ya hablaremos ms adelante):
Objeto Bien BienMueble Prenda Pulsera

Supongamos que montamos un esquema de codificacin que, para cada clase, inserte cada nuevo objeto en una coleccin representativa del tipo (lo que se denomina -en ingls- el "extent"), y lo extraiga en el momento de su destruccin. Vemoslo:
class Objeto { public: Objeto() { extent.inserta( this ); } ~Objeto() { extent.extrae( this ); } private: static Coleccion extent; // etc., etc. }; class Bien : public Objeto { public: Bien() { extent.inserta( this ); } ~Bien() { extent.extrae( this ); } private: static Coleccion extent; // etc., etc. };

10

La biblioteca NIH es, para gozo del lector, de dominio pblico y puede encontrarse en la mayora de servicios on-line: Internet, BIX, Compuserve, etc. Aunque yo, personalmente, no prescindira del libro en que se explicitan las decisiones de diseo de tal biblioteca, un clsico ya de la programacin en C++: Data Abstraction and Object-Oriented Programming in C++, Gorlen, Orlow & Plexico, 1990, John Wiley & Sons, 0-471-92346-X.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 39

// aqu se repite el mismo esquema para todas las // clases de la jerarqua, hasta llegar a la terminal class Pulsera : public Prenda { public: Pulsera( String* unaMarca = 0 ) { // la clase String tiene definido el // constructor de copia, naturalmente marca = new String( *unaMarca ); extent.inserta( this ); } ~Pulsera() { delete marca; extent.extrae( this ); } static Coleccion& getColeccion() { return extent; } private: static Coleccion extent; String* marca; // etc., etc. };

De esta manera cada vez que creemos un nuevo objeto de alguna de estas clases automticamente se insertar en la coleccin esttica (nica para todos los objetos de la clase) correspondiente a su tipo (con el nombre "CLASE::extent" y accesible a travs de las correspondientes funciones miembros pblicas estticas, que aqu se han obviado). As, por ejemplo, la lnea
Pulsera* miPulseraDeCompromiso = new Pulsera( "Cartier" );

insertar mi pulsera de marca en el extent de pulseras. Pero, atencin, como sabemos que el constructor de Pulsera automticamente llamar al constructor de su clase base -Prenda-, y ste a su vez al de su respectiva clase base, hasta llegar a la clase Objeto, resultar que el mismo objeto Pulsera se insertar en cada una de las colecciones estticas de las clases bases de Pulsera. Vaya, pero esto puede resultar muy costoso! Y, para qu sirve? Muy fcil: imaginemos que deseamos relacionar, para su posterior impresin o visionado, todos los objetos existentes del tipo (de la clase) BienMueble. Dado que las pulseras son bienes muebles, el comportamiento lgico a esperar es que mi pulsera de compromiso aparezca en tal relacin. Y as es en este caso. Se trata, en definitiva, del polimorfismo aplicado a las jerarquas. Cuando se destruya el objeto pulsera:
delete miPulseraDeCompromiso;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 40

al entrar en accin los destructores de las clases bases (en orden inverso al de construccin, como el voraz lector ya sabe), se extraer tal objeto de cada una de las colecciones. Un corolario lgico es que la coleccin esttica de la clase Objeto contendr en cada momento todas las instancias de clases disponibles en nuestra aplicacin. De cualquier forma, y como ya se ha dicho, este es un esquema particularmente poco eficiente, as que slo se usar cuando el polimorfismo que proporciona sea real y positivamente necesario (lstima que no existan todava mecanismos ni mtricas orientadas-a-objetos maduras que permitan calibrar tal necesidad). Tenemos, pues, que el esquema de derivacin simple no encaja demasiado bien con lo que queremos. Pero, puesto que estamos en C++ y no en Smalltalk, no nos podra ofrecer alguna solucin la herencia mltiple? Bueno, es justo que le echemos un vistazo. HERENCIA MLTIPLE: MS DE LO MISMO? Como no queremos, y normalmente no podemos conseguir, que todas nuestras clases deriven de Objeto, vamos a intentar un enfoque matizadamente distinto. Se trata de, para no modificar nuestra clase, crear una nueva clase que derive a la vez de sta y de Objeto. Esto es, si tenemos:
class Cliente { // descripcin de clase };

crearamos una nueva clase:


class ObjCliente : public Objeto, private Cliente { // descripcin de clase };

de forma que as se facilitara la parametrizacin de contenedores respecto de clases de las que no podemos obtener el cdigo fuente, o que no pudieran ser modificadas. De cualquier forma el esquema no cambia mucho y, sin embargo, nos procura complicaciones adicionales, pues deberemos dotar a nuestra nueva clase de un interfaz mnimo: constructores, sobrecargas del operador de asignacin, del operador de comparacin, etc. Pero lo peor es, sin duda, que tendramos que usar objetos de una clase distinta a la prevista: un ObjCliente NO-ES, en sentido estricto, un Cliente, y en realidad la derivacin pblica de Cliente tampoco nos solucionara este problema de fondo. Imaginemos un sistema persistente donde a cada objeto se le otorga un identificador nico (cual es el caso de la mayora de las bases de objetos, donde a cada objeto se le asigna un OID: object identifier): el hecho de instanciar un objeto de una nueva clase supone la asigna-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 41

cin de un nuevo identificador, de forma que no se mantiene la integridad referencial, que debera aqu ser expresamente codificada (o sea: problemas!). Claro que algo se puede arreglar -nunca se arregla todo, como el desencantado lector ya puede intuir- a costa de complicar un tanto -o mejor un mucho- el esquema de derivacin y de relaciones entre clases. Se trata, en esencia, de aplicar a nuestros contenedores un patrn conocido como de clases "Sobre/Carta" montado sobre un mecanismo virtual que permita la insercin y extraccin de objetos en contenedores sin tener que realizar "casts" expresos. Este patrn est suficientemente explicitado en el libro de Coplien11, y junto con el patrn o idioma de "Ejemplares" proporciona soporte para una parametrizacin en tiempo de ejecucin de nuestros contenedores. Pero quizs este modelado sobrepase el tono resueltamente elemental del presente captulo. Adems, qu demonios son "patrones"? En pocas palabras: se trata de construcciones idiomticas con personalidad y estructuracin propias, que conllevan particulares formas de codificar y modelar los problemas12. Pero esto, aparte de resultar muy extenso, en realidad es relativamente nuevo (de hecho existe en Internet un grupo de discusin de patrones via correo electrnico al que se puede apuntar cualquier interesado), as que volvamos a nuestras cuitas anteriores: puede solucionar la conjuncin de herencia mltiple y el uso de patrones nuestros problemas de parametrizacin de contenedores? S en buena medida, pero bsicamente a costa de la eficiencia y del chequeo esttico de tipos, aparte de que se genera la necesidad de mantener un esquema derivativo no trivial en el que hay que insertar cada nueva clase (esto es, se hace necesario un "administrador" de la parametrizacin). Pero la cosa no acaba aqu. ITERADORES Los contenedores agrupan objetos que, tras ser debidamente insertados, necesitarn ser accedidos, y este trabajo lo facilitan los iteradores. Un iterador es, en esencia, un objeto que, de forma secuencial, accede a los objetos insertos en un contenedor, y su implementacin se basa, por lo general, en un dato miembro que apunta al contenedor sobre el que opera y en datos miembros que apuntan a los objetos en cada momento accedidos. Algo as como:
class Iterador { public: Iterador( Coleccion* coleccion ) :

11

Advanced C++ Programming Styles and Idioms, James O. Coplien, 1992, Addison-Wesley, 0201-54855-0. 12 El lector inquieto puede leer el excelente texto Design Patterns: Elements of Reusable ObjectOriented Software, de Gamma, Helm, Johnson & Vlissides, 1994, Addison-Wesley, 0-201-633612.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 42

contenedor( coleccion ); void rebobina(); Objeto* operator(); Objeto* operator++(); private: Coleccion* contenedor; Objeto* objetoSeleccionado; // etc., etc. };

Se trata de un iterador genrico que, al operar sobre Objetos puede manejar cualquier tipo derivado. El operador () devuelve un puntero al objeto actualmente apuntado, mientras que el operador ++ llama a la tpica funcin next() del contenedor para devolver un puntero al prximo objeto en la secuencia. Perfecto? Bueno, como el lector ya habr adivinado, aqu se nos plantea el mismo problema de downcasting anterior. Examinemos una porcin de cdigo:
Coleccion* piara = new Coleccion; // aqu se insertaran los distintos objetos // de la clase Cerdo, derivada de Objeto. piara->inserta( porky ); piara->inserta( echanove ); // etc., etc., // seguidamente se define un iterador // afecto a nuestra coleccin Iterador iterador( piara ); // se rebobina al principio de la coleccin iterador.rebobina(); // como first() // y ahora se accede al primer objeto ((Cerdo*)iterador())->groink();

Por supuesto que si suprimiramos el cast a Cerdo* la ltima lnea no funcionara, y pensar que la funcin groink() debe ser virtual en Objeto no casa con la mnima prudencia y el decoro que se le suponen a un programador. Entonces, cmo solucionar este problema y los anteriormente expuestos? Con las plantillas, naturalmente! Pasemos a ello. LAS PLANTILLAS: CON HERENCIA, SIN ELLA O A SU PESAR Qu es una plantilla? En primer lugar la traduccin, desafortunada o no, del trmino "template", actualmente parte del lenguaje C++. Otros autores prefieren "genrico", pero personalmente pienso que esto constituye un sobreabuso del vocablo (adjetivo, al fin y al cabo). Se trata, en definitiva, de un concepto asociado al de "parametrizacin de tipos", de manera que se usarn "plantillas" para implementar en C++ estructuras de datos (objetos contenedores, de forma ms explcita) y algoritmos independientes en buena medida (aunque no absolutamente) de los tipos de objetos sobre los que operan o se aplican.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 43

En resumen, y dado que en este captulo no examinaremos la sintaxis de las plantillas, ahora podramos codificar una coleccin genrica de la siguiente forma:
template <class T> class Coleccion { public: bool inserta( T* ); T* extrae( T* ); // etc., etc. };

donde "T" ha de ser sustituido por el tipo de objeto (clase o predefinido) que deseamos manejar en nuestra coleccin (y obviaremos momentneamente el espinoso asunto de los punteros y los objetos en plantillas). Pero esta sustitucin se produce mediante la "instanciacin" de la plantilla en una lnea como la siguiente:
Coleccion< Politico > parlamento;

de tal forma que las siguientes lneas:


Perro miPerro = new Perro( "Buck" ); parlamento.inserta( miPerro );

originarn un error en tiempo de compilacin (algo que no habamos podido conseguir con el esquema derivativo), pues se est pasando como argumento un puntero a un Perro, mientras que lo que se espera es un puntero a Politico. A la vez tenemos que la siguiente lnea
cout << (parlamento.extrae( pPolitico ))->partido();

funciona sin cast alguno, pues la funcin miembro devuelve directamente un puntero a Politico (en este caso), y no un puntero a una clase base (cual era el caso con Objeto en el enfoque anterior) que necesitara de un "downcast" para poder acceder a una funcin miembro de la clase adecuada. Bien: hemos visto, aun muy brevemente, que el enfoque de plantillas soluciona los problemas planteados. Cul es el siguiente paso? Parece que habra que usar la sintaxis de plantillas para codificar las clases contenedoras que necesitemos. Pero, es lgico que cada programador haya de enfrentarse individualmente al no-trivial problema de codificar los mismos contenedores? O sea, hay que inventar la rueda cada vez? Naturalmente que no! El lector puede estar seguro que existen multitud de bibliotecas comerciales con particulares implementaciones de contenedores mediante plantillas (Rogue Wave, Borland, etc.). Pero, cul elegir? Ninguna de ellas! Resulta que, como ya se anunci al principio de este captulo, C++ ya posee su propia biblioteca estndar de plantillas (STL), desarrollada por

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 44

Alex Stepanov en los laboratorios HP y puesta por Hewlett Packard en el dominio pblico, liberando todas las licencias a ella afectas. Cualquier interesado puede acceder al cdigo fuente completo de la STL via ftp annimo o va e-mail, aunque el fichero tambin puede encontrarse en distintos servicios electrnicos, como por ejemplo en el forum de Microsoft Espaa en Compuserve. La STL supone un trabajo de desarrollo de unos diez aos, y el cdigo C++ es de una calidad que impresiona, con dos particularidades notables: en absoluto se usa de la herencia en esta biblioteca y el tratamiento algortmico recuerda las mejores bibliotecas fortran. Pero el uso de la STL y su integracin en los esquemas de programacin en C++ es asunto prolijo que necesita de un captulo exclusivo: el siguiente.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 45

3
C++ STL

a STL, acrnimo de Standard Template Library (Biblioteca Estndar de Plantillas), es, segn Stroustrup, un entorno-marco, formado por contenedores, iteradores y algoritmos, que resulta grande, sistemtico, limpio, formalmente completo, comprehensible, elegante y eficiente. Y adems codificado en C++. Tantos elogios los recibe una biblioteca-marco de clases derivada de los trabajos de Dave Musser y Alex Stepanov en Hewlett Packard, cuyo propsito primero fue la produccin de una estructura de cdigo que permitiera la creacin, en su seno, de algoritmos reutilizables. Tras un proceso iterativo de acoplamiento a Scheme, Ada y finalmente C++, en Noviembre de 1.993 el propio Stepanov junto con Meng Lee presentaron al Comit de Estandarizacin ANSI/ISO X3J16 la biblioteca, que fue aceptada como parte de la Biblioteca Estndar de C++ en julio de 1.994 e incorporada al borrador del estndar del lenguaje. Bien, bien: parece que la STL es fabulosa, pero, tras esta exposicin histrica, para qu demonios sirve? Durante mucho tiempo se ha achacado a C++ la carencia de estructuras de datos con funcionalidad suficiente para procurar las bases de una deseada genericidad en la codificacin. Y la STL proporciona justamente eso: un conjunto de estructuras de datos y de algoritmos que operan sobre aqullas. Pero sobre todo procura, segn Koenig, un entorno conceptual que facilita a los usuarios la adicin de sus propios algoritmos y estructuras de datos de una forma ciertamente genrica: los nuevos algoritmos funcionarn con todas las estructuras de datos (contenedores) existentes, a la vez que sobre las nuevas estructuras de datos se podrn aplicar todos los algoritmos existentes. La STL viene, pues, a cubrir un hueco mal tapado hasta ahora por macros y clases noestandarizadas, propias o de bibliotecas comerciales, usualmente poco efectivas, con un uso inadecuado de la herencia, con escaso o nulo chequeo de tipos, tan sustancial a C++. En los pragrafos siguientes se expondr, trufado con varios ejemplos (validados con VisualAge C++ para OS/2 y STL<ToolKit>), un acercamiento a la STL que no se pretende exhaustivo (toda vez que la sola descripcin completa de las clases y algoritmos involucrados supera con mucho el mbito de un captulo estndar, ademas de existir un excelente manual de dominio pblico en que tales se deta-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 46

llan), sino ms bien comprehensivo e inicitico. No se detallar, tampoco, la sintaxis y uso de las plantillas en C++. En definitiva mi intencin es transmitir al lector el espritu de la STL y la animosidad suficiente para que pueda usarla con efectividad, esperando, entre otras cosas, no vuelva a usar otra clase vector que la provista por esta biblioteca13. A ello. ESTRUCTURA DE LA BIBLIOTECA La STL est construida sobre cinco componentes:

algoritmo contenedor iterador objeto-funcin adaptador

define un procedimiento computacional gestiona un conjunto de localizaciones en memoria provee un medio para que un algoritmo recorra un contenedor encapsula una funcin en un objeto reutilizable por otros componentes adapta un componente para procurarle un interfaz distinto

aunque la relacin fundamental entre componentes podra establecerse as:

algoritmos -------------------------- iteradores --------------------------- contenedores

Esto es, el ncleo de la STL son los algoritmos, que utilizan iteradores para acceder a contenedores. Como bien explican Stepanov y Lee, si quisiramos codificar c contenedores para t tipos de datos accesibles mediante a algoritmos, deberamos contemplar c*t*a combinaciones. Debido a la parametrizacin de tipos que procuran las plantillas, la STL slo necesitara c*a combinaciones, que finalmente se reducen a a+c por la reutilizacin de los algoritmos en diferentes contenedores. Adicionalmente los componentes de la STL son al menos tan eficientes como los codificados a-mano (debido al uso del inlining y el prcticamente nulo uso de la derivacin); proveen un fuerte chequeo de tipos (mediante el uso de plantillas); sus iteradores son generalizaciones de los punteros (pudiendo usarse donde tales aparecen, singularmente en los arrays de C); y permiten el uso, sobre todo en
13

Mucha gente piensa, como Prmontal, que las bibliotecas son como las farmacias: muchos venenos y pocos remedios. As que prefieren las soluciones caseras a-mano. El mercado mismo evidencia su error.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 47

algoritmos, de funciones encapsuladas en objetos (tambin como el uso de las tpicas funciones C/C++). CONTENEDORES En la STL se dan las siguientes categoras de contenedores, que en definitiva son objetos que contienen otros objetos:

Secuencial Asociativo Adaptador

el almacenamiento de tems es lineal, con inserciones rpidas al final (vector, ...) estructuras adecuadas para las bsquedas asociativas rpidas (conjuntos, ...) interfaces a otros tipos de colecciones (colas, pilas, ...)

que a su vez encierran las siguientes colecciones concretas, todas ellas codificadas en C++ mediante plantillas y con las subdisiviones que se indican:

vector bit_vector deque list

multiset set multimap map

COLECCIONES DE PRIMERA CLASE Colecciones Secuenciales almacenamiento contiguo y linear de elementos, con inserciones rpidas al final. vector de bits. doble cola, como un vector, con posibilidad de inserciones rpidas de elementos en sus dos extremos. lista doblemente enlazada, en la que se pueden insertar elementos en cualquier lugar. Colecciones Asociativas conjunto no ordenado en que se permiten duplicados. conjunto, como el multiset, pero en el que no se permiten duplicados. coleccin de correspondencias de 1-a-muchos. coleccin de correspondencias de 1-a-1.

stack queue priority_queue

ADAPTADORES pila, en la que el primer elemento en entrar es el ltimo en salir. cola, en la que el primer elemento en entrar es el primero en salir. cola que mantiene sus elementos en orden.

Todas las colecciones de la STL tienen definido un interfaz mnimo, compuesto por las siguientes funciones pblicas (se usar el contenedor list para los prototipos):

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 48

Descripcin Constructor Constructor Copia Destructor Tamao mximo Tamao Intercambio Asignacin Igualdad Comparacin orden

Prototipo de las funciones miembros list() list( const list<T>& lista ) ~list() size_type max_size() const size_type size() const void swap( list<T>& lista ) list<T>& operator=( const list<T>& lista ) bool operator==( const list<T>& lista ) const bool operator<( const list<T>& lista ) const

T D C D T T A A C C

STL provee otras funciones de comparacin (C) que se derivan (en sentido figurado) de los operadores == y <, a saber: <=, >=, > y !=. En realidad STL provee tales operadores adicionales para cualquier objeto, supuesta la existencia de los dos primeros. Pero veamos un ejemplo de uso de los contenedores STL:
class Politico{ /* protocolo */ }; Politico felipe, joseMaria, julio; // material de relleno // definimos una lista doblemente-enlazada de Politicos list<Politico> camarilla; camarilla.push_back( felipe ); // inserta al final camarilla.push_front( joseMaria ); // inserta al principio // crea un iterador (que se ver ms adelante) del tipo adecuado // y lo inicializa apuntando a la primera posicin de la lista list<Politico>::iterator iterador = camarilla.begin(); // inserta un nuevo politico en la segunda posicin de la lista camarilla.insert( ++iterador, julio ); // le da la vuelta a la lista (julio sigue en medio) camarilla.reverse(); camarilla.size(); // el tamao actual de la lista: 3

Los adaptadores son, en esencia, plantillas que procuran un interfaz especial para los otros tipos de contenedores. As cualquier contenedor que soporte las operaciones de push_back y pop_back (como vector, list y queue) puede ser usado para instanciar stack. Si se aade la operacin front , entonces se podr instanciar una priority_queue. Por fin queue podr instanciarse con contenedores que soporten front , back, push_back y pop_front . Como el lector fcilmente habr adivinado, los adaptadores adaptan o adecan un determinado contenedor para que adopte un nuevo comportamiento, restringiendo ciertas caractersticas y cambiando otras.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 49

Bien, bien -exclamar el impaciente lector- Todo esto est muy bien, pero yo ya uso los contenedores de la biblioteca de clases X (o de una propia) que me van estupendamente. Estupendo! Pero el nfasis de la STL no est en los contenedores, sino en los algoritmos (que veremos poco despus). De cualquier manera la genericidad que otorgan las plantillas es difcilmente superable por una biblioteca comercial, y la efectividad de los contenedores de la STL es, por otro lado, virtualmente inmejorable. Pero de poco sirve una mera estructura sin las herramientas que permitan accederla, revisar y modificar tanto su propia configuracin como los tems que contenga. Y aqu aparecen los iteradores. ITERADORES Segn Andrew Koenig, un iterador es algo que permite un conjunto de operaciones en una estructura de datos sin decir nada sobre la naturaleza de tal estructura. Esta definicin resulta especialmente relevante dentro del entorno que proporciona la STL pues sta, centrada en los algoritmos, se encuentra con la dificultad de aplicar stos directamente en los contenedores o estructuras genricas de datos: algunos algoritmos funcionan con ciertas estructuras; otros no. Con la introduccin de los iteradores se genera un nuevo nivel de indireccin que permite, en su calidad de mediador, el perfecto entendimiento entre contenedores y algoritmos. Los iteradores, as, saben poco de algoritmos o de contenedores, de forma que son grandemente independientes de ambos. De esta manera los algoritmos se expresarn en trminos de iteradores, de manera que las estructuras de datos accedidas, en otro nivel, por los iteradores, sern independientes de los primeros. De hecho esto es precisamente lo que diferencia a la STL de otras bibliotecas de clases. Pero, son en realidad los iteradores totalmente independientes de las colecciones que acceden? O sea, cualquier iterador funciona en cualquier contenedor? Humm, parece que no, pues si, en el sentido prctico que nos ocupa, un iterador es un objeto que permite recorrer los elementos de una coleccin, recorrindola (o atravesndola) con distintas estrategias, para cada estrategia quizs haya que procurar un iterador distinto. Ciertamente los iteradores de la STL funcionan, en general, tanto en los contenedores STL, como en los arrays de C o en los streams de C++, pero esto no significa que un iterador (un tipo de iterador) concreto funcione a la vez en todos. Nos hacen falta, pues, varios tipos de iteradores. Vemoslos: InputIterator (iterador de entrada/lectura): lee un solo tem cada vez, en una nica direccin, y su desreferenciacin (*iterator) slo podr ser usada a la derecha de una asignacin: esto es, la desreferenciacin devuelve un elemento constante. Un puntero de C operando sobre un array predefinido es un iterador de lectura (veremos que tambin es de escritura, pero las dos condiciones in-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 50

cluyen la establecida). As, por ejemplo, si consideramos el algoritmo max_element , con signatura:
template<class InputIterator> InputIterator max_element( // iterador en el primer tem del rango elegido InputIterator primero_, // iterador tras el ltimo tem del rango elegido InputIterator ultimo_ )

y cuya funcionalidad es devolver un iterador apuntando al mayor tem dentro del rango [primero, ultimo), para lo que usa el operador <, tenemos que, dado que usa iteradores de lectura, podremos usarlo con arrays y punteros:
int cabala[] = { 666, 17, 7 }; cout << *max_element( cabala + 1, cabala + 2 ) // 17 // la desreferenciacin aplicada al InputIterator que // devuelve el algoritmo procura el tem deseado (slo lectura)

pero tambin con contenedores STL:


vector<int> monroe; // vector cinematogrfico // inserta elementos (int) al final del vector monroe.push_back( 90 ); monroe.push_back( 60 ); monroe.push_back( 90 ); cout << *max_element( ++monroe.begin(), monroe.end() ); 90

//

Repare el lector que la aplicacin de las funciones miembros begin y end al vector devuelve sendos iteradores, que pueden ser directamente usados en el algoritmo. La aplicacin, por otro lado, del operador de pre-incremento origina que el iterador avance una posicin desde el principio, posicionndose en el tem con valor 60, de manera que el algoritmo devuelve un iterador apuntando al tercer elemento con valor 90 del vector, convenientemente desreferenciado. Dejamos al lector suponer cul sera el resultado si se hubiera tomado como rango el vector entero. OutputIterator (Iterador de salida/escritura): Un iterador de escritura es como un iterador de lectura, con la particularidad que su desreferenciacin (*iterator) slo podr ser usada a la izquierda de una asignacin. O sea el iterador de lectura slo lee tems, y el de escritura slo los escribe. Veamos un ejemplo de uso con el algoritmo fill_n, con signatura:
template<class OutputIterator, class Size, class T> void fill_n (

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 51

OutputIterator primero_, rango Size n_, const T& valor_ )

// apunta al primer tem del

// limita el rango: primero_ + n_ // valor de relleno

y cuya funcionalidad es rellenar un contenedor asignando a cada tem, desde el tem apuntado por el iterador primero hasta el lugar n, el valor valor_:
vector<int> quiniela( 15 ); fill_n( quiniela.begin(), quiniela.size(), 1 ); // el iterador de escritura que devuelve la funcin begin() // se utiliza para escribir el valor 1 en el tem apuntado, // y quiniela queda como { 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 }

ForwardIterator (Iterador de lectura-escritura): se denomina as al iterador que a la vez opera como de lectura y escritura, como por ejemplo en el algoritmo iter_swap, con signatura:
template<class ForwardIterator1, class ForwardIterator2> void iter_swap( ForwardIterator1 a_, ForwardIterator2 b_, )

y cuyo sentido es intercambiar los elementos apuntados por los iteradores (cada iterador lee el tem al que apunta, pero tambin lo escribe):
int vector<Politico> listaElectoral; // se rellena la lista // y se procede a aplicar el principio // de intercambiabilidad de los politicos iter_swap( listaElectoral.begin() + 1, listaElectoral.begin() + 4 ); // se ha cambiado el segundo por el quinto

BidirectionalIterator (Iterador bidireccional): se trata de un iterador de lecturaescritura al que se puede aplicar el operador --; esto es, que puede iterar en dos sentidos. Como ejemplo podemos considerar el algoritmo copy_backward, con signatura:
template< class BidirectionalIterator1, class BidirectionalIterator2> BidirectionalIterator2 copy_backward ( BidirectionalIterator1 primero_, // inicio rango origen BidirectionalIterator1 ultimo_, // ++final rango origen BidirectionalIterator2 resultado_ ) // ++final rango destino

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 52

y cuyo propsito es la copia de los elementos comprendidos en el rango [primero_, ultimo) en otro rango cuyo final est indicado por el iterador resultado_ (que apunta a la posicin tras el ltimo elemento del rango). O sea, para copiar se da la posicin final del destino (como si se copiara hacia atrs), copiando mediante el operator= . Lo que se devuelve es otro iterador del mismo tipo que resultado_ pero apuntando al primer elemento del nuevo rango:
vector<Politico> listaPartidoD; vector<Politico> listaPartidoI; // se rellenan ambas listas copy_backward( ++listaPartidoD.begin(), --listaPartidoD.end(), --listaPartidoI.end() ); // ahora ambas listas son iguales menos el // primer y ltimo elemento: la sin par realidad.

RandomAccessIterator (Iterador de acceso aleatorio): se trata de un iterador bidireccional que admite la adicin y substraccin de enteros, la computacin de la distancia entre dos iteradores y la indexacin. Si usamos el algoritmo partial_sort, con signatura:
template<class RandomAccessIterator> void partial_sort ( RandomAccessIterator primero_, RandomAccessIterator medio_, RandomAccessIterator final_ )

y cuya funcionalidad es la de ordenar, usando operator<, los primeros n elementos en el rango [primero_, final), donde n = medio_ - primero_ (operacin permitida slo en los iteradores de acceso aleatorio), dejando el resto del rango en orden indefinido:
int array[ 7 ] = { 6, 4, 2, 1, 5, 3, 7 }; partial_sort( array, array + 4, array + 7 ); // resultado: { 1, 2, 3, 4, 7, 5, 6 }

Como vemos, los punteros de C son, en realidad, iteradores de acceso aleatorio, como el lector ya haba adivinado. De hecho los iteradores son generalizaciones de punteros, y su semntica es una generalizacin de la de aqullos. As Musser expresamente nota que Cualquier tipo de puntero C++, T*, obedece todas las leyes de la categora de iteradores de acceso aleatorio. En resumen, si i y j son iteradores y n un entero cualquiera, se cumple:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 53

Iteradores Operaciones permitidas

Todos ++i i++

Input *i (const) i == j i != j

Output *i i=j

Bidirectional --i i--

Random Access i += n i -= n i+n i-n i[ n ]

dndose la siguiente relacin entre iteradores:

input forward output bidirectional random access

de forma que donde se espera un cierto iterador, puede aplicarse cualquier iterador a su derecha. Y, claro, aqu el lector podra exclamar: Una jerarqua de herencia de iteradores!. Pues no, irredento lector: nada de jerarquas: aunque parezca lo contrario, la clase del iterador bidirectional no deriva de la clase del iterador forward, como no lo hacen tampoco las dems. Andrew Koenig acertadamente afirma que habra que pensar en las relaciones entre iteradores como herencia conceptual, pues un iterador es una familia de tipos relacionados en razn de formas que no son directamente expresables en C++. Adems de los iteradores expuestos, la STL provee otros igualmente tiles: istream_iterator y ostream_iterator (que operan como cin y cout respecto de streams C++ de entrada y salida, respectivamente), reverse_bidirectional_iterator y reverse_iterator (que iteran hacia atrs), insert_iterator (inserta en la posicin a que apunta), back_insert_iterator y front_insert_iterator (slo insertan al final y al principio de un contenedor, respectivamente), etc. Demasiados iteradores! -podra aqu perfectamente exclamar el lector: Cmo saber qu iterador aplicar en cada contenedor o algoritmo? Bueno, respecto de los algoritmos slo hay que mirar su signatura o prototipo; respecto de los contenedores, he aqu la tabla:

Tipo de iterador RandomAccessIterator BidirectionalIterator sin iteradores

Contenedores asociados vector, bit_vector, deque list, multiset, set, multimap, map stack, queue, priority_queue

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 54

donde se explicita algo evidente: nicamente las Colecciones de Primera Clase (esto es, contenedores secuenciales y asociativos) pueden ser accedidas por iteradores. La ligazn entre contenedores, iteradores y algoritmos se produce as: la descripcin de los contenedores incluye la categora de los tipos de iteradores que proveen, mientras que los algoritmos genricos incluyen (en su prototipo) la categora de iteradores con que trabajan. As, para evitarle al usuario la consulta o aprendizaje de tablas como la anterior, cada contenedor define una serie adecuada de typedefs, de forma que la notacin contenedor<class T>::iterator enmascara los tipos:

typedef vector<T>::iterator deque<T>::iterator bit_vector<T>::iterator list<T>::iterator ContenedorAsociativo<T>::iterator

Categora de iterador RandomAccessIterator RandomAccessIterator RandomAccessIterator BidirectionalIterator BidirectionalIterator

Pero adems se dan los siguiente tiles typedefs:

iterator

const_iterator

reverse_iterator

const_reverse_iterato r

para iterar adecuadamente en colecciones escribibles o de slo-lectura, hacia adelante o hacia atrs. De esta manera, podramos trabajar con los iteradores de la siguiente guisa:
list<Politico> cuadrilla; // aqu se rellena la lista, y seguidamente // se define un iterador del tipo adecuado // (que en este caso ser bidireccional) list<Politico>::const_iterator i = cuadrilla.begin(); // y ahora se utiliza el iterador for ( i; i != cuadrilla.end(); i++ ) // supondremos que la clase Politico sobrecarga // el operador de insercin (y esto no parece des// cabellado, pues los polticos lo sobrecargan todo). cout << *i << \n; //imprime la lista // Y ahora al revs list<Politico>::const_reverse_iterator ri; // y en lo siguiente aparecen dos nuevas funciones marcadas // por una r (reverse) inicial: rbegin() devuelve un iterador // posicionado en el ultimo tem, mientras que rend() devuelve

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 55

// un iterador posicionado inmediatamente antes del primer tem. // Su uso es evidente para iteradores que operan al revs. for ( ri = cuadrilla.rbegin(); ri != cuadrilla.rend(); ri++ ) cout << *i << \n;

dejando que los typedefs hagan el trabajo de eleccin del iterador correcto por nosotros. No es sencillamente fantstico? ALGORITMOS He aqu el corazn de la STL: algoritmos reutilizables. Y es que a pesar de la importancia de los algoritmos que acompaan a la biblioteca, lo verdaderamente significativo se encuentra en el entorno-marco que procura protocolos exactos para la adicin de otros muchos algoritmos, tal y como hemos visto al revisar los iteradores. Los algoritmos en la STL hacen uso de iteradores y objetos-funciones (de entre ellos los predicados) para acceder a los elementos de los contenedores. De entre los numerosos algoritmos que vienen con la biblioteca, y que el lector puede escudriar en el completo manual, podemos mencionar:

Algoritmo for_each find adjacent_find find_if count count_if search binary_search fill fill_n min min_element max max_element sort partial_sort set_difference set_intersection set_union merge +++

Descripcin aplica una funcin a cada uno de los objetos en un rango dado localiza un tem en una secuencia localiza la secuencia consecutiva en un rango dado halla el elemento que satisface un predicado en un rango dado cuenta las ocurrencias de un valor en un rango determinado cuenta los elementos que satisfacen un predicado en un rango dado encuentra una secuencia contenida en otra localiza un elemento perteneciente a una secuencia ordenada rellena un determinado rango con un valor rellena los n primeros elementos con un valor dado devuelve el minimo de dos elementos devuelve el minimo elemento dentro de un rango devuelve el maximo de dos elementos devuelve el mximo elemento dentro de un rango ordena los elementos en un rango dado ordena los elementos de un rango hasta el trmino n-simo genera un conjunto con la diferencia de las colecciones A y B (A-B) genera un conjunto con los elementos comunes a dos secuencias genera un conjunto con los elementos pertenecientes a AUB integra dos listas ordenadas en una nica lista ordenada +++

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 56

Pero veamos un ejemplo de un algoritmo eminentemente prctico: for_each, que con signatura
template<class InputIterator, class Function> Function for_each { InputIterator primero_, InputIterator ultimo_, Function funcion_ }

tiene como propsito aplicar a cada elemento comprendido en el rango [primero_, ultimo_) la funcin determinada por funcion_:
vector<Politico> listaNegra; void detecta( const Politico& politico ) { if ( politico.piensa() ) listNegra.pushBack( politico ); } list<Politico> lista; // se rellena convenientemente la lista for_each( ++lista.begin(), lista.end(), detecta );

Qu es lo que aqu sucede? El algoritmo for_each aplica a cada elemento de la lista (a partir del segundo) la funcin detecta, que toma como argumento el elemento visitado en cada caso, y esta funcin discrimina a los polticos con ideas, que son insertados en una lista negra para un rpido direccionamiento al ostracismo. Pero en el ejemplo vemos tambin que una funcin se trata como un objeto. Y es exactamente eso. FUNCIONES-OBJETO U OBJETOS-FUNCIONES? Muchos de los algoritmos usan de funciones que son aplicadas a los elementos de los contenedores por medio de iteradores. Tales funciones pueden ser bien punteros a funciones normales de C/C++ o una generalizacin de stas: funciones encapsuladas en objetos. Los objetos-funciones son instancias de clases con un comportamiento definido por sus funciones miembros pblicas, pero cuya sintaxis simula la de las funciones C mediante la sobrecarga del operador (); pero adems los objetos-funciones incorporan datos miembros y operan como el resto de los objetos: se crean, se modifican y se destruyen. En general los objetosfunciones, o simplemente funciones respecto de la STL, pueden dividirse en unarios o binarios, dependiendo si toman uno o dos argumentos, pero tambin, en funcin de su propsito, en

Predicados Comparadores

devuelven un valor booleano, y se usan como condiciones de disparo devuelven un valor booleano, y se usan para ordenar elementos

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 57

Funciones les

Genera- sin funcionalidad predefinida, se aplican sobre elementos de contenedores

Pero veamos un ejemplo de cada uno, empezando por los predicados. Si consideramos el algoritmo find_if con prototipo:
template<class InputIterator, class Predicate> InputIterator find_if ( InputIterator primero_, InputIterator ultimo_, Predicate predicado_ )

que devuelve un iterador apuntando al primer elemento del contenedor que cumple el predicado (esto es, la funcin de tipo Predicate aplicada a ese elemento devuelve true):
bool traeMalaSuerte( int numero ) { return numero == 13; } vector<int> numeros; numeros.push_back( 4 ); numeros.push_back( 13 ); numeros.push_back( 13 ); vector<int>::iterator i; i = find_if( numeros.begin(), numeros.end(), traeMalaSuerte ); // i apunta al segundo elemento del vector

Veamos seguidamente cmo operan los comparadores. Si consideramos el algoritmo min con prototipo:
template<class T> const T& min( const T& a_, const T& b_, Compare comparador_ );

cuya funcionalidad es la de comparar los elementos a_ y b_ usando la funcin determinada por comparador_, devolviendo el menor elemento:
bool comparaPoliticos(const Politico& uno, const Politico& otro) { return ( uno.votos() < otro.votos() ); } Politico julio, jordi; // y se inicializan debidamente despus cout << min( jordi, julio, comparaPoliticos ) << \nl;

Por ltimo examinemos las funciones generales, para lo que trataremos con el algoritmo count_if con prototipo:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 58

template<class InputIterator, class Predicate, class Size> void count_if ( InputIterator primero_, InputIterator ultimo_, Predicate predicado_, Size& n_ );

y que procura el nmero de ocurrencias del cumplimiento de un determinado predicado respecto de cada uno de los elementos de un contenedor. Como predicado usaremos el objeto-funcin logical_not, que devuelve true si el argumento que se le pasa es cero, definido as en la STL:
template<class T> struct logical_not : unary_function<T, bool> { // ... bool operator()( const T& x_ ) const { return !x_; } };

y que encaja perfectamente en el ejemplo siguiente:


vector numeros[ 8 ] = { 0, 1, 0, 0, 1, 1, 1, 1 }; int n = 0; count_if( numeros, numeros + 2, logical_not<int>(), n ); cout << n; // imprime 2

Como vemos los objetos-funciones necesitan ser parametrizados y esta operacin puede ser prolija: para facilitar esta labor aparecen los adaptadores de funciones. As, por ejemplo, los negadores not1 y not2 toman como argumento predicados unarios y binarios y devuelven sus complementos. Pero no abundaremos ms en adaptadores, cuyo estudio se deja al vido lector. DE LOS PELIGROS DE LA EXTENSIBILIDAD Examinemos, por ejemplo, el algoritmo count(), que cuenta el nmero de tems en un contenedor que satisfagan un determinado valor. Su prototipo es:
template<class InputIterator, class T, class Size> void count { InputIterator first_, // iterador en el primer tem InputIterator last_, // iterador tras el ltimo tem const T& value_, // el valor a comparar

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 59

Size& n_ cia }

// el contador a incrementar por cada ocurren-

O sea, este algoritmo recorre una coleccion o contenedor desde el primer elemento hasta pasado el ltimo, y compara cada tem encontrado con value aplicando el operador ==. Si la comparacin devuelve true entonces se sumar uno a n. Pero el lector, siempre atento, notar que el algoritmo no inicializa n a cero, y ni siquiera devuelve el nmero de ocurrencias, que parece lo ms intuitivo, sino void. Pero tal es natural, pues la reusabilidad de un algoritmo se sustenta en no fijar presunciones que lesionen su genericidad: de esta manera podemos pasar por referencia a count() una variable con un valor anterior para que sea modificada con las ocurrencias buscadas (caso que se da, por ejemplo, en la concatenacin de dos o ms bsquedas sobre la misma o distinta coleccin). Se deja, as, al usuario de la STL que especifique expresamente su intencin:
// definimos un array (arreglo?!) de ocho elementos int vector[] = { 1, 2, 2, 3, 3, 3, 2, 2 }; int contador = 0; count( vector, vector + 8, 2, contador ); cout << contador; // devuelve 4 (ocurrencias del 2) count( vector, vector + 8, 1, contador ); cout << contador; // 5 (ocurrencias del 2 del 1)

Bien, bien -reconoce aqu el lector-: de acuerdo con la genericidad pero y si yo quiero algo ms sencillo? O sea, No resulta peligrosamente tendente al error tanta genericidad? Por otra parte, si ya conocemos el contenedor sobre el que se aplica el algoritmo, por qu repetirlo en los dos primeros argumentos? Y si se me olvida inicializar el contador? No sera ms adecuada una versin simplificada de tales algoritmos, quizs por derivacin de clases? Bueno, el lector ha puesto el dedo en la llaga, como siempre. Pero es la llaga correcta? Hay que pensar que esto mismo le achacaban los pascalistas al C: Demasiada libertad es peligrosa (cualquier remembranza poltica es deliberada). Veamos los peligros de dejar demasiada responsabilidad en manos del usuario:
vector<Politico> listaMunicipal; vector<Politico> listaAutonomica; // seguidamente se llenan los vectores con criterios // que escapan a los propositos de este captulo y por // lo comn a la lgica y la prudencia. Politico discolo; // se inicializa debidamente del objeto dscolo (o sea, // se ponen algunas ideas en l). int contador; // oops! No se ha inicializado. // seguidamente querremos contar cuntos polticos // dscolos hay en una determinada lista. count( listaMunicipal.begin(),

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 60

// seguidamente se cambia de vector (Horror!) listaAutonomica.end(), discolo, contador ); // error: sin inicializar // El resultado? Impredecible!

Visto lo anterior parece que para la mayora de los casos un algoritmo como el siguiente sera mucho ms legible y seguro:
int politicosDiscolos = listaMunicipal.count( discolo );

a lo que se podra llegar derivando de la clase vector en la STL una nueva clase que incorporara como funcin miembro una funcin count() que, a su vez, usara del algoritmo count(). Algo as como:
template<class T> class vectorEspacial : public vector<T> { public: int count( const T& valor_ ) const { int n = 0; count( begin(), end(), valor_, n ); return n; } // sigue resto protocolo clase };

De esta manera las listas anteriores deberan ser instanciadas como objetos de nuestro vector personalizado:
vectorEspecial<Politico> listaMunicipal; vectorEspecial<Politico> listaAutonomica;

Y ahora s se podra utilizar la funcin miembro, como antes se ha visto. De hecho este es el enfoque que han adoptado la mayora de implementaciones comerciales de la STL, con el objetivo de facilitar el uso de la biblioteca a los usuarios. Pero este enfoque tiene muchos puntos negros. Vemoslos: Para cada algoritmo deber aadirse una funcin miembro a nuestra clase. As, y aparte de la duplicacin de clases que la derivacin supone (para cada clase en la STL habr de crearse una nueva clase derivada con funciones miembros reflejando cada algoritmo), dada la naturaleza de la STL, que invita a aadir nuevos algoritmos, el interfaz de las clases derivadas debera ser cambiado con relativa frecuencia. La eficacia inherente a la STL se ve perjudicada por la introduccin de jerarquas de herencia y destructores virtuales.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 61

La facilidad por derivacin enfatiza el uso de clases no-normalizadas, de manera que el cdigo generado no se acoje a normas de estandarizacin y por tanto plantea problemas para su extensin y acoplamiento a distintos entornos. Un enfoque sustancialmente distinto es el que adopta STL<ToolKit>, de ObjectSpace Inc. Para facilitar el uso de los algoritmos de la STL, ObjectSpace ha aadido unos cuantos llamados algoritmos de ayuda, que anteceden a los identificadores estndar de la STL con el prefijo os_, de forma que as se podra codificar:
vector<Politico> listaMunicipal; // vector estndar STL int PoliticosDiscolos = os_count( listaMunicipal, discolo );

donde os_count sera codificada como:


template< class Contenedor, class T > inline int os_count( const Contenedor& c, const T& valor ) { int n = 0; count( c.begin(), c.end(), valor, n ); return n; }

Personalmente me parece una solucin que, adems de respetar el espritu de la STL, resulta tan eficiente como la original (por su implementacin inline), pero ms fcil de usar para la mayora de situaciones, aparte de no incurrir en ninguna de las anteriores desventajas (el mismo algoritmo de ayuda funciona, por ejemplo, para todos los contenedores de la STL). LEVES CRTICAS Si la STL es tan endiabladamente buena, qu impide su adopcin generalizada? Nada! Bueno, s, quizs una cierta candidez cultural, semejante a la de aquellos ciudadanos que no comen marisco en pblico por temor -mayormente fundado- a no saber manejarse con los cubiertos. En realidad la propia sintaxis del lenguaje es mucho ms prolija y compleja que la estructuracin en que se basa la STL, de forma que cualquiera que use C++ debiera usar STL o, ms an, la Biblioteca Estndar del lenguaje que incluye, en ella diluida y sin forma explcita, a la STL. Ah, pero biblioteca no es bibliotenaje! Esto es, como titulara Pitigrilli, El pollo no se come con la mano: hay que estudiar y entender la STL antes de usarla, as como apreciar los leves inconvenientes derivados de su uso, que en la actualidad se reducen a dos: la dificultad de depuracin del cdigo errneo (debida no tanto a la estructura de la biblioteca como a sus actuales implementaciones) y el aumento del tamao de los ejecutables (que Cargill cifra en un 25%). Hay que afinar la balanza, seores, pero sinceramente no creo que tales dificultades afecten al grueso de los programadores en C++.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 62

APRENDIZAJE Y DOCUMENTACIN La implementacin de STL de Hewlett Packard, que con una decisin encomiable liber todas las licencias afectas a la biblioteca convirtiendo la STL y el trabajo de muchos aos en freeware puede ser conseguida, junto con el manual de Stepanov y Lee en postscript, mediante ftp annimo bien en ftp://butler.hpl.hp.com/stl/ bien en ftp://ftp.cs.rpi.edu/pub/stl/, pero tambin en distintos foros electrnicos (como el de Microsoft Spain en CI$). En el World-Wide Web habra que echarle un vistazo a la pgina (home page) que mantiene David R. Musser, del Instituto Politcnico Rensselaer, en http://www.cs.rpi.edu/~musser/stl, con documentacin on-line y varios enlaces. En general los enlaces de OOA/D/P pueden ser accedidos a travs de La Pgina Orientada-a-Objetos (The Object-Oriented Page: The OOPage) que yo mismo edito para Galaxy en el Web14 (http://galaxy.einet.net/galaxy/Engineering-andTechnology/Computer-Technology/Object-Oriented-Systems/ricardo-devis/oo.html), o tambin a travs de mis propias pginas personales en The Well (http://www.well.com/user/ritchie). En cuanto al aprendizaje y uso, en repetidas ocasiones he mencionado el manual que acompaa a la STL. Naturalmente este manual es perfecto si la perfeccin estilstica se entiende a la manera de Borges: esto es, eliminando adjetivos en un proceso iterativo que genera un documento denso y completo, pero que hay que releer varias veces, y donde lo esencial ni siquiera se separa de lo accesorio, en aras de la completitud formal, claro. Bien: el manual de Stepanov y Lee es perfecto (perfectamente tcnico) y un cierto ejemplo sobre cmo debe componerse una buena documentacin. Sin embargo, para iniciarse en la STL (o para el gran pblico, que dicen los legalistas de C++) quizs sea mejor atender a otros textos (y es que Voltaire acu una frase omnipresente en informtica). Pero, qu textos? Pues los de las implementaciones comerciales de la STL, que son bastante buenos. Un momento, un momento! Implementaciones comerciales? Pues claro! La STL hace un uso extensivo e intensivo de las plantillas y, por ende, carece de un soporte pre-construido que cubra la mayora de los compiladores del mercado, caractersticas que proporcionan los vendedores de STL, que adems incorporan diversas golosinas, ciertamente prcticas, que aumentan la facilidad y funcionalidad de la STL. Las implementaciones comerciales actuales arrostran un precio usualmente no superior a los $300,00 y bsicamente (existen algunas ms) se deben a Modena Software Inc. (Stl++), con soporte para tablas hash, y ObjectSpace Inc.

14

Ah, lo siento! Para m es el Web y no la Web. Y es que pese a la traduccin de Telaraa a lo ancho del mundo (que a m me resuena a un cierto Capitn Tan), los barbarismos WWW, World-Wide Web, Web W3 me resultan terminantemente masculinos. Claro que una solucin polticamente correcta sera la de el/la Web, tan comn hoy en da en los textos norteamericanos. Pero, vaya, tras leer la versin polticamente correcta de Los Tres Cerditos creo que me batira en duelo por reivindicar el sano derecho a la incorrectitud individual.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 63

(Stl<ToolKit>), con soporte para la mayora de los compiladores C++ actuales, aunque Rogue Wave ha anunciado tambin la inclusin de la STL en su conocida biblioteca de clases Tools.h++. Restringindonos a los dos primeras, ambas con buenos manuales y varios aadidos, yo recomendara la segunda: STL<ToolKit>, que provee un manual de 421 pginas perfectamente pedaggico, con ms de 250 ejemplos de uso y una distribucin de la informacin sencillamente perfecta (tanto es as que parece que en breve se publicar el manual como libro en Prentice Hall). Adems ObjectSpace, accesible en el Web por http://www.objectspace.com provee extensiones multi-thread, multitud de algoritmos de ayuda y soporte para asignadores dinmicos de memoria. REFERENCIAS DIRECTAS Cargill, T. STL Caveats, C++ REPORT, 7(6), julio-agosto 1995. Barreiro, J.-Fraley R. & Musser D.R. Hash Tables for the Standard Template Library, X3J16/94-0218, WG21/N0605, enero 95. Koenig, A. The ideas behind STL, X3J16/94-0134, WG21/N0521, 1994. Musser D.R. The Standard Template Library Home Page, WWW 26/07/95. ObjectSpace Inc. STL<ToolKit> User Guide, mayo 1995. Stepanov, A. & Lee, M. The Standard Template Library, X3J16/94-0140, WG21/N0527, julio 1994. Stroustrup, B. Making a vector fit for a standard, C++ REPORT, 6(8), octubre 1994. Vilot, M. An Introduction to the Standard Template Library, C++ REPORT, 6(8), octubre 1994.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 64

4
MANEJO DE EXCEPCIONES EN C++
xcepciones? Es que no basta con las reglas15? Oh, difcilmente las construcciones humanas pueden tratar con la inflexible y perfecta exactitud reglada! Ya deca Goethe que apenas hablamos, empezamos ya a equivocarnos. Y si la vida est repleta de errores, equvocos e imponderables, imagnense el software, pobre y desdibujado reflejo de aqulla. As que para manejarnos con cierta soltura debemos reglar tambin lo que no cabe en la propia norma, estableciendo ciertas estructuras de control que nos permitan, cuando menos, construir una somera malla en que las excepciones queden atrapadas: lo excepcional se convierte as en previsible, en alguna medida. Esta es la ventaja, claro. Pero desafortunadamente el diseo e implementacin de un sistema de captacin y manejo de excepciones posee tambin sus reglas, sutilezas y desventajas. Si encima aadimos a stas la prolijidad y los problemas usualmente achacados al lenguaje C++, bueno, el asunto adquiere tintes inopinadamente malignos. Pero quiz el tratamiento de excepciones constituya una excepcin respecto del comportamiento usual de C++: la sintaxis es relativamente sencilla, pero su aplicacin en sistemas software reales requiere de una estrategia previa cuidadosamente medida (y ms vale que el lector me crea a pies juntillas). Entre ambos extremos se sitan, empero, los aspectos semnticos de uso de las caractersticas del lenguaje asociadas al manejo de excepciones y que son de los que este captulo se ocupar.

LOS CDIGOS DE ERROR La mayora de las estrategias de control de excepciones/errores/imprevistos se basan en que todo procedimiento/funcin/mensaje debe devolver a su usuario, considerado en un sentido amplio, un valor indicativo de su exito o fracaso. As, por ejemplo, es comn encontrar cdigo como el siguiente:
int adiciona( Plantilla& plantilla, const Empleado& empleado )

15

Quien piense que el proverbio latino Exceptio probat regulam significa la excepcin confirma la regla debera repasar su latn.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 65

{ if plantilla.incluye( empleado ) return -21545; //absurdo cdigo de error else { plantilla.adiciona( empleado ); return 1; } }

de manera que pueda hacerse el siguiente uso de la funcin:


if ( !adiciona( plantilla, fernandez ) ) muestraDialogoError( Empleado ya existe );

Naturalmente lo que aqu se plantea resulta relativamente simple cuando se trata de funciones que debieran devolver void. Cuando no es as las cosas se complican:
Politico& PartidoPolitico::politicoHonrado() { // devuelve un poltico honrado del partido // El problema es que si tal poltico no existe // qu se devuelve? }

Una posible solucin pasara por reconvertir la funcin en otra que devuelva un codigo de error:
int PartidoPolitico::politicoHonrado( Politico* politico ) { // si existe, asigna el politico encontrado al // puntero que se le pasa, y devuelve 1 // si no existe devuelve 0 algn valor negativo }

de tal manera que el cdigo cliente deber siempre comprobar el valor de retorno antes de operar con el posible Politico encontrado, pues si realmente no se encuentra (el caso ms frecuente) tal puntero apuntar ... a qu?. Humm, esta solucin, aparte de no ser especialmente elegante y resultar intrusiva 16, ni siquiera puede aplicarse en todas las situaciones: pensemos, por ejemplo, en los constructores, que no pueden devolver cdigo alguno.

16

Cuando se quiere recomponer artificialmente cdigo muerto, el producto final tiene bastantes posibilidades de acabar como el monstruo de Victor Frankentein: bien en la hoguera bien como leitmotiv de pelculas absolutamente infames.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 66

D situaciones y, por tanto, no debe constituirse en estrategia genrica de manejo de excepciones.


La devolucin de cdigos de error por funciones no puede aplicarse en muchas

La clara alternativa sera construir/devolver un objeto con un cierto estado interno relativamente estable y que, a la vez, indicara la inestabilidad del mismo: o sea, un objecto zombi:
class Persona { long dni; public: Persona::Persona( if ( unDNI < 0 ) { dni = 0; return; } // cdigo consructor persona } int comprueba() { return dni; } // sigue resto descripcin de clase };

Pero esto arrostra nuevos problemas: ahora obligaremos bien a los clientes de la clase a validar cada objeto antes de usarlo:
if ( fulano.comprueba() ) cout << fulano;

bien a incluir cdigo de comprobacin en cada funcin miembro de la clase Persona, que a su vez deberan devolver, as, ciertos cdigos de error.

Los objetos zombis generan una ingente cantidad de cdigo cliente de comprobacin y bifurcacin usualmente dependiente de unas especificaciones voltiles. La aplicacin indiscriminada de este enfoque ocasiona sistemas software de dudosa mantenibilidad.

Adivina ahora el lector por qu las estrategias usuales de error suelen resultar tan artificiosas, frgiles y dficiles de mantener? Basta con echarle un vistazo a los manuales corporativos de referencia de cdigos de error: una barbaridad tal que al final proporciona ciertos gusto y adiccin malsanos17. Naturalmente no se afir17

Des Esseintes, el sofisticado protagonista del rebours de Huysmans, gustaba de coleccionar orquideas naturales que parecieran absolutamente artificiales: las corporaciones intentan alcanzar el aberrante nivel opuesto asimilando a cada error un cdigo que resulte humanamente intuitivo (Diantre! La psicologa industrial se ha desquiciado!).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 67

ma aqu que los cdigos de error resulten dainos per se, pues de alguna manera (con algn cdigo) ha de comunicarse la parte que genera un error con la parte que la maneja. Pero el cmo es fundamental. CONCEPTOS BSICOS Como solucin a estas cuitas, lo que C++ provee son tres nuevas construcciones explicitadas en tres nuevas palabras reservadas: la expresin throw18, que lanza excepciones. el bloque catch, que define manejadores de excepciones. el bloque try, que indica las secciones de cdigo que son sensitivas respecto de las excepciones. y su funcionamiento, en breve, es el siguiente: en cualquier seccin del cdigo puede lanzarse, mediante throw, una excepcin, pero tal excepcin slo ser procesada si tal seccin est incluida, directa o indirectamente, en un bloque try, y de tal proceso se encargarn los manejadores definidos por catch y afectos al bloque try en que se incluya la excepcin lanzada. La expresin throw puede aparecer en cualquier parte del cdigo de la siguiente guisa:
throw throw throw throw 5; // lanza Persona(); // lanza Racional( 1,2 ); // Error de suma; // el objeto 5 (de tipo int) un objeto por defecto de tipo Persona lanza el objeto Racional lanza un objeto de tipo char*

mientras que el bloque catch ha de ir forzosamente antecedido por un bloque try, de la misma manera que un else ha de ir precedido de un if. Pero tras un try (inmediatamente despus) pueden asociarse varios bloques catch. El bloque try no posee argumentos, pues su propsito es indicar sobre qu porcin de cdigo (la encerrada entre las llaves del try) se aplicarn los manejadores catch que le siguen. Los manejadores catch, sin embargo, s poseen argumentos: desde la elipsis (...) hasta cualquier tipo definido-por-el-usuario:
try { // una porcin de cdigo cualquiera }

18

Como seala Stroustrup, raise o signal hubieran sido palabras ms apropiadas, pero stas ya existan en la biblioteca estndar de C.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 68

catch ( int entero ) { // inmediatamente despus del bloque try cout << Cdigo de error: << entero; } catch ( Persona ) { // en este catch slo importa el tipo de error // y no el objeto concreto lanzado por throw relanzaProcesoDePersona(); } catch ( Racional& racional ) { racional += 1; cout << racional; } catch ( const char* mensaje ) { VentanaDeMensaje( mensaje ); }

El manejo de excepciones en C++ es, en esencia, un mecanismo que permite la comunicacin entre dos partes distintas de una aplicacin (y esto provoca no pocas crticas, al estar tales partes usualmente bien distantes y supuestamente romper, as, uno de los principios establecidos por Meyer: evitar la propagacin de errores en tiempo de ejecucin). En realidad hay una cierta similitud entre tal mecanismo y el de llamada y resolucin de funciones: la expresin throw equivaldra a la llamada a la funcin, con un argumento dado, mientras que el bloque catch representara la definicin de la funcin. La diferencia fundamental consiste en que la ligazn de una llamada a una funcin con el cuerpo de sta se produce en tiempo de compilacin, mientras que la resolucin del mecanismo de manejo de excepciones se produce en tiempo de ejecucin. Esto significa que el compilador no sabe qu bloque catch (si acaso alguno) manejar una determinada excepcin. De hecho lo nico que puede hacer el compilador es generar ciertas estructuras que soporten la informacin necesaria para que funcione el mecanismo en tiempo de ejecucin. As cada vez que el compilador encuentra una expresin throw o catch creara un descriptor de tipo para cada una de ellas, permitiendo su comparacin en tiempo de ejecucin. El encaje de ambos descriptores es, en gran medida, igual al encaje de argumentos en funciones: un operando de throw con tipo E casar con un manejador catch con argumento de tipo M, const M, M& o const M& si: E y M son del mismo tipo M es una clase base inambigua de E M y E son punteros y se da una conversin estndar de E a M Resulta, entonces, que si se lanza la siguiente excepcin, significada por un objeto que se construye para la ocasin:
throw Mensaje( Thats all folks );

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 69

la expresin throw inicializara un objeto temporal del tipo esttico del operando (ste es, Mensaje), y tal objeto se usara a su vez para inicializar, de la misma manera que un argumento en la llamada a una funcin, la variable establecida como operando del catch adecuado. Vamos, que el mecanismo semeja el de una expresin return. En tal sentido debe tenerse en cuenta que el paso por valor significa el uso del constructor de copia, y que a pesar que la memoria para el objeto temporal se asigna de una forma dependiente de la implementacin, el destructor del objeto deber ser finalmente usado, de manera que tal funcionalidad mnima tendr que ser prevista en la clase.
en C cer a clasesen laque el constructor de copia y el destructor sean accesibles (estn declarados seccin pblica). Los objetos que se utilicen como operandos de expresiones throw deben pertene-

Cuando se entra en un manejador catch que toma como operando un objeto (no una referencia a un objeto) de una clase dada, se produce una copia del objeto lanzado por la expresin throw correspondiente, que se destruye cuando se sale del mbito del manejador. Si el catch espera un objeto no-constante, los posibles cambios realizados en la copia del objeto dentro del manejador sern locales a dicha copia y, por tanto, se perdern a la salida del catch. MANOS A LA OBRA Seguidamente vamos a detallar un ejemplo elemental en el que se han sealado las lneas de inters con nmeros para permitir su rpida localizacin en la densa explicacin que sigue al cdigo:
class MensajeDeSocorro { public: MensajeDeSocorro( char* cadena ); char* cadena() const; // resto descripcin clase }; void Programador::codifica() { desactivaSalvaPantallas(); escribe(); escribe(); escribe(); modifica(); piensa(); throw MensajeDeSocorro( // (1) } extern Programador* programador;

Qu

haba

que

hacer?

);

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 70

void Analista::analiza() { try { // (2) desactivaSalvaPantallas(); escribe(); escribe(); escribe(); discute(); piensa(); programador->codifica(); throw Qu haba que hacer?; // (3) } catch ( char* ) { // (4) VentanaModalDeAviso( Cambiar de analista ); } } extern Analista* analista; void empiezaProyecto() { try { // (5) analista->analiza(); } catch( ... ) { // (6) throw; } catch( MensajeDeSocorro mensaje ) { // (7) cout << Esta lnea es inalcanzable; } } void ejecutaProyecto() //nunca mejor dicho { try { // (8) empiezaProyecto(); terminaProyecto(); } catch (MensajeDeSocorro mensaje ) { // (9) cout << mensaje.cadena(); } }

Empecemos con la ltima funcin ejecutaProyecto(): en primer lugar se llama a la funcin empiezaProyecto(), que a su vez llama a la funcin Analista::analiza(), que llama a la funcin Programador::codifica() que genera una excepcin del tipo MensajeDeSocorro lanzando un objeto de tal clase construido con un argumento de tipo String (lnea 1). Bien. Ahora slo hay que ver cmo se maneja esta excepcin. Obviando otras consideraciones, lo primero que se hace es mirar si la excepcin est contenida directamente en un bloque try. Como no es as, se busca en el

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 71

mbito en que se llama a la funcin Programador::codifica(), dentro de la funcin Programador::analiza(), que s est incluida en un bloque try (lnea 2). Seguidamente miramos si el bloque try tiene uno o ms bloques catch asociados. Y as es: en la lnea 4 se da un catch que admite objetos del tipo char*. Pero el objeto que se lanz en el throw era de tipo MensajeDeSocorro, por lo que este catch no es de aplicacin. As que se busca un nuevo bloque try exterior, que se encuentra en la lnea 5 y que tiene asociados dos bloques catch en las lneas 6 y 7. En seguida se comienza la comparacin del tipo lanzado con el que espera cada uno de los bloques catch, examinados en estricto orden de aparicin. As tenemos que el primero (lnea 6) admite cualquier tipo de argumento (...), por lo que casa perfectamente con el tipo MensajeDeSocorro que se lanz en el throw inicial. Pasa inmediatamente a ejecutarse el catch(...), y en ese mismo momento la excepcin se entiende manejada (exactamente as, querido lector). Lo que sigue es una instruccin throw sin ms que, simplemente, relanza la misma excepcin que haba captado, significada en el mismo objeto de tipo MensajeDeSocorro: o sea, es como si se repitiera la lnea 1, pero en esta nueva posicin:

Una expresin throw sin operando relanza la excepcin que en ese momento se estaba manejando sin copiarla. Si no se est manejando ninguna excepcin se genera una llamada a terminate().

Claro que ahora el lector despistado podra pensar: Bueno, perfecto. El segundo catch de la lnea 7, que espera un objeto de tipo MensajeDeSocorro manejar perfectamente la excepcin relanzada. En absoluto! Hay que pensar que las conjunciones try-catch se asemejan sobremanera en su comportamiento a las conjunciones switch-case (suponiendo un break al final de cada case): para cada try se ejecuta, a lo sumo, solo uno de los catch asociados. Es fcil ver, as, que como el catch de la lnea 6 capta cualquier excepcin de cualquier tipo, el catch de la lnea 7 no ser alcanzado por ninguna excepcin en ningn caso, y de hecho un buen compilador emitira el siguiente error (s caro lector: error, no aviso):
error EDC3194: "catch(MensajeDeSocorro)" will never be reached because of previous "catch(...)".

C entre los manejadores.

Si siguiendo a un bloque try se da un catch(...), ste debe ocupar el ltimo lugar

Pero volvamos al flujo de nuestra excepcin. Como ya se ha ejecutado el catch(...) al relanzar la excepcin se vuelve a buscar un bloque try en un mbito exterior, que se encuentra en la lnea 8, dentro de la funcin ejecutaProyecto(). Este try tiene asociado un solo catch (lnea 9) que admite el tipo MensajeDeSocorro, y por tanto casa con el tipo de nuestra excepcin, por lo que tal catch la manejar. Y como en este bloque catch se explicita un identificador para el objeto (que no apareca en el catch de la lnea 7), puede usarse tal objeto en su interior: en este

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 72

caso para llamar a una funcin miembro, cadena(), que devuelve la cadena de caracteres de su representacin interna (sta es, Qu haba que hacer?). Recapacite el lector que este ltimo catch (lnea 9) admite un objeto (no una referencia) de forma que, como ya se not en el pargrafo anterior, si se produjera algn cambio en el mismo, ste se perdera al salir del mbito del manejador. Hay que fomentar aqu, tambin, las mismas consideraciones de eficiencia que aconsejan el uso de referencias a objetos como argumentos de funciones. Incidentalmente el lector habr tambin notado que la lnea 3, en que est codificado directamente el lanzamiento de una excepcin asociada a la funcin Analista::analiza(), nunca ser alcanzada, pues la excepcin lanzada con anterioridad por la funcin Programador::codifica() modifica el flujo secuencial del programa, como es fcil suponer y ms adelante veremos. De esta manera el software imita al mundo real: el error del programador impide que el del analista resulte visible. CLASES DE EXCEPCIONES El lector habr apreciado que en el ejemplo anterior se lanzan tanto objetos de tipo predefinido como objetos de clases definidas-por-el-usuario. Lo que el lector habr tambin asimilado a estas alturas es que las clases de excepciones se corresponden con las clases (por tipos) de los objetos lanzados como excepciones. Resulta, as, que en una estrategia de manejo de excepciones en C++ es imprescindible la creacin de un cmulo de clases adecuadas para tratar cada error. Naturalmente podemos crear clases independientes para cada excepcin, pero por qu no usar del mecanismo de la herencia que provee C++ y construir una jerarqua de clases de error? Una de las principales ventajas (discutidas, no obstante, por ciertos autores y organizaciones) de este enfoque es el tratamiento uniforme que se dara a la especificacin de excepciones, que examinaremos en breve. Pero no adelantemos acontecimientos y fimonos ahora simplemente de las supuestas bondades universales de la derivacin como mecanismo buenopara-casi-todo. JERARQUAS DE CLASES DE EXCEPCIONES Si construimos una jerarqua de clases representativas de excepciones/errores, parece prudente que la clase base (TStandardException, por ejemplo, en el caso del Taligent Application Environment) contenga una mnima funcionalidad (o ninguna, si se piensa que el estndar del lenguaje puede llegar a reglar este extremo) ms un destructor virtual (imprescindible en las jerarquas de derivacin, como el lector ya debera saber). De cualquier forma y en aras de la pedagoga examinaremos un ejemplo ms simple:
class Error { /* clase base */ };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 73

class ErrorBaseDeDatos : public Error { /*...*/ }; class ErrorDeActualizacion : public ErrorBaseDeDatos { /*...*/ }; void actualizaClientes() { throw ErrorDeActualizacion(); } try { actualizaClientes(); } catch ( ErrorDeActualizacion ) { /*...*/ } // (12) catch ( Error ) { /*...*/ } // (13) catch ( ErrorBaseDeDatos ) { /*...*/ } // (14)

// (10)

// (11)

Como vimos anteriormente, la excepcin lanzada en la lnea 10 salta hasta el bloque try de la lnea 11 y seguidamente pasa a comprobar sus manejadores asociados. Como stos se examinan en estricto orden de aparicin, es fcil ver que el primero de ellos (lnea 12) es del mismo tipo que la excepcin lanzada, y por tanto casa perfectamente con ella. Las cosas cambiaran, sin embargo, si la excepcin lanzada fuera
void actualizaClientes() { throw ErrorBaseDeDatos(); }

pues al empezar la comparacin de descriptores de tipo con los de los bloques catch encontrara que el de la lnea 12 no casa, pero s lo hace el siguiente de la lnea 13, ya que el operando de la expresin throw es un objeto de una clase derivada pblicamente de Error. De aqu se sigue, como el lector ya se est apresurando a proclamar, que la lnea 14 no ser alcanzada en ningn caso.
catch con argumento de clases derivadas debern C en jerarqua, los bloquescatch que manejen excepciones de sus clases base siempre anteceder a los respectivas.. Si en un conjunto de bloques catch tras un bloque try se manejan tipos de datos

EL DESBOBINADO19 DE LA PILA Cuando se lanza una excepcin el programa salta hacia un nivel superior donde el error podr ser procesado20 o, lo que es lo mismo, se transfiere el control de la

19

Bueno, desbobinado no existe en castellano, pero rebobinado, el vocablo ms ajustado, representa la accin de desbobinar para bobinar en otro carrete (un tipo de pila, al fin y al cabo). Por si el lector abriga alguna duda, desempilar o desapilar tampoco existen. 20 No les viene a la cabeza una poca piadosa semblanza con la actitud de algunos ante la supuesta vida eterna? Yerra, yerra y sufre, que de todo se ocupar un nivel superior! Ah, pero, y

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 74

ejecucin del programa al primer bloque try que lo encierre. Normalmente los objetos en la pila (stack) se destruyen cuando finaliza el mbito en que fueron declarados, pero al realizar el salto quedaran objetos abandonados entre el lanzamiento y el manejador. Para evitar esto se invocan los destructores de todos los objetos automticos construidos hasta que se encuentra el bloque try, y este proceso de denomina desbobinado de la pila (stack unwinding). Pero pongamos las cosas ms difciles: imaginemos que se genera una excepcin en el bloque de inicializacin de un constructor, de tal forma que algunos de los objetos que debera inicializar quedan sin construir. El desbobinado de la pila, a resultas de tal excepcin, llamar solamente a los destructores de los objetos totalmente construidos. CONSISTENCIA DE ESTADOS Stroustrup relata con detalle las dudas que surgieron en el proceso de diseo del mecanismo de manejo de excepciones en C++ respecto de s deba ser continuativo o conclusivo: o sea, si tal mecanismo deba constituirse en una bifucarcin que, tras ser tratada, pudiera devolver el flujo del programa a donde se lanz la excepcin o bien debera adoptarse el actual enfoque. La decisin final es actualmente evidente. Las razones fueron, en esencia, que el mecanismo continuativo representaba graves complejidades como estrategia y, sin embargo, resultaba fcilmente codificable tomando como base el enfoque conclusivo. Es relativamente usual, por ejemplo, que una funcin miembro necesite completar una serie de acciones para mantener la consistencia del estado interno del objeto a que se aplica. Echemos, si no, un vistazo a la siguiente funcin:
void Politico::adjudicaContrato( long soborno ) { recibeDinero( soborno ); cometeTurbiosManejos(); emiteDictamenFavorable(); }

El problema es que si en la funcion cometeTurbiosManejos() se genera una excepcin, entonces no se alcanzar nunca la funcin emiteDictamenFavorable() y el poltico, sin embargo, se habr embolsado el dinero del soborno. Pero esto, aunque refleja fielmente la realidad, no parece convenir comercialmente. Cmo solucionar, pues, este claro problema de contraprestaciones?
void PoliticoHonrado::adjudicaContrato(

vivir? Esta es, naturalmente, una de las razones por las que el hombre mata a Dios (pero su sombra es larga, que deca Nietzsche).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 75

Adjudicatario& X, long soborno ) { recibeDinero( soborno ); try { cometeTurbiosManejos(); } catch(...) { devuelveDinero( X, soborno ); throw; // relanza la excepcin } emiteDictamenFavorable(); }

Claro que aqu el lector descontento podra exclamar: Oh, esto es demasiado prolijo. Si tengo que codificar de esta manera todas mis funciones el cdigo final crecer una barbaridad. Y eso sin hablar de los errores tipogrficos que acechan en cada lnea. Bueno, en primer lugar he de reconocer que el lector se expresa muy bien, para despus proclamar que, como ya anunci, el manejo de excepciones en C++ no es tarea simple. ADQUISICIN DE RECURSOS VA INICIALIZACIN Otra cuestin frecuente es la que se refiere a la liberacin de los recursos adquiridos. Veamos un ejemplo de la vida real:
void Politico::cobra() { HombreDePaja* testaferro = new HombreDePaja(); // Aqu se suceden distintas llamadas // a funciones y mtodos (a cul peor) delete testaferro; // se eliminan las pruebas }

El problema es que si entre la creacin del testaferro y su destruccin se genera alguna excepcin, la memoria asignada (primaria o secundaria, si incluimos la persistencia) nunca se liberar. Naturalmente la solucin podra pasar por un esquema similar al del pargrafo anterior, insertando una expresin try-catch entre la creacin y destruccin del objeto, pero una mejor solucin sera crear una clase
class PunteroAHombreDePaja { public: PunteroAHombreDePaja() : testaferro( new HombreDePaja; ) {} ~PunteroAHombreDePaja() { delete testaferro; } HombreDePaja* testaferro; // anatema! };

de tal manera que la funcin se recodificara de la siguiente guisa:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 76

void Politico::cobra() { PunteroAHombreDePaja testaferro; // Transacciones financieras varias }

Si no se produce una excepcin tras la creacin de testaferro, al salir del mbito de la funcin se llamar al destructor del objeto testaferro y al ejecutarse ste se liberar la memoria dinmica asignada. Si se genera una excepcin tras la creacin del objeto, al ponerse en marcha el desbobinado de la pila se llamar tambin al destructor, obteniendo el mismo resultado. Este planteamiento, resultando efectivo, no es, sin embargo, suficientemente satisfactorio: por un lado tenemos que el cdigo original operaba con punteros, y ste lo hace con objetos, de manera que bien habra que cambiar el cdigo (lo que frecuentemente es inaceptable) bien dotar a la clase con una funcin u operador* que devolviese el puntero para as poder operar con l; por otro lado resulta que con un tal esquema habra que crear una clase distinta para cada tipo de dato que se deseara manejar con esta tcnica. La solucin es echar mano de las plantillas:
template <class T > class New { public: New() : t( new T ) {} ~New() { delete t; } New( T* tt ) { t = tt; } operator T*() { return t; } private: T* t; protected: // se declaran no-pblicos el constructor de copia y // el operador de asignacin para evitar problemas New( const New& n ); const New& operator=( const New& n ); };

De manera que ahora podramos escribir:


class HombreDePaja : public PersonaFisica { /* lo que sea */ }; void firma( HombreDePaja* hdp ) { /* ... */ } void Politico::cobra() { New< HombreDePaja > testaferro; // ahora puede usarse testaferro como un puntero

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 77

// a un HombreDePaja, merced al operator*. firma( testaferro ); }

Otra solucin, a falta de un buen recolector de basura para C++, sera usar de Punteros Inteligentes (Smart Pointers) para gestionar el manejo de excepciones. Pero esto se sale del mbito de lo aqu pretendido, as que el lector interesado puede echarle un vistazo al interesante artculo de Steve Churchill. ESPECIFICACIN DE INTERFACES Resulta desafortunadamente usual que un programador, a poco de aprender (oh, dije aprender?) alguna nueva caracterstica de un lenguaje, proceda bien a obviarla bien a aplicarla sin control ni concierto. Imaginen el desbarajuste que puede ocasionar un programador(de los hiperactivos: segundo caso) lanzando excepciones a diestro y siniestro. Ahora magnifiquen el desastre: pinsense usando el cdigo as generado por otra persona. Naturalmente los programas generados, al no tener claro conocimiento de las excepciones lanzadas (pues el cdigo de implementacin de las funciones generalmente no es accesible), no podrn manejarlas prudentemente, as que todo sern abruptas finalizaciones. No habra alguna manera de especificar, de una forma expresa y clara, el tipo de excepciones que una funcin puede lanzar? Pues claro! Para eso est la especificacin de excepciones. La idea es matizadamente simple: en el declarador de una funcin bien en su declaracin bien en su definicin (pero no en ambas, como tampoco en un typedef) puede detallarse la lista de tipos de excepciones que tal funcin puede legalmente lanzar. Veamos unos ejemplos:
void f() throw( int ); int g() throw( Overflow, ErrorDB ); Poltico& encarcelar() throw ( PoliticoHonesto );

Para evitar un cambio impensable en todo el cdigo existente, la no declaracin de una especificacin de excepciones equivale a:
void funcionNormal() throw( ... );

En justa correspondencia, para especificar que una funcin no puede legalmente lanzar ninguna excepcin se escribe:
void funcionSinExcepciones() throw();

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 78

Bueno, esto resulta perfecto: ahora cada uno sabr a qu atenerse cuando maneja funciones ajenas, dotando a su cdigo si es necesario de los manejadores adecuados (y antes de los bloques try) para controlar las posibles excepciones. Perfecto? Humm, seguro que el lector ha notado un cierto retintn en la repeticin del adverbio legalmente. Qu significa aqu est apreciacin jurdica? Pues exactamente lo siguiente: si una funcin con una especificacin de excepciones de ciertos tipos lanza una excepcin no contemplada en la lista, entonces el sistema llamar automticamente a la funcin unexpected(), que por defecto llamar a terminate(), que por defecto, a su vez, llamar a abort(), y el programa acabar abruptamente. Vaya! Funciones nuevas! Echmosles un vistazo. EL FINAL DE LA CUERDA C++ provee dos funciones esenciales para el manejo bsico de excepciones, incluidas en la cabecera <exception> de la biblioteca estndar del lenguaje: void terminate() y void unexpected(). Veamos cada una por separado. La funcin terminate() se llama, en breve, cuando una excepcin no encuentra manejador, cuando se genera una excepcin en el proceso de destruccin de un objeto en el desbobinado de la pila (stack unwinding), o cuando se da algn error interno.

No se debe lanzar una excepcin desde el interior del cuerpo de un destructor, pues si su lanzamiento se produce durante un desbobinado de la pila se ignorar el mecanismo de manejo de errores y se llamar indefectiblemente a terminate().

La funcin terminate() llama a su funcin manejadora asociada de tipo


typedef void (*terminate_handler)();

y cuyo comportamiento por defecto es llamar a la funcin abort(). El manejador asociado a terminate() puede, no obstante, ser cambiado haciendo uso de la funcin
terminate_handler set_terminate( terminate_handler f ) throw();

que admite un puntero no nulo a una funcin (que necesariamente debe terminar sin devolver el control al usuario) y retorna el anterior manejador.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 79

VULNERACIN DE LA ESPECIFICACIN DE EXCEPCIONES Si una funcin con una especificacin de excepciones asociada lanza una excepcin no contemplada en tal lista, se producir una llamada a la funcin void unexpected(), que a su vez llamar a su manejador asociado de tipo
typedef void (*unexpected_handler)();

que por defecto llamar a la funcin terminate(). Tal manejador puede cambiarse, empero,mediante la funcin
unexpected_handler throw(); set_unexpected( unexpected_handler f )

que devuelve el manejador hasta entonces vlido y admite un nuevo puntero no nulo a una funcin que puede lanzar una excepcin ya normal ya de tipo bad_exception, o bien llamar a exit() o abort() Demonios! Otra nueva palabra! Bueno, sufrido lector, no me negar que esta situacin excepcional lo disculpa casi todo: bad_exception es el nombre de una clase derivada pblicamente de exception, perteneciente a la biblioteca estndar del lenguaje, y cuya razn de ser es precisamente evitar el problema sugerido por Taligent y que se refiere al peligro de usar funciones con especificacin de excepciones en un cdigo robusto: cuando se lanza una excepcin no prevista, directa o indirectamente, la accin por defecto es terminar el programa. Y, claro, esto resulta inaceptable. Debe procurarse algn mecanismo que permita obviar conscientemente este problema sin eliminar las tiles especificaciones de interfaz. La solucin la proporciona la clase bad_exception. Pero vemoslo en detalle. Si el tipo de la excepcin lanzada por una funcin no est en la lista de especificaciones de sta, entonces, como el lector bien sabe, se llama a unexpected(). Si unexpected() lanza a su vez una excepcin permitida en tal lista, entonces contina la bsqueda de manejador en el mbito de la llamada a la funcin primera. Si, por el contrario, el manejador de unexpected() lanza una excepcin de un tipo no permitido (no incluido en la lista), si acaso no se haba incluido el tipo bad_exception en la especificacin, se llamar igualmente a terminate(); si contrariamente se haba incluido, como por ejemplo en
void funcion() throw (int, Overflow, bad_exception );

entonces la excepcin no permitida y lanzada se sustituye por un objeto, definido por cada implementacin particular, del tipo bad_exception y se contina la bs-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 80

bsqueda de un nuevo manejador en el mbito de la llamada a la funcin con la especificacin referida. CONCLUSIONES Como bien afirma Hortsmann, Las excepciones debern reservarse para circunstancias inesperadas en el flujo normal de una computacin y cuya ocurrencia crea una situacin que no puede ser resuelta en su actual mbito. De hecho l mismo establece unas cuantas indicaciones de uso de excepciones:
Captar nicamente aquellos errores que se puedan manejar. Las excepciones deben usarse en circunstancias excepcionales. No apoyarse en excepciones si se puedes validar el cdigo. No lanzar una excepcin si se puede continuar. Permitir a los usuarios de bibliotecas decidir cmo desean que los errores sean manejados. Usar excepciones cuando se den fallos en constructores. No pierdas recursos durante el procesado de excepciones

David Reed, por su parte, expone un plan metdico para incorporar las excepciones a un cdigo ya existente:
Implementar manejadores especiales para las funciones terminate() y unexpected(). Aadir bloques try/catch que cubran las excepciones pre-existentes. Disear y utilizar clases de excepciones. Aadir especificaciones de excepciones a las funciones. Localizar y reparar prdidas de recursos.

Como el lector puede apreciar, el tema da para mucho: quedronse muchas ideas y tcnicas de uso de las excepciones en el procesador de textos, como el mantenimiento de invariantes, el tratamiento de precondiciones y postcondiciones, etc. etc.
sin conocer exactamente recursos lenguaje y las caractersti& en C++ compilador troca imposiblelos definicin del una estrategia exitosa que cas del la de en una eficaz, efectiva y fcilmente M estructure las excepciones sin duda,arquitectura de relojera gobernada por un mantenible. Lo contrario es, una bomba Lea, lector, lea. Porque cualquier intento de aplicar el manejo de excepciones reloj estropeado.

REFERENCIAS DIRECTAS Working Paper for Draft Proposed International Standard for Information Systems - Programming Language C++, Documento X3J16/95-0185WG21/N0785, 26 de septiembre 1995. Exception Handling: Supporting the Runtime Mechanism, Jose Lajoie, SIGS Publications, C++ Report, marzo-abril 1994. Using C++ Exceptions, David Reed, SIGS Publications, C++ Report, marzoabril 1994.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 81

Excepctions: Pragmatic issues with a new language feature, David R. Reed, SIGS Publications, C++ Report, octubre 1993. Designing and Coding Reusable C++, Martin D. Carroll & Margaret A. Ellis, 1995, Addison-Wesley, 0-201-51284-X. The Design and Evolution of C++, Bjarne Stroustrup, 1994, Addison-Wesley, 0-201-54330-3. Mastering Object-Oriented Design in C++, Cay S. Horstmann,1995, John Wiley & Sons, 0-471-59484-9. C++ Strategies and Tactics, Robert B. Murray, 1993, Addison-Wesley, 0-20156382-7. Exception Recovery with Smart Pointers, Steve Churchill, SIGS Publications, C++ Report, enero 1994. Taligents Guide to Designing Programs: Well-Mannered Object-Oriented Design in C++, Taligent Inc, 1994, Addison-Wesley, 0-201-40888-0. Designing with Exceptions, Grady Booch y Michael Vilot, SIGS Publications, C++ Report, Mayo 1994. Designing with Exceptions, Grady Booch y Michael Vilot, SIGS Publications, C++ Report, julio-agosto 1994. C++ Primer, 2nd Edition, Stanley B. Lippman,1991, Addison-Wesley, 0-20154848-8. The C++ Programming Language, 2nd Edition, Bjarne Stroustrup, 1991, Addison-Wesley, 0-201-53992-6.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 82

5
ASIGNACIN EN C++

a asignacin en C++ no es, como no lo son otras muchsimas caractersticas del lenguaje, asunto balad. C++ es sorprendentemente copioso en sutilezas sintcticas, lo que plantea dos cuestiones: la seguridad de las herramientas generadoras de cdigo y la eficacia de los cursos-relmpago de C++ avanzado (se han llegado a publicitar risibles reclamos de la guisa Programacin Avanzada Orientada-a-Objetos en C++, Visual Basic y Clipper en 15 das). C++ es extenso, prolijo, complejo y, afortunadamente, imperfecto en su sentido ms prctico: amigo de lo bueno, como podra haber dicho Voltaire. Lo que sigue es, pues, una concentracin de tcnicas, sintcticas y de construccin de programas, que pretende mostrar al programador novel -y aun intermedio- en C++ las soluciones a distintos problemas bien conocidos, como fuego en carne, por los expertos21. CONCEPTOS BSICOS Como bien sintetiza Winston, El operador de asignacion se utiliza para cambiar el valor de una variable y en C++ viene representado por los smbolos: = *= /= %= += .= >>= <<= &= ^= |= de los cuales en adelante representativamente usaremos el primero: la asignacin simple. Dado el carcter esencialmente mutable de las variables, todos los lenguajes de programacin incorporan un operador de asignacin con una funcionalidad predefinida para los tipos incorporados. As, en C++, el operador de asignacin por defecto es exactamente el operador estndar de C. Qu ocurre, sin embargo, con los tipos definidos-por-el-usuario o clases? Pues que, dado que en C++ se pretende una equiparacin de las clases con los tipos predefinidos, el compilador
21

Al decir de Oscar Wilde, la experiencia es el nombre que cada uno da a sus propios errores, mientras que para Auguez es la suma de nuestros desengaos. Un experto es, por tanto, una persona que, a ms de equivocarse muchsimo, sufre abundantes rechazos y desencantos. La lnea entre un experto y un psictico resulta, as, sorprendentemente frgil.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 83

garantizar la declaracin y, en su caso, definicin de un operador de asignacin implcito para las clases en que expresamente tal no se codifique, y que en esencia consistir en la copia miembro a miembro, secuencial y recursiva, de los miembros no-estticos y de las correspondientes porciones de las clases base de la dada. De esta manera tenemos que (suponiendo que un poltico es un objeto con una cierta oscura funcionalidad) la siguiente lnea:
unPolitico = otroPolitico;

equivale a
unPolitico.operator=( otroPolitico );

El operador impltico, o por defecto, garantiza una intuitiva codificacin de la copia por asignacin en objetos de cualquier tipo, pero que normas rigen respecto de tal operador implcito? No deben ser declaradas en C++ todas las funciones? Existe alguna diferencia respecto de otros operadores? Qu ocurre con la asociatividad? Las clases vacas tambin disponen de operador implcito? Ataquemos, sin ms, la parte sintctica del tema. EL OPERADOR DE ASIGNACIN POR DEFECTO Si no se declara explicitamente el operador de asignacin para una clase dada, el compilador automticamente declarar (con las excepciones que ms adelante veremos) un operador de asignacin implcito, o por defecto, que se definir la primera vez que se utilice una asignacin a un elemento de tal clase. Asi, si tenemos, por ejemplo:
class Politico { /* clase vaca */ }; // sin comentarios Politico unPolitico, otroPolitico; unPolitico = otroPolitico; // todos los polticos son iguales

en la ltima lnea se producir la definicin implcita del operador de asignacin (definiendo antes, si procediera, los operadores de asignacin declarados tambin implcitamente correspondientes a las clases bases directas de la dada y a los datos miembros no-estticos de la misma), en calidad de funcin miembro noesttica perteneciente al protocolo pblico (public) de la clase, con el prototipo:
Politico& Politico::operator=( Politico& )

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 84

y cuya implementacin realiza una copia bit-a-bit del objeto otroPolitico en el objeto unPolitico. De hecho, y segn el borrador del estndar C++ (en adelante WP22: working paper), un operador de asignacin por copia, operator=, es una funcin miembro no-esttica de la clase X con exactamente un parmetro de tipo X& const X&. El prototipo de operador por defecto, generado por el compilador, que hemos visto antes, cambiara empero su parmetro a constante
Politico& Politico::operator=( const Politico& )

nicamente si, y slo si, todos los miembros de la clase Politico y sus posibles clases base directas (muy variadas, atendiendo al sorprendente resultado) poseyeran operadores de asignacin con argumento constante. El operador de asignacin se dice trivial si y slo si es implcito y todas las clases bases directas de la dada, adems de todos los datos miembros no-estticos de tipo no-predefinido, poseen un operador de asignacin tambin trivial. El esquema de copia por defecto es, en definitiva, el siguiente: para cada dato miembro no-esttico de la clase se busca, recursivamente, si el tipo o clase a que tal miembro pertenece posee operador de asignacin, de forma que si existe se usa para copiarlo y si no se genera una copia bit-a-bit. LOS LMITES EXPLCITOS DE LA ASIGNACIN IMPLCITA El compilador no generar un operador de asignacin por defecto en los siguientes casos: Si la clase contiene un dato miembro no-esttico de tipo referencia o de tipo constante, como por ejemplo en:
class Politico { const long ambicion; //una constante poltica Persona& padrino; // imposible empezar sin l // sigue descripcin de clase };

El compilador no podr generar el operador implcito para tal clase, pues, como el ledo lector conoce, los datos miembros de tipo referencia y constantes tienen que ser inicializados y asignados a la vez: esto es, no pueden ser prime-

22

El nombre completo es Working Paper for Draft Proposed International Standard for Information Sytems -- Programming Language C++, y su ltima versin ha sido sometida a revisin pblica, con peticin de comentarios, en los pases cuyo captulo nacional de estandardizacin as lo ha requerido (no Espaa, naturalmente).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 85

ro inicializados para luego asignarles un valor. Precisamente por esto tales miembros han de ser construidos forzosamente en la lista de inicializacin de todos los constructores, y no tienen cabida en una mera copia por asignacin, que es la que proporciona el operador implcito. El compilador originar, pues, sendos errores (parece, as, que la ambicin, por ser constante, y el padrino, por constituirse en referencia, impiden, o cuando menos dificultan, la sustitucin de los polticos). Si la clase contiene un dato miembro no-esttico con un operador de asignacin inaccesible o deriva de una clase base con un operador de asignacin inaccesible. Naturalmente la inaccesibilidad se refiere bien a la imposibilidad de generacin del operador de asignacin por defecto bien a la restriccin en la cualificacin de acceso de tal operador, implcito o no. En cuanto a la inexistencia, veamos un ejemplo:
class PartidoPolitico { Politico Presidente; // sin operador implcito o explcito // y un largo etctera };

Si consideramos a la clase Politico con una ambicin constante (como acabamos de ver), la clase PartidoPolitico contendr un miembro con un operador de asignacin inaccesible (de imposible generacin implcita), y por tanto no generar su propio operador de asignacin por defecto. O sea, un Partido Poltico no podr ser cambiado, sustituido o absorvido por otro si su presidente posee una ambicin constante. En cuanto a la cualificacin de acceso, veamos este otro ejemplo:
class Politico { private: Politico& operator=( const Politico& ); // sigue descripcin de clase };

Aqu hemos proporcionado un operador definido-por-el-usuario, evitando la necesidad de un operador implcito. Tal operador, no obstante, ha sido declarado como privado, de tal forma que no es accesible, as que la clase PartidoPolitico no podr generar tampoco su operador por defecto. De la misma forma, la clase derivada
class Alcalde : public Politico { /* clase vaca */ };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 86

no podr generar, en cualquier caso de los expuestos, su propio operador de asignacin por defecto. As, cuando el compilador se encuentre con la primera expresin de asignacin exclamar algo as como:
error EDC3209: class "X" does not have a copy assignment operator

LA COPIA DE UN PUNTERO GENERA ... OTRO PUNTERO! Atendamos a un error muy extendido. Como el lector bien sabe, el operador de asignacin de los datos miembros, si existe, implcito o no, nicamente se usar cuando estos sean objetos, no punteros. Esto es, si tenemos el cdigo:
class Politico { String* nombre; String alias; }; otroPolitico = unPolitico;

y suponemos que la clase String tiene definido un operador de asignacin (implcito o no), la ltima lnea hara que se copien los datos miembros de un objeto de tipo Politico al otro de la siguiente forma: la direccin del puntero a nombre se copiar en la variable correspondiente del objeto otroPolitico, mientras que para la copia del dato miembro alias se usar del operador de asignacin de String. Naturalmente lo ideal sera que el compilador emitiera un aviso cuando un operador de asignacin implcito copiara un puntero. La realidad, sin embargo, est ah para indicarnos que estas son cuitas del programador y que los compiladores ya tienen demasiado trabajo. Ah, la sin par realidad! ASIGNACIN NO ES INICIALIZACIN El siguiente cdigo:
Politico unPolitico; Politico otroPolitico = unPolitico; unPolitico = otroPolitico;

equivale a:
Politico otroPolitico( unPolitico ); unPolitico.operator=( otroPolitico );

Esto es, la inicializacin (realizada por un constructor) se da cuando se crea un nuevo objeto, mientras que la asignacin (realizada por el operador de asigna-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 87

cin) muta los valores en objetos ya creados. Por eso en la lnea en que aparece el smbolo = y donde se crea el objeto otroPolitico interviene el constructor (denominado constructor de copia) en lugar del operador de asignacin. EL OPERADOR POR DEFECTO RESULTA DEFECTUOSO Naturalmente la copia por defecto no funciona adecuadamente en numerosas ocasiones, en concreto cuando las clases envueltas contienen miembros que requieren la asignacin dinmica de memoria. As, por ejemplo, si nuestra clase contuviera una cadena de caracteres de la forma:
class Politico { public: Politico( int numero = 0 ) : numeroDeLista( numero ){ cout << Se crea el nuevo ideario << numeroDeLista << \n; ideario = new String; } ~Politico() { cout << Se destruye el ideario << numeroDeLista << \n; delete ideario; } private: int numeroDeLista; String* ideario; // resto definicin de clase };

y nos firamos del operador de asignacin implcito, obtendramos resultados inesperados, de forma que el siguiente cdigo
Politico* unPolitico = new Politico( 1 ); Politico* otroPolitico = new Politico( 2 ); *unPolitico = *otroPolitico; // pueden dos polticos compartir // exactamente el mismo ideario? delete otroPolitico; // imperativos electorales delete unPolitico; // la hecatombe!

originara el siguiente resultado (en mi compilador IBM VisualAge C++):


Se crea el nuevo ideario 1 Se crea el nuevo ideario 2 Se destruye el ideario 2 Exception = c0000005 occurred at EIP = 12705.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 88

Qu ha ocurrido? Vemos que, en primer lugar, la copia implcitamente definida origina que se copie en el objeto receptor ... el puntero a la cadena (como vimos en el pargrafo anterior) y no la cadena en s (para lo que habra que reservar espacio y luego copiar los caracteres haciendo uso, por ejemplo, de strcpy(...) suponiendo que la representacin interna de String sea un puntero a char y que adems sea accesible), de forma que tenemos dos objetos apuntando a la misma cadena de caracteres, siendo as que si uno de ellos cambiara la cadena sta cambiara en ambos. Esta situacin, en que ambos comparten exactamente la misma cadena, causa que al operar el destructor de uno de ellos eliminando tal cadena, el otro se quede conteniendo un puntero ... a qu? A basura! De esta manera, cuando se aplica el destructor sobre el segundo objeto, el resultado es ... el desastre. Naturalmente, y sin necesidad de aplicar el segundo destructor, el segundo objeto est en estado inestable, y cualquier operacin con l puede procurar resultados indeseables. Incidentalmente cabe notar, tambin, que el ideario primero queda libre ocupando memoria y ... sin que nadie lo destruya!, gastando as los preciados recursos del sistema. Por fin, y esto lo dejo en ejercicio al inteligente lector, siempre desconfiado de las apariencias, qu ocurrira si cambiramos el orden de destruccin de los objetos? Realmente esto no funciona, as que, como afirman Meyers, Cargill y otros muchos, siempre se definir un operador de asignacin para clases que usen de memoria dinmica. Stroustrup propone una asimilacin, a este respecto, entre constructor de copia, destructor y operador de asignacin, que Horstman formula como regla de esta interesante forma: Cualquier clase con un destructor notrivial necesita un operador de asignacin definido-por-el usuario que realice las copias de manera adecuada, queriendo indicar que si el destructor tiene trabajo que realizar, probablemente el operador de copia/asignacin tenga parecidas tareas, lo que descalificara al operador por defecto. EL OPERADOR DE ASIGNACIN EXPLCITO Si el operador por defecto no funciona correctamente en ciertas clases, habr que dotar a stas con operadores de asignacin expresos, solapando al operador implcito cuando exista o simplemente dotando de l a las clases en otro caso. En primer lugar hay que insistir en que, como ya hemos visto, el operador = debe ser una funcin miembro (regla que se extiende a los tres operadores (), [] y ->), de manera que su declaracin como funcin global (o amiga, un caso especial de aqulla), como por ejemplo
extern void operator=( Politico&, const Politico& );

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 89

originara un error en compilacin. El operador ha de ser tambin forzosamente no-esttico (no hay que olvidar que su funcionalidad se refiere a las instancias de la clase). Recordemos, por otro lado, que la asociatividad de un operador predefinido se mantiene en sus sobrecargas. Tenemos, de esta manera, que cualquier operador de asignacin (predefinido, definido-por-el-usuario, implcito o explcito) es asociativo a la derecha, esto es, de derecha a izquierda, de manera que la expresin
a = b = c = d = e;

siempre se evaluar en el siguiente ordn:


( a = ( b = ( c = ( d = e ) ) ) );

DESIGNACIN NO ES ASIGNACIN Pero veamos cmo aadir nuestros propios operadores de asignacin: En principio, cuando definamos expresamente tal operador ya no se generar el operador implcito, siempre que la declaracin de nuestra funcin admita un solo parmetro del tipo const Politico& Politico&. Esto quiere decir que si declaramos el operador de asignacin nicamente como la siguiente funcin miembro noesttica:
Politico& Politico::operator=( Politico* );

s se producir la definicin del operador de asignacin implcito, pese a que quizs semnticamente se produzca una copia completa de un objeto en otro. De esta manera tenemos que es sintcticamente aceptable la siguiente codificacin:
class Politico { public: // operador ortodoxo explcito Politico& operator=( const Politico& ); // sobrecarga (en el argumento, no en el tipo de retorno) void operator=( Politico& ); // operador no-ortodoxo Politico operator=( Politico* ); // etc., etc. };

De hecho, para establecer la diferencia entre cualquier operador de asignacin y el operador ortodoxo, a este ltimo se le denomina operador de copia/asignacin.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 90

Ahora bien, es semnticamente aceptable que un operador de copia/asignacin devuelva un tipo distinto de Politico&? Es razonable que se devuelva void (aunque alguno pueda alegar que un poltico nunca devuelve nada)? Qu tipo debe, en definitiva, devolver el operador de asignacin/copia? LO QUE LA ASIGNACIN PRODUCE Como el lector sobradamente sabe, la sobrecarga de operadores en C++ debe intentar mimetizar el comportamiento predefinido de tales operadores, ajustndolo a la idiosincrasia de la clase afectada. Si atendemos, pues, al comportamiento de los tipos predefinidos, encontramos que el operador de asignacin, como todos los operadores de C++, produce un valor que, por convencin, es el mismo que el valor asignado (as el valor de la expresin variable = 17 es 17). Precisamente el hecho que los operadores devuelvan un valor permite codificaciones habituales en C++ como:
if ( unPolitico == otroPolitico ) { // sigue ...

Vemos as que nuestro operador de asignacin explcito ha de devolver el objeto al que se asigna, a fin de permitir que las expresiones de asignacin pueden aparecer como subexpresiones anidadas en expresiones ms grandes. Naturalmente podemos estimar que no deseamos codificar tales expresiones encadenadas, y que precisamente para evitarlo devolvemos void. Bueno, esto puede ser cierto e incluso correcto respecto de los operadores no-ortodoxos (con argumento distinto de Politico& const Politico&), pero dada la reutilizacin latente de todo el cdigo C++, es lgico suponer que cualquier usuario de nuestro cdigo presupondr lo ms intuitivo: esto es, que puede utilizar tales expresiones anidadas y que, por tanto, no ha de cambiar su forma de codificar por el arbitrario capricho de otra persona. Pero, exactamente qu devolvera nuestro operador? Un objeto? Evidentemente no, porque si as fuera operaramos con una copia del objeto. Debe devolver, pues, una referencia a un objeto. Pero, una simple referencia o una referencia a un objeto constante? Fcilmente podemos advertir en el siguiente ejemplo
int uno = 1; int dos = 2; int tres = 3; cout << ( uno = dos = tres ) << dos << tres; // imprime 333 cout << ( ( uno = dos ) = tres ) << dos << tres; // imprime 323 cout << ( uno = dos = uno ) << dos << tres; 113 cout << ( ( uno = dos ) = uno ) << dos << tres; 223 // imprime // imprime

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 91

que el resultado de una asignacin puede ser, a su vez, asignado, as que el operador predefinido devuelve una referencia no constante. Pero en el ejemplo advertimos, tambin, los un tanto inesperados resultados de aplicar la asociatividad de izquierda a derecha en la ltima lnea. Debemos considerar, pues, a la hora de codificar nuestra funcin de asignacin si vamos a permitir tal comportamiento. Si no deseamos que el resultado de una asignacin pueda ser usado a la izquierda de una asignacin (como lvalue), que suele ser lo ms prudente, debemos prototipar as nuestro operador:
const Politico& Politico::operator=( const Politico& );

CONVERSIN, CONSTRUCCIN Y ASIGNACIN Se debe limitar, con todo, el prototipo del operador de asignacin explcito a las sobrecargas con un argumento Politico& y const Politico&? Dirase que no. Examinemos el siguiente cdigo:
class Politico { public: Politico( char* promesas = 0 ); const Politico& operator=( const Politico& ); // ... }; Politico puedoPrometerYPrometo; puedoPrometerYPrometo = Jams dimitir;

En la ltima lnea, dado que el operador de asignacin de la clase espera una referencia a un objeto Politico constante y encuentra un puntero a char, se produce una conversin implcita y entra en juego el constructor de la clase, creando a partir de la cadena un objeto temporal Politico que, despus de ser asignado a puedoPrometerYPrometo se destruir antes de finalizar el mbito en que se ubica la expresin. Si deseamos evitar la construccin de un objeto temporal deberemos dotar a nuestra clase con una funcin como:
const Politico& Politico::operator=( char* );

evitando as la puesta en marcha del esquema de conversiones del lenguaje. Naturalmente la regla se puede generalizar de la siguiente forma: Se replicar la sobrecarga de parametros unitarios de los constructores respecto del operador de asignacin.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 92

LA ASIGNACIN EN JERARQUAS DE HERENCIA El operador de asignacin evidentemente no se hereda, pues, como ya hemos visto, si no se declara expresamente en una clase derivada, el compilador proveer uno por defecto, solapando as, en cualquiera de los casos, la funcin de la clase base. Pero, atencin, esto significa que se solaparn todas las funciones con nombre operator=(...) y no slo la funcin con un argumento Base& o const Base&. Y es que el lector debe aprender que asignacin y herencia no son pareja de recibo: si la herencia es mltiple los problemas aumentarn; si virtual, los problemas pueden resultar demasiado sutiles (al decir de los notarios: las asignaciones de herencias pueden conllevar muchos problemas). ASIGNACIN NO ES TRANSMUTACIN Es difcil que un patn se convierta instantneamente en educado, pues solo copiar -si acaso- algunas caractersticas de aqul (y si no, recordemos a El Burgus Gentilhombre). A qu viene esto? Bien: si a un determinado objeto se le asigna otro, parece intuitivo esperar que el objeto a la izquierda del operador sea sustituido por el objeto a la derecha del mismo. Pero esperar lo intuitivo en informtica es tan aventurado como apostar por la lgica en derecho. Y es que, como el lector ya sabe, en C++ un objeto no puede cambiar de clase. As que el operador de asignacin, implcito o explcito, en ningn caso cambiar la disposicin o tamao del objeto a la izquierda del mismo (ni por supuesto del de la derecha). Esto es, si tenemos:
Persona persona; Politico politico;

y suponemos definido el operador de asignacin en la clase Politico admitiendo como parmetro una referencia a un objeto de tipo Persona, la lnea
politico = persona;

no conseguir que el poltico se convierta en una persona, pese a mucho que se porfe. Y es que eso sera tanto como convertir el plomo en oro. Pero vemoslo en detalle:
class Persona { public: virtual void disculpa() { cout << Lo siento\n; } };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 93

class Politico : public Persona { public: void disculpa() { cout << Estaba as cuando llegu\n; } }; Persona persona; Politico politico; // llama a Persona::operator=( const Persona& ) // pues se produce conversin implcita del tipo // Politico a su clase base pblica Persona persona = politico; // pero veremos que no se observa cambio alguno: persona.disculpa(); // Lo siento politico.disculpa(); // Estaba as cuando llegu // lo que sigue es un error, porque intenta acceder // con un objeto de tipo Persona a la funcin de // asignacin implcita, que tiene un prototipo // Politico& Politico::operator=( const Politico& ) politico = persona; // lo que sigue, sin embargo, s funciona, porque // se asigna una persona a la porcin de Persona // que existe en un Politico (al menos en teora). // As que en realidad se aplica la llamada: // ((Persona&)politico).Persona::operator(persona); ( Persona& )politico = persona; // pero, como se ve, el poltico no cambia: politico.disculpa(); // Estaba as cuando llegu

RECURSIVIDAD EXPLCITA: CSAR O NADA Cuando el compilador provee un operador de asignacin implcito est cargando con un tedioso trabajo, posiblemente recursivo, de copia. Si codificamos nuestro propio operador el compilador entender, sin embargo, que no debe en absoluto intervenir. O sea, que no deberemos contar con una ayuda similar a la que se da en los constructores: si no codificamos expresamente la copia de un dato miembro tal copia no se producir. Pero, cmo no, el problema se intensifica en una jerarqua de herencia: el operador implcito automticamente asigna las porciones de las clases base directas de la dada (en el mismo orden en que fueron declaradas en la definicin de la clase), pero en el explcito este trabajo de copia habr de ser expresamente codificado. Esto es, deberemos codificar algo como lo siguiente (y en adelante usar structs discreccionalmente para evitar las etiquetas de acceso pblico):
struct Persona { Persona& operator=( const Persona& ); };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 94

struct Politico : public Persona { Politico& operator=( const Politico& politico ) { // llama al operador de la clase base Persona:operator=( politico ); // y seguidamente copia los datos miembros } };

Bien, pero qu ocurrira si la clase base no dispusiese de operador de asignacin explcito? Nada nuevo! No olvidemos que el compilador proveera entonces un operador implcito, que es una funcin miembro de pleno derecho y que, por tanto, puede ser llamada expresamente, cual es el caso en el ejemplo anterior, o tambin de la siguiente forma:
( Persona& )*this = politico;

Esta es la mejor manera de copiar la porcin de una clase base y, de hecho, la nica pausible, pues de otra forma tendramos que copiar uno a uno los datos miembros de la clase base, pero estos usualmente son privados, por lo que habramos de amigar las clases y ... bueno, esto nos plantea que habremos de tener buenas razones para prescindir del operador de asignacin por defecto. CUIDADO CON LA AUTO-ASIGNACIN Puestos a codificar nuestro propio operador de asignacin, examinemos el siguiente ejemplo:
class Animal { /* definicin */ }; class Persona : public Animal { /* evidente! */ }; class X : public Animal { /* quin sabe qu? */ }; class Politico : public Persona, public X { public: Politico ( char* unNombre = 0 ) { ponNombre( unNombre ); } const Politico& operator=( const Politico& politico ) { delete[] nombre; ponNombre( politico.nombre ); } private: void ponNombre( char* unNombre ) { if ( unNombre ) { nombre = new char[ strlen( unNombre ) + 1 ]; strcpy( nombre, unNombre ); } else { nombre = new char[ 1 ];

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 95

nombre = \0; } char* nombre };

Y ahora aadamos estas lneas de pura maldad:


Politico* politico = new Politico( Fulano ); Persona* persona = &politico; *politico = *persona;

Qu ocurre en la peligrosa ltima lnea? Pues que se ejecuta el cdigo contenido en el cuerpo de la funcin de copia/asignacin, y en sta lo primero es desasignar la memoria dinmica del dato miembro nombre en el objeto *politico, para despus asignar memoria suficiente (midiendo a partir del dato miembro nombre de *persona) para seguidamente copiar la cadena de caracteres. El problema? Que al eliminar la cadena de caracteres del objeto *politico ... se est eliminando la cadena nombre del objeto *persona!, por lo que las subsiguientes operaciones de medicin y copia originan ... el desastre! Pues claro -exclamar el atento lector-: los dos punteros apuntan al mismo objeto y -de nuevo claro- esto no funciona! Hay que cambiar el orden de las sentencias y modificar ligeramente el cdigo para solucionar este pequeo problema! (dejemos que el hirsuto lector tome las riendas y veamos dnde nos lleva). Basta con copiar la cadena del objeto a la derecha de la asignacin (*persona en nuestro caso) a una cadena temporal en calidad de variable local, a la que habr que asignar memoria dinmica suficiente midiendo la longitud de la cadena a copiar, para despus poder eliminar esta cadena sin problemas y luego -aqu el lector empieza a mostrar signos de preocupacin-, bueno luego habra que ver si hay ms punteros o, mejor, copiar todo el objeto en un objeto temporal del mismo tipo, para as poder restituir las variables y... (en este momento el lector, totalmente avergonzado, reconoce que su estrategia en absoluto funciona, y proyecta serios planes de enmienda). En fin, retomemos el captulo: si el problema slo se produce en caso de autoasignacin (directa o indirecta, por medio de lo que se denomina autoexplicativa y brbaramente aliasing), chequeemos esta circunstancia para adoptar diferencialmente la estrategia adecuada, que evidentemente es ... no copiar nada! Es natural que si lo que se pretende es copiar dos objetos exactamente -bueno, inmediatamente matizaremos este adverbio- iguales, el mejor trabajo es no realizar trabajo alguno, con lo que la copia quedar hecha. Nuestro operador quedara de la siguiente guisa:
const Politico& Politico::operator=( const Politico& politico ) { if ( *this == politico ) return *this; delete[] nombre; ponNombre( politico.nombre ); }

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 96

Ah, esto parece perfecto! Pero las apariencias no son ms que eso: pura vanidad. Si atendemos a la lnea de chequeo vemos que se comparan los objetos a ambos lados del operador de asignacin (objetos, no punteros), y adems haciendo uso de un operador de comparacin que ha de suponerse definido para la clase Politico. Atendamos a los hechos. IDENTIDAD, IGUALDAD Y ... FRATERNIDAD? Cul es el criterio que nos permitir comparar dos objetos respecto de la autoasignacin, como hemos hecho en el pargrafo anterior? La igualdad o la identidad? Parece claro que, en general, la igualdad no, pues sta se basa en la exacta similitud de los valores de dos objetos, de forma que, por ejemplo, dos objetos de una clase con un nico atributo de nombre seran iguales si sus nombres coincidieran. La identidad, sin embargo, se refiere al hecho diferencial del objeto: yo soy yo, independientemente de los valores que asuma mi representacin interna. Claro que en la prctica las cosas no son tan sencillas. Seran por ejemplo idnticas dos personas con el mismo NIF? Esto es, sera adecuada la siguiente funcin?
bool Persona::operator==( const Persona& persona ) { return nif == persona.nif; }

Pues bien, slo si el establecimiento de NIFs asegurara su biunivocidad respecto de cada persona, y nicamente dentro del espacio geogrfico espaol, y slo si se descarta a los menores. Demasiadas condiciones. Meyers sugiere la implementacin de una funcin virtual que devuelva una cadena identificativa especial y nica para cada objeto. Claro que esto podra acarrear problemas en un entorno distribuido donde la asignacin de identificadores no estuviera sincronizada. Y por qu no usar del mecanismo de identificacin de objetos propio de C++? En C++ todos los objetos son transitorios (transient), esto es, no sobreviven al proceso o CPU que los cre, y su naturaleza mutable est representada por su direccin en memoria. Por qu no usar, pues, tal direccin y comparar simplemente punteros para verificar la identidad? Pues porque, como hemos visto en el ejemplo del pargrafo anterior de una clase con herencia mltiple, un objeto puede ser referenciado a travs de distintos punteros (correspondientes a las distintas porciones de las clases base que lo componen), con lo que el esquema alternativo en que slo se comparan punteros:
if ( this == &politico ) return *this;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 97

no tiene por qu necesariamente funcionar. El modelo de objetos propuesto por el OMG (Object Management Group) en CORBA (Common Object Request Broker Architecture) propone unos identificadores de objetos (denominados objrefs) que no tienen por qu ser nicos para un slo objeto en tanto cada uno de estos puede existir en distintos contextos no solapados. De cualquier manera el enfoque habitual en bases de objetos es la asignacin automtica y opaca por el sistema de un OID (Object Identifier) a cada objeto. Pero estamos entrando en un tema que examinaremos con ms detenimiento -cmo no?- en el captulo dedicado a Bases de Objetos o Bases de Datos Orientadas-a-Objetos. A fin de cuentas este enfoque de luego veremos es parte sustancial de la Orientacin-aObjetos: involucin permanente y citas circulares. SOBRE LA ASIGNACIN BIDIRECCIONAL Hasta ahora hemos visto cmo una referencia o puntero de una clase derivada de una dada se convierte convenientemente en un puntero o referencia a la clase base para encajar con su operador de asignacin, implcito o no. Pero seamos exigentes: si tenemos
struct Persona { const Persona& operator=( const Persona& ); }; struct Politico : public Persona { const Politico& operator=( const Politico& ); }; Persona persona; Politico politico;

y quisiramos codificar
politico = persona;

o, en general, deseramos una jerarqua de clases en que los valores de los objetos pudieran ser asignados con independencia de las clases involucradas (siempre en la misma jerarqua derivativa), necesitaramos aadir, en el presente caso, una nueva funcin a la clase Politico:
const Politico& Politico::operator=( const Persona& );

que manejara adecuadamente la asignacin de clase base a clase derivada (lo usual es exactamente lo contrario, de clase derivada a clase base, haciendo normalmente uso de la conversin implcita de tipos en caso de mbitos con deriva-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 98

cin pblica). Pero esto significa que ahora tendremos en nuestra clase Politico dos funciones, una con argumento const Persona& y otra con argumento const Politico&, de parejo contenido (relacionadas cuando menos por una inclusin noestricta). Y si la jerarqua es una larga cadena de derivacin tendremos que cada clase constar de un operador de asignacin ms que la anterior, y que la adicin de una clase en medio de tal jerarqua obligara a aadir una nueva sobrecarga del operador de asignacin en las clases derivadas de la insertada. Bueno, es un panorama ciertamente poco elegante y difcil de explicitar en una jerarqua de uso comercial. No habra una forma de usar tan slo un operador que reuniera la funcionalidad de los otros con argumentos de clases bases? En realidad el comportamiento de tales funciones resulta seguir el siguiente esquema:
const Politico& Politico::operator=( const Persona& persona ) { // se chequea la autoasignacin Persona::operator=( persona ); // y aqu las escasas particularidades semnticas return *this; } const Politico& Politico::operator=( const Politico& politico ) { // se chequea la autoasignacin Persona::operator=( politico ); // y aqu la copia del resto de datos miembros return *this; }

Y si dispusiramos de un slo operador con argumento de referencia a la clase base y la actuacin se determinara mediante un cast dinmico? Vemoslo:
const Politico& Politico::operator=( const Persona& persona ) { if ( *this == persona ) return *this; const Politico* politico = dynamic_cast< const Politico* >( &persona ); // si politico es distinto de cero significa que persona // es una referencia a Politico o a una clase derivada, con // lo que la funcin con argumento const Politico& ya no // es necesaria, pues sta hace el trabajo de ambas. if ( politico ) // aqu se copiaran los datos miembros de Politico Persona::operator= ( persona ); return *this; }

Con esta solucin eliminaramos la posible explosin combinatoria (es un decir) y conservaramos una sola signatura para el operador de copia/asignacin a travs de la jerarqua. Naturalmente si se produjera una modificacin en la jerarqua el cuerpo de tales funciones debera ser tambin modificado, pues se llama expre-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 99

samente al operador de la clase base directa. Es, pues, una buena solucin? Ea! Seguro que el inteligente lector ya supone, a estas alturas, que con el operador de asignacin en C++ no hay solucin nica. Podramos decir que el operador de asignacin implcito proporciona lo que se denomina una copia superficial (shallow copy), mientras que nuestra recursividad manual procura la llamada copia profunda (deep copy). La copia superficial presenta escasos problemas conceptuales, mientras que la copia profunda, bueno, por citar slo un problema: qu ocurre cuando se dan referencias circulares en la recursividad hacia atrs planteada? Qu ocurre, por otro lado, con el operador de comparacin para el chequeo de la autoasignacin? No debera tal operador codificarse de la misma manera que el de asignacin montando casts dinmicos? Seguro que s! Digamos que el aumento de complejidad supone un parejo aumento de la capacitacin del programador respecto del lenguaje. As que, como dicen en Trfico, si no est realmente seguro, no adelante, so pena de encontrarse con demasiados problemas y otras tantas peligrosas implicaciones. Y si no veamos qu ocurre cuando el problema se hace virtual (Problemas virtuales! Gracin caerase muerto ya). POLIMORFISMO EN ASIGNACIN Como quiera que un operador de asignacin es una funcin miembro de una clase (se trate de un operador de copia/asignacin o de un operador de asignacin cualquiera), en tal calidad puede ser perfectamente declarado como virtual. La nica salvedad a considerar aqu es que el operador de copia/asignacin de la clase derivada no se constituye en destinatario del mecanismo virtual respecto del operador de copia/asignacin en la clase base, lo cual es ciertamente lgico, merced a la diferencia del tipo del argumento y al especial mecanismo implcito del operador. Examinemos, as, el siguiente cdigo:
struct Persona { virtual int operator=( char* ); virtual Persona& operator=( const Persona& ); }; struct Politico : Persona { virtual int operator=( char* ); virtual Politico& operator=( const Persona& ); virtual Politico& operator=( const Politico& ); }; Politico unPolitico, otroPolitico; Persona* persona = &unPolitico; // llamada a Politico::operator=( char* ) persona->operator=( Disraeli ); *persona = Disraeli; // llamada a Politico::operator=( const Persona& ) persona->operator=( otroPolitico );

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 100

*persona = otroPolitico; // llamada a Politico::operator=( const Politico& ) unPolitico = otroPolitico;

Ah, todo perfecto! Si se definiera, no obstante, nicamente la funcin


Politico& Politico::operator=( const Politico& );

en la clase Politico, desechando la que observa un argumento const Persona&, s se solapara el mecanismo virtual, pues tal funcin escondera a la de la clase base. Este comportamiento resulta, por ejemplo, en la siguiente lgica situacin: si el operador de asignacin se declara virtual y una clase derivada no implementa operador explcito, el mecanismo virtual se resolver, finalmente, en una llamada al operador de asignacin correspondiente a la clase base directa de la dada. Qu pasara, sin embargo -y esto se lo dejo de elemental ejercicio al inquieto lector-, si tal clase base no dispusiera de operador de asignacin explcito? Podramos evitar problemas, no obstante, si codificramos en cada clase de la jerarqua la funcin con cast dinmico que hemos visto antes. Con tal enfoque convendra declarar siempre el operador de asignacin como virtual, lo que permitira codificaciones del tipo:
Politico& creaPolitico( const Persona& ) { persona = personaLobotomizada; }

pudiendo pasar como un argumento una referencia a una Persona o una referencia a una clase derivada de sta. CUANDO LA ASIGNACIN ES INDESEABLE Qu ocurre si no se desea que el cliente de una clase utilice la semntica de copia para cambiar los valores de un objeto de tal clase? Lo usual cuando no se desea procurar cierta funcionalidad es evitar su inclusin en el protocolo de la clase. Aqu, sin embargo, la elipsis hara que entrara en marcha el mecanismo implcito, generando de cualquier forma la funcin indeseada. La solucin? Plum y Saks proponen declarar el operador de asignacin pero sin dotarlo de cuerpo, de manera que su uso generara un error en el enlazado del programa. No es sta, empero, una solucin segura, pues al estar declarada la funcin en la definicin de la clase, el usuario puede aadir la definicin en un aparte. Un procedimiento ms seguro consiste en declarar adems el operador de asignacin en la seccin privada de la clase, de forma que el compilador sealara como error cualquier uso del mismo, as como impedira la declaracin del operador implcito en las clases derivadas. El problema es que si en la jerarqua en cuestin el operador de asignacin ha sido declarado como virtual, el lector ya sabe que la cuali-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 101

ficacin de acceso al operador que se resuelve en tiempo de ejecucin depende de la cualificacin de acceso de la clase a que pertenece el puntero o la referencia desde la que se accede a la funcin. Esto es, si tenemos:
struct Persona { virtual Persona& operator=( const Persona& ); }; class Politico : public Persona { // operador privado Politico& operator=( const Persona& ); }; Politico unPolitico, otroPolitico; Persona* persona = &unPolitico; persona->operator=( otroPolitico ); // OK

la ltima lnea accede al operador privado a travs del puntero a la porcin de Persona en poltico, con lo que se vulnera nuestra intencin inicial. Tenemos, as, que lo mejor sera que el operador de asignacin no fuera virtual, replicando en este caso en cada clase los argumentos del operador de asignacin de sus clases base. Como vemos, se trata de un enfoque sustancialmente distinto al hasta ahora expuesto. En fin, que en C++, como en el mus, objetivamente no puede ganarse a todo (otra cosa es que en la prctica una buena pareja saque el mximo partido a su juego y fuerce continuamente la victoria). LA ASIGNACIN CON CLASES BASE VIRTUALES
Retomemos un ejemplo anterior el en que se da derivacin mltiple: class class class class Animal {}; Persona : public Animal {}; X : public Animal {}; Politico : public Persona, public X {};

Politico unPolitico, otroPolitico; unPolitico = otroPolitico;

La ltima lnea originar que se defina el operador de copia/asignacin implcito para la clase Politico, que a su vez llamar a los operadores implcitos de las clases bases directas Persona y X (por este orden), los cuales, a su vez, llamarn al operador implcito de la clase Animal, que resultar llamado dos veces (una por cada clase derivada, correspondientes a las dos porciones fsicas de la clase base Animal contenidas en Politico). Bien, aparte que esto pueda hacer pensar al lector, qu ocurrira si la derivacin fuera virtual? Esto es, si se tuviera:
class Animal{};

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 102

class Persona : virtual public Animal {}; class X : virtual public Animal {}; class Politico : public Persona, public X {};

Pues que, de acuerdo con el WP, queda sin especificar si la porcin de la clase base virtual Animal se asignar una o dos veces mediante el operador de copia/asignacin definido implcitamente en la clase Politico. El comportamiento quedar, en cada caso, determinado por el compilador concreto utilizado, con lo que viene a colacin el consejo de Cargill: No trates de aprender la semntica de la herencia mltiple de tu propio compilador. Naturalmente tal inespecificidad puede ser salvada -cmo no?- codificando expresamente todos los operadores de asignacin y procurando manejar las asignaciones de todas las porciones, tal y como muestra el mismo Cargill. De cualquier forma en el ARM se reconoce que llegar a un estado de consistencia en jerarquas virtuales con operadores de asignacin es francamente difcil. ALGUNOS CONFUSOS CONSEJOS Ante todo lo expuesto, qu hacer? Codificar o no el operador de asignacin? Declarar el operador virtual? Usar del mecanismo de resolucin dinmica de tipos? Atendamos a lo que opinan los expertos: Saks afirma que se debe trabajar con el operador implcito a menos que haya una razn funcional que lo impida, mientras que Taligent indica que hay que explicitarlo todo, que es mejor codificar un costoso operador de asignacin, cuya funcionalidad sea la misma que la del operador implcito, que dejar a la imaginacin del cliente de la clase el motivo de una supuesta elipsis. Evidentemente aqu se oponen dos criterios bien distintos: el del programador individual y el del programador de marcos o bibliotecas de clases, que sern utilizadas de forma intensiva por otros programadores o usuarios finales. Sabe el lector que aconseja la Gua de Taligent? Pues que en caso de duda se consulte a un arquitecto de software! Y es que, como dijera Disraeli, cunto ms fcil resulta ser crtico que correcto. As estn, con todo, las cosas. La conclusin, as, es la misma que enunciara Bernard Shaw: respecto del operador de asignacin la regla de oro es que no hay reglas de oro. REFERENCIAS DIRECTAS Working Paper for Draft Proposed International Standard for Information Systems -- Programming Language C++, ANSI X3J16, 28-abril-1995. The C++ Programming Language, 2nd Edition, Bjarne Stroustrup, 1991, Addison-Wesley, 0-201-53992-6. Mastering Object-Oriented Design in C++, Cay S. Horstmann, 1995, Wiley, 0471-59484-9. On To C++, Patrick Henry Winston, 1994, Addison-Wesley, 0-201-58043-8.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 103

C++ Programming Guidelines, Thomas Plum & Dan Saks, 1991, Plum Hall, 0911-537-10-4. C++ Strategies and Tactics, Robert B. Murray, 1993, Addison-Wesley, 0-20156382-7. Class Construction in C and C++, Roger Sessions, 1992, Prentice Hall, 0-13630104-5. Effective C++: 50 Specific Ways to Improve Your Programs and Designs, Scott Meyers, 1992, Addison-Wesley, 0-201-56364-9. Advanced C++: Programming Styles and Idioms, James O. Coplien, 1992, Addison-Wesley, 0-201-54855-0. The Design and Evolution of C++, Bjarne Stroustrup, 1994, Addison-Wesley, 0-201-54330-3. Taligents Guide to Designing Programs: Well-Mannered Object-Oriented Design in C++, Taligent, 1994, Taligent Press, 0-201-40888-0.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 104

6
PATRONES DE DISEO

n el captulo Gestin de Proyectos Orientados-a-Objetos se expone de forma breve el panorama aparentemente confuso y un tanto desolador en el que parece estr sumido el Diseo Orientado-a-Objetos (OOD), necesitado de soluciones formales claras, sectorialmente completas, efectivas, comprensibles y aplicables en la gestin diaria de proyectos software. Se trata, en definitiva, de aplicar la modularidad propugnada para la Programacin Orientada-aObjetos (bsicamente segn los criterios y principios que expone Bertrand Meyer en Object-Oriented Software Construction) a las reas del Anlisis y Diseo Orientados-a-Objetos. Y es en este contexto donde aparecen, como sacados de un cuento de Perrault, los patrones de diseo (inevitable traduccin, quizs desafortunada, de Design Patterns: DPs). Basados en la obra del arquitecto y matemtico estadounidense Christopher Alexander, los patrones, cual solucin balsmica, pretenden encerrar la esencia cualitativa de distintas soluciones sectoriales software y generar componentes de diseo universalmente reutilizables. Bien: el propsito es encomiable, y merece la pena examinarlo en algn detalle. LA CALIDAD SIN NOMBRE Los analistas/diseadores con gran experiencia aplican, de forma mayormente intuitiva y automtica, criterios precisos que, en un sentido global, solucionan de forma elegante y efectiva los problemas de modelado software de sistemas reales. Usualmente estos diseadores utilizan mtodos, estructuras y subsistemas que son, a la vez, herramientas del diseo y partes de la solucin final, de una manera que difcilmente puede transmitirse, en un sentido formal, a especialistas menos expertos. Estos bien-dotados diseadores poseen, tambin, un sentido especial que detecta la completitud, en un sentido eminentemente arquitectnico, de un determinado diseo, con independencia de las posibles mtricas y paradigmas utilizados. Naturalmente lo ideal sera extraer la quintaesencia de estos afortunados diseos para formular una suerte de blsamo de fierabrs que pudieran ingerir los diseadores noveles. Aunque, existe en verdad una parte comn en los buenos diseos, a veces tan dispares entre s? Alexander as lo afir-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 105

ma, y da a esta parte la elusiva calificacin de la calidad que no se puede nombrar. Alexander sostiene que existe un algo innombrable que no puede ser modelado nicamente por medio de un conjunto arbitrario de requerimientos. Esto es, que los sistemas poseen una esencia cualitativa que les otorga verdadera identidad y equilibra sus fuerzas internas. Y si bien tal calidad no tiene nombre, s pueden adjetivarse los sistemas que la poseen: vivos, completos, libres, exactos, despersonalizados y eternos. Bien, esto puede sonar un tanto mstico, pero as suena Alexander todo el tiempo. Pongamos un ejemplo arquitectnico prctico: si nos fijamos en las construcciones de una determinada zona rural observaremos que todas ellas poseen apariencias parejas (tejados de pizarra con gran pendiente, etc.), pese a que los requerimientos personales por fuerza han debido ser distintos. De alguna manera la esencia del diseo se ha copiado de una construccin a otra, y a esta esencia se plegan de forma natural los diversos requerimientos. Dirase aqu que existe un patrn que soluciona de forma simple y efectiva los problemas de construccin en tal zona. Este patrn, no obstante, para ser considerado como tal, y siempre segn Alexander, debe encerrar la capacidad de conectar con la cualidad buscada. PATRONES DE DISEO SOFTWARE Tal y como Alexander expone, cada patrn describe un problema que ocurre una y otra vez en nuestro entorno, para describir despus el ncleo de la solucin a ese problema, de tal manera que esa solucin pueda ser usada ms de un milln de veces sin hacerlo siquiera dos veces de la misma forma. Pero pasemos ya al rea software: un patrn de diseo23 es, pues, una solucin a un problema en un determinado contexto. Tal solucin es, empero, a la vez parte del qu y del cmo del sistema completo a construir: esto es, la pieza que conforma el patrn software es como la pieza del patrn de sastre que se utiliza para confeccionar vestidos y trajes, pues tal pieza, aparte de contener las especificaciones de corte y confeccin del producto final, representa a la vez, en apariencia, una parte de tal producto textil. Pero vayamos a un ejemplo prctico. Es usual que en el diseo de distintos sistemas software nos encontremos con similares problemas a resolver, y uno de los ms frecuentes es el que nos enfrenta a un conjunto de objetos (o estructuras de datos -en fin, seamos comprensivos) cuyo contenido debemos recorrer, objeto a objeto, con el fin de operar (comparar, coleccionar, etc.) con los valores que encontremos. Usualmente, tambin, la solucin consiste en usar de un objeto iterador (o funcin iteradora) que recorre la coleccin de elemento en elemento. Pero pronto constatamos que el problema

23

Tambin denominado patrn software o patrn generativo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 106

necesita una solucin matizadamente distinta en cada contexto en el que se plantea: as, por ejemplo, no resulta igual iterar por una coleccin que por un objeto compuesto por capas envolventes, como tampoco es exactamente igual un recorrido que la conjuncin concurrente de varios iteradores sobre la misma coleccin, ni resultan iguales los iteradores concretos que aquellos otros polimrficos, aunque, de alguna manera, la esencia de la iteracin es la misma para todos los problemas de ese tipo. Aqu tenemos, por tanto, un patrn, conocido como Iterador o Cursor, cuya descripcin podra darse de acuerdo con el siguiente esquema (extrado del libro del GOF): Intencin: sucinta descripcin de lo que se pretende conseguir con el patrn. Tambin Conocido como: otros nombres del mismo patrn. Motivo: explicacin justificativa de la necesidad de que el patrn exista como entidad autnoma. Aplicabilidad: lista de usos para los que resulta especialmente adecuado el patrn que se describe. Estructura: descripcin grfica de los comportamientos, acciones y relaciones de los objetos que participan en el patrn. Participantes: diccionario de las partes que componen el patrn. Colaboraciones: diccionario de las relaciones e interacciones entre los participantes en un patrn. Consecuencias: detalle de los posibles beneficios y perjuicios que pueden derivarse del uso del patrn. Implementacin: detalle de las posibles implementaciones y catlogo de las decisiones de diseo en la codificacin de soluciones concretas basadas en el patrn. Cdigo de Ejemplo: planteamiento de cdigo prctico referido a un ejemplo (o ejemplos) suficientemente representativo del uso del patrn. Usos Conocidos: detalle de bibliotecas, productos y sistemas en que se ha utilizado el patrn. Patrones Relacionados: referencias a otros patrones que bien sean directamente utilizados por el descrito bien representen soluciones complementarias o suplementarias al mismo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 107

Si accedemos a un catlogo que contenga este patrn (iterador), encontraremos que se refiere al acceso secuencial a objetos sin entrar en su representacin interna: esto es, sin directamente cambiarlos. Porque resulta que si lo que queremos es actuar de alguna manera sobre los objetos a recorrer, entonces deberemos usar de otro patrn: el conocido como visitador. Vemos, pues, que ya existe una granulacin diferencial de patrones que pretende encapsular la experiencia adquirida en muchos proyectos software de forma lmpida y reutilizable. Y es que, como el lector fcilmente comprender, lo difcil de los patrones es precisamente descubrirlos, pulirlos y formalizarlos, porque la realidad, como una alfombra, necesita ser extendida y desenrollada para que se puedan apreciar sus patrones, pues si no stos aparecen desfigurados y confusos24. CATLOGOS DE PATRONES Si aceptamos, pues, que los patrones pueden resultar tiles en el desarrollo de software, el siguiente paso es reunirlos en catlogos de forma que resulten accesibles mediante distintos criterios, pues lo que necesitamos no es tan slo la completa descripcin de cada uno de los patrones sino, esencialmente, la correspondencia entre un problema real y un patrn (o conjunto de patrones) determinado. Desafortunadamente, y a pesar de la segmentacin en la exposicin de los patrones detallada anteriormente, tal objetivo todava no se ha conseguido: existen catlogos de patrones (como el libro del GOF, que se detalla ms adelante), pero la capacidad de eleccin todava se basa en el conocimiento completo de los mismos. Pero esto se apreciar mejor en un ejemplo. Recientemente un cliente nos enfrent al diseo de una biblioteca genrica de impresin multiplataforma cuyo uso principal sera generar en tiempo de ejecucin objetos concretos de tipo Impresora, con distintas implementaciones, a los que dirigir mensajes de impresin en base a un interfaz genrico predefinido. Tras el pertinente estudio estimamos que el problema bsico de diseo se poda resolver utilizando dos patrones (y en esta eleccin influy notoriamente el lenguaje a utilizar, C++): Prototipo, para diferir hasta tiempo-de-ejecucin la creacin de un determinado objeto impresora, clonando un objeto esttico, y Puente, para separar el interfaz (establecido en una clase base gruesa que encerrara toda la funcionalidad) de las posibles implementaciones (los lenguajes de impresora) que se establecen en una jerarqua paralela aparte 25. Naturalmente este resultado se bas en el anterior conocimiento de un suficiente nmero de patrones, de manera que, en realidad, si no hubieran existido patrones se habra solucionado de

24

Vaya, esto suena profundo!, pero debo reconocer que el mrito, en traduccin libre, es de Themistocles. 25 En realidad se necesit algo ms que dos patrones (como, por ejemplo, un subsistema gestor de implementaciones), pero esa es otra historia (nadie ha dicho que los patrones sean autosuficientes para completar sistemas software).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 108

parecida manera, pues se trataba de problemas que ya se haban abordado anteriormente. Pero, claro, lo que se pretende con un catlogo de patrones no es favorecer al diseador experto (que quizs no necesite en absoluto de los patrones, aunque el estudio de la formalizacin del conocimiento es siempre recomendable), sino ms bien ayudar al diseador inexperto a adquirir con cierta rapidez las habilidades de aqul, como tambin comunicar al posible cliente, si es el caso, las decisiones de diseo de forma clara y autosuficiente. Se trata, en definitiva, de un medio para comunicar la experiencia de forma efectiva, reduciendo (o aplastando, aplanando o suavizando) lo que sorprendentemente se conoce como curva de aprendizaje del diseo. PATRONES ORIENTADOS-A-OBJETOS? Hablamos de diseo de software o ms bien de diseo-orientado-a-objetos de software? Parecera que, segn lo hasta ahora visto, los patrones habran de acoplarse bien a cualquier esquema. Bien: en teora s, pero en la prctica la casi totalidad de los trabajos y catlogos en este campo (como el libro GOF) se refieren a sistemas orientados-a-objetos. Parece que esto responde a que, simplemente, el patrn de conducta en diseo es ahora el OOD. Claro que algunos pretenderan una solucin para todo26, pero parece claro que las ideas de modularidad reutilizable en que se sustentan los patrones encuentran asiento natural en sistemas de diseo con las facilidades modulares de la orientacin-a-objetos. TELEPREDICADORES DE SOFTWARE La Programacin Estructurada, la Orientacin-a-Objetos, y ahora ... los Patrones! En la comunidad software, como en la religiosa y en la poltica, aparecen cada tanto soluciones pretendidamente salvadoras que ofrecen a sus postulantes cambios tan radicales que resultan tentadoramente crebles27. Y es que, con qu herramientas se mide la idoneidad de una teora emprica? Usualmente infieriendo su correctitud desde exitosos ejemplos prcticos. Entonces, si examinamos los patrones, por qu no examinar, en primer lugar, su aplicacin en la arquitectura tradicional? Por qu no estudiar los exitosos trabajos de Alexander? Pues porque el brillante prestigio terico de Alexander (un tanto discutido en su propia rea) est ligado a una desazonadora ejemplificacin prctica de sus proyectos: desde inesperados -por no decir turbadores- resultados a fastuosos fracasos

26

Es como si desearan una suerte de quinta sinfona de Prokofiev (la fusin del clasicismo tradicional y la vigorosa modernidad), pero slo obtuvieran el poderoso scherzo del segundo movimiento. Ah es nada! 27 Remy de Gourmont afirmaba que los hombres son tan estpidos que dando un nombre nuevo a una cosa vieja creen haber pensado algo nuevo. Bierce, ms prctico, ironizaba: Cogito cogito ergo cogito sum.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 109

(como el de la comunidad de Mexicali). Entonces -preguntar el ahora decididamente inquieto lector- los patrones no funcionan en arquitectura? Bueno, querido lector, piense que Alexander, en s, no es la piedra angular de ningn sistema software. Recordemos, por ejemplo, que Collodi fue un mediocre escritor antes de Pinoccio y sigui sindolo despus de ste. A veces una solitaria buena idea genera resultados extraordinarios, y Alexander expone, en un ingls exaltado, varias excelentes ideas. Pinsese, tambin, que los hijos no resultan nunca como los padres porfan han de ser, y es que en la comunidad software a Cronos se lo comeran sus hijos sin darle tiempo siquiera a posar para Goya. Parece, por otro lado, que los patrones son nuevos, pero en absoluto es as, pues existen patrones-marcos formales desde hace tiempo: MVC de Smalltalk, MacApp, etc., as como patrones-de-rutinas que todos conocemos: las bibliotecas de algoritmos. Resulta, al fin, que nos encontramos en una fase incierta de captura y formalizacin de la rica experiencia en diseo extendida en multitud de maduros sistemas software, y aparece claro que el sentido de la marcha es irreversible. Patrones? S, pero con prudencia! PATRONES ELECTRNICOS Dados la juventud y el estado de permanente construccin de los patrones, el lector quizs desee tener acceso a algunas de las fuentes on-line. Helas aqu: World-Wide-Web: obviar las referencias Gopher y de ftp-sites, que pueden ser accedidas mediante el WWW. La Pgina de Patrones (Patterns Home Page) en el Web est mantenida por Richard Helm (s, uno del GOF) y su URL es: http://stwww.cs.uiuc.edu/users/patterns/patterns.html. Aquellos que no puedan acceder al Web pueden obtener esta pgina va e-mail, pues existe un servidor en el CERN que enva por correo electrnico la pgina WWW que se le pida: slo hay que envar un mensaje via correo electrnico a <code>listproc@www0.cern.ch. La lnea del asunto no tiene importancia, pero en el cuerpo del mensaje debe figurar <code>"www [URL completa]" (en este caso www http://st-www.cs.uiuc.edu/users/patterns/patterns.html). Tambin en el Web, en http://g.oswego.edu/dl/pd-FAQ/pd-FAQ.html o en http://gee.cs.oswego.edu/pd-FAQ.html puede encontrarse un FAQ (Frequent Answers & Questions: Frecuentes Preguntas y Respuestas) de patrones. Listas de correo: esta es la materia viva de la que el lector podr extraer lo ltimo en patrones. Es aqu, tambin, donde se pueden exponer ideas, pedir consejos, etc. Discusin de Patrones (patterns-discussion): En esta lista se discuten la teora y aplicacin de patrones, incluidos los trabajos de Alexander y si sus ideas

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 110

pueden o no aplicarse al software, as como herramientas y mtodos que soporten patrones en el desarrollo de software, y si los patrones software son similares o diferentes de otras clases de patrones. Para aadirse a la lista debe enviar un mensaje a listserver@cs.uiuc.edu con el siguiente cuerpo: subscribe patterns-discussion Nombre Apellidos. Si tienen problemas para obtener la subscripcin y contrasea, pnganse en contacto con Ralph Johnson (s, amable lector, otro del GOF), el propietario de la lista, en johnson@cs.uiuc.edu. Patrones de Negocio (business-patterns): En esta lista se pretenden dejar de lado los patrones de bajo-nivel para tratar de aqullos con relevancia para el mundo empresarial. Para suscribirse hay que enviar un mensaje a businesspatterns-request@cs.uiuc.edu con la lnea subscribe como cuerpo. Patrones del Clan-de-los-Cuatro (Gang-of-4-Patterns): Esta es una lista centrada en el libro del GOF, aunque sus autores se pasean por las otras listas tambin. Para aadirse a la lista debe enviar un mensaje a listserver@cs.uiuc.edu con el siguiente cuerpo: subscribe gang-of-4-patterns Nombre Apellidos. Compuserve: En la seccin 3 (Study Hall) del forum CLMFORUM de Compuserve se est discutiendo actualmente el libro del GOF. Conferencias: aparte de las que seguidamente se mencionan hay que resear la seccin de OOPSLA dedicada a los patrones: en realidad la mayora de conferencias sobre Orientacin-a-Objetos empiezan a considerar -si es que ya no lo han puesto en prctica- la inclusin de una seccin especfica de patrones. PLoP 94: La Primera Conferencia Anual sobre Patrones (PLoP: Pattern Languages of Programs) se celebr del 4 al 6 de agosto de 1994 en Monticello, Illinois, USA. El planteamiento de esta conferencia result particularmente gratificante, porque los trabajos no fueron expuestos directamente por sus autores, sino por un grupo de revisores pre-seleccionados que en cada caso expusieron sus gustos, quejas y sugerencias, fomentando as la participacin entre los asistentes. PLoP '95: La Segunda Conferencia Anual sobre Patrones se celebr del 6 al 8 de septiembre de 1995 en Monticello, Illinois , USA. PLoP 96: La Tercera Conferencia Anual sobre Patrones. Los interesados pueden contactar con los organizadores en plop95@parcplace.com, o dirigirse

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 111

bien Richard P. Gabriel en rpg@parcplace.com bien a Kent Beck28 en 70761.1216@compuserve.com. EuroPLoP 95 : La Conferencia Europea sobre Patrones (European Pattern Languages of Programs), celebrada del 7 al 11 de agosto de 1.995 en Aarhus, Dinamarca, en conjuncin con ECOOP 95.

28

Kent Beck, que pertenece al Grupo de Patrones de Hillside, present en OOPSLA 89, junto con Ward Cunningham, las fichas CRC, como el lector orientado-a-objetos posiblemente ya sabr.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 112

7
ROLES Y OBJETOS EN C++

mpecemos con una pequea disgresin lingustica: el vocablo rol no existe en castellano, pues habitualmente se utiliza papel en el sentido de cargo o funcin que uno desempea en alguna situacin o en la vida (RAE). Lamentndolo mucho <grin> tal trmino papel parece referirse ms bien a personas, y adems, al poseer un signicado contextual, casi siempre tendramos que utilizar la frase papel desempeado/interpretado/jugado/acometido por, mientras que el barbarismo rol (del ingls: role) nos permite expresar sin ambigedad situaciones como, por ejemplo, el rol de mdico o el rol de la impresora, tal y como hacen los psiclogos y los malos literatos. El barbarismo es, pues, ms directo y claro. Eugenio DOrs deca que el estilo, como las uas, es ms fcil tenerlo brillante que limpio, pero en informtica quizs haya de ser simplemente eficaz. Algn lector se habr preguntado, con todo, por qu enfatizo tanto las decisiones lingsticas. Pues porque resulta que el modelado software del mundo real se basa en requerimientos, verbales o escritos, en los que los vocablos y la sintaxis juegan un papel esencial. De hecho buena parte de los mtodos de OOA/OOD se basan en la bien-establecida tcnica de Abbott que sustituye sustantivos por clases y verbos o frases verbales por responsabilidades/relaciones/mtodos/mensajes. Resulta al fin que, como afirma Nietzsche, estamos presos de las redes del lenguaje, y los fillogos tienen un gran futuro en el campo informtico. Sigamos con otra diminuta disgresin: la conceptualizacin y modelado de roles han sido conveniente y abundantemente estudiados en el rea de Inteligencia Artifical: marcos (frameworks), ranuras (slots), redes semnticas, etc. resultarn familiares al lector avisado en esas lides (y si no qu mejor que ojear los textos de Winston, Norvig y tantos otros). Pero aqu no tratamos de capturar la representacin del conocimiento ni otro parecido elevado proposito, sino ms bien mostrar distintas tcnicas arquitectnicas para solucionar en C++ la codificacin de escenarios en que los roles aparecen. As que ... al tema.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 113

CLASES DE ROLES Planteemos, sin ms, un problema tpico al que se enfrenta la mayora de soluciones software de gestin para entornos comerciales: un cliente, sea persona fsica o jurdica (en su acepcin ms amplia, no necesariamente fiscal), puede a la vez ser tambin proveedor, acreedor, comisionista, colaborador, socio, etc. Naturalmente el problema es cmo modelar los roles -usualmente simultneos- de tal cliente, garantizando, a la vez, que se mantiene la integridad referencial en la porcion de cada rol que conforma el comn subconjunto de datos interseccin de todos ellos (el nombre, el nif <sic>, etc.). La primera cuestin es: constituye cada rol una clase distinta? Shlaer y Mellor exponen que uno de los trucos (o tcnicas) para encontrar objetos en la fase de anlisis consiste en buscar roles desempeados por personas u organizaciones (doctor, enfermera, paciente, agente, cliente, empleado, supervisor, propietario, etc.). Segn esto los roles concretos son claramente instancias de una clase representativa del rol, y as tendramos las clases Cliente, Proveedor, Acreedor y dems. Intentemos una primera codificacin, en la que a cada rol se asocia una clase independiente:
class Cliente { public: String nombre(); void nombre( String* ); Date fechaDeAlta(); PlazoDePago plazoDeCobro(); // etc., etc. private: String* nombre_; String* apellidos_; Date* fechaAlta_; PlazoDePago* plazoDeCobro_; // etc., etc. }; class Proveedor { public: // un interfaz similar al de cliente private: String* nombre_; String* apellidos_; Date* fechaAlta_; PlazoDePago* plazoDePago_; // y sigue y sigue };

Es fcil ver que el resultado es ingenuamente ineficaz: los roles comparten mucha informacin que aqu simplemente se replica (con las dificultades de mantenimiento que esto conlleva). Necesitamos, pues, que estas clases de rol posean como porcin comn la representativa de la clase Persona. Y rpidamente aqu el lector exclamar: hay que derivar, con la misma segura solemnidad con que

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 114

Luis XIV exclamara Ha olvidado Dios todo lo que he hecho por l?. Pero no tan deprisa. En realidad una de las causas del fracaso de primeros proyectos en C++ es la sobredosis de herencia. Intentemos, no obstante, la sugerencia del lector, muy avisado ya en estas cuitas. UNA BUENA HERENCIA LO ARREGLA TODO? Qu tipo de herencia necesitaramos? Privada, pblica o protegida? Parece claro que protegida no, desde luego. Entonces, privada o pblica? Y aqu, de nuevo, el impenitente lector rpidamente exclamar: Como se trata de una relacin ES-UN, procede la derivacin pblica. Bien, bien, bien. Pero, se trata realmente de una relacin de subtipacin ES-UN? En fin, dejmonos llevar de nuevo por el lector:
class Persona { /* clase base abstracta */ }; class PersonaFisica : public Persona { public: String nombre(); void nombre( String* ); // etc., etc., private: String* nombre_; String* apellidos_; // etc., etc. }; class Politico : public PersonaFisica { public: PartidoPolitico partido(); // se hereda el interfaz pblico de PersonaFisica private: PartidoPolitico* partido_; };

As las cosas, un Poltico ES-UNA Persona? Bueno, esto significara que all donde se espere una persona podra perfectamente aparecer un poltico. Y, claro, aparte del lgico disgusto, esto es defendible -al menos jurdicamente. De esta manera tendramos que funciones con prototipo similares a
void encarcela( PersonaFisica* ) { /* cdigo */ } void soborna( Persona* ) { /* cdigo */ }

felizmente admitiran sendos punteros a objetos de tipo Politico, clase derivada pblicamente de Persona y PersonaFisica. La derivacin privada, al no permitir en tal mbito la conversin implcita de punteros de clases bases a clases derivadas, parece totalmente inapropiada para su aplicacin a los roles.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 115

DINMICA DE CLASES Bien, parece que la derivacin puede funcionar y que los roles son objetos (por clases) de pleno derecho, como establecen Shlaer y Mellor. Pero resulta que stos afirman poco despus que este conjunto de objetos (los representativos de roles) deber contemplar el caso de una enfermera que momentneamente es paciente en un hospital. O sea, que los roles, como evidencia la realidad, son esencialmente dinmicos. Segn Grady Booch, el rol de un objeto denota la seleccin de un conjunto de comportamientos que estn bien-definidos en un punto concreto en el tiempo, siendo tal rol la cara que un objeto presenta al mundo en un momento dado, de forma que la mayora de objetos interesantes interpretan diferentes roles durante su vida, como por ejemplo en el curso de un da, la misma persona puede interpretar el rol de madre, doctor, jardinera y crtico de cine. El carcter dinmico de los roles no encaja, empero, con la disposicin esttica de la herencia en C++. Esto es, en C++ un objeto no puede cambiar de clase, por lo que si tenemos un objeto rol de tipo Medico que en un momento dado asume el rol de Paciente, no podremos mutarlo de Medico a Paciente, sino que ms bien deberemos crear un nuevo objeto de tipo Paciente al que traspasar el ncleo de PersonaFisica embebido en Medico. Necesitaramos, pues, algo como lo siguiente:
class PersonaFisica : public Persona { public: PersonaFisica( PersonaFisica* pPF) { nombre = pPF->nombre; nacimiento = pPF->nacimiento; // se asignan los dems datos miembros } PersonaFisica personaFisica() { return PersonaFisica( this ); } // sigue resto descripcin de clase }; class Medico : public PersonaFisica { public: Medico( const PersonaFisica& ); // etc., etc. }; class Paciente : public PersonaFisica { public: Paciente( const PersonaFisica& ); // resto de descripcin doliente }; // aqu tenemos a un objeto de tipo Medico Medico cardiologoJefe;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 116

// ... // poco despus el mdico enferma (el tabaco, ya saben) Paciente paciente( cardiologoJefe.personaFisica() );

Este mecanismo un tanto soez permite replicar la porcin de PersonaFisica en cada uno de los objetos roles. Pero pinsese que no es la copia lo que necesitamos, sino que paciente y mdico sean la misma persona. Y es que la misma realidad desvirta el esquema esttico de derivacin en C++, al menos en lo que a roles se refiere. Imaginemos, por ejemplo, que tenemos una clase-rol para Ministro de Interior y otra clase-rol para Ministro de Justicia, y ocasionalmente el presidente del gobierno decide unificar ambos ministerios. El nuevo rol resultante Ministro de Interior y Justicia, Es realmente nuevo? Es una clase distinta? Nos encontramos ante un caso de herencia mltiple? Podemos usar las dos clases anteriores simplemente replicando la porcin correspondiente a la nica persona que los detenta? No, no, no y por supuesto que no, respectivamente! LA HERENCIA INNECESARIA Si la herencia no nos soluciona el problema, por qu no renunciar a ella? Examinemos, pues, la opcin ms natural: si necesitamos una porcin de Persona en cada rol, por qu no aadirla simplemente?:
class Medico { public: String nombre() { return persona->nombre(); } Medico( PersonaFisica* pPF ) { persona_ = pPF; // resto inicializacin } PersonaFisica* persona() { return persona_; } // resto interfaz pblico private: PersonaFisica* persona_; EspecialidadMedica* especialidad_; };

Bueno, esto ofrece un mejor aspecto. Pero, no cumple la misma funcin la herencia privada en C++, en el sentido de insertar en los objetos de clases derivadas una porcin privada de la clase base? En esencia s, pero sin procurarnos una porcin separada representativa de tal parte privada. Y es que la herencia es como las armas, el ingenio o la cucharilla del postre: slo hay que usarla si es inevitable.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 117

Tenemos, pues, que la opcin de capas expuesta (layering) permite, de forma sencilla, que dos objetos-rol compartan al mismo individuo de fondo:
PersonaFisica* juanNadie = new PersonaFisica(); // aqu se inicializa debidamente el // objeto juanNadie (apellidos, etc.) Medico* jefeDePlanta = new Medico( juanNadie ); // se opera con el mdico (o ste opera), y // seguidamente, cuando ste ingrese como // paciente, se construye tal objeto con la // misma persona que asuma el rol de mdico Paciente tuberculoso1002( jefeDePlanta->persona() );

La diferencia respecto del anterior esquema derivativo es que aqu existe un objeto diferencial de tipo PersonaFisica al que pueden apuntar distintos roles. La persona representada por juanNadie no abandona -al menos no necesariamente- el rol de mdico cuando asume el rol de paciente, a la vez que se preserva la nocin de identidad (una nocin fundamental que repasaremos cuando examinemos las Bases de Objetos) respecto del sujeto que desempea el rol. Sin embargo aqu se nos plantea un nuevo problema: cundo se destruye el objeto de tipo Persona contenido en un objeto de tipo Medico? Tal y como lo hemos planteado, en el destructor de la clase Medico podemos hacer dos cosas igualmente malas: bien eliminar el objeto Persona, con lo que otros objetos, como por ejemplo de tipo Paciente, que apunten hacia el mismo quedaran en estado indefinido; bien no eliminar tal objeto, de tal forma que se irn consumiendo valiosos recursos de memoria: en definitiva, dos vertientes del desastre. Necesitamos, pues, de la matizacin de una estructuracin conocida como Clase Carta de Singleton, bien explicitada en el texto de Coplien (y de forma sintetizada en el de Murray), y que, en breve, se basa en que una clase, a modo de sobre o envoltura, sirve de interfaz respecto del mundo exterior de la carta (por clase) que contiene:
class PersonaFisicaRep { friend class PersonaFisica; private: PersonaFisicaRep() { // inicializacin bsica datos miembros } // sigue resto de constructores String* nombre; String* apellidos; Date* fechaNacimiento; int contador; }; class PersonaFisica { public: PersonaFisica() { // aqu se accede al constructor privado

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 118

// de la representacin de PersonaFisica rep = new PersonaFisicaRep(); rep->contador = 1 } // sigue resto de constructores PersonaFisica& operator=( const PersonaFisica& pPersonaFisica ) { // incrementamos el contador de objetos // que apuntan a la Persona del argumento. pPersonaFisica.rep->contador++; // si la representacin de la persona // contenida en el presente objeto ya no // es apuntada por nadie, se elimina. // (sin contar el presente objeto, claro) if ( --rep->contador <= 0 ) delete rep; // se sustituye una representacin por otra rep = pPersonaFisica.rep; return *this; } ~Persona() { // comprueba si existe ms de un objeto que // apunte a la representacin interna de // Persona. En otro caso lo elimina. // (ms de uno, porque al menos uno lo // apunta: el presente objeto: *this) if ( --rep->contador <= 0 ) delete rep; } String* getApellidos() { return rep->apellidos; } // sigue resto interfaz pblico private: PersonaFisicaRep* rep; };

De esta manera deberamos cambiar el interfaz de nuestra clase Medico de la forma:


class Medico { public: Medico( PersonaFisica* pPF ) { // se cambia la asignacin a objetos // en lugar de la anterior a punteros, // para que acte el operador de asignacin // redefinido anteriormente. *persona_ = *pPF; // resto inicializacin } // resto definicin de la clase };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 119

As que sta es la solucin? Claro que no! Bueno, esto funciona, pero ... es demasiado artificioso (respecto del problema que pretende resolver), pedestre e inseguro: debemos definir en cada rol un mtodo que devuelva la porcin de PersonaFisica (o PersonaJuridica, en su caso); se establece, adems, un contrato con los programadores (usar asignacin con objetos, etc.) sin establecer, no obstante, precondiciones y postcondiciones en otro lugar que no sea la documentacin. Y es que al renunciar a la herencia hemos renunciado a algo muy importante: al grueso del polimorfismo en C++. Resulta que ahora no contamos, entre otras cosas, con la conversin implcita de tipos, y que funciones como las siguientes:
void tributaAHacienda( Persona* ); void aprendeDeAnterioresErrores( PersonaFisica* );

no podrn aplicarse a punteros a objetos de tipo Medico o Politico, pues tales no derivan pblicamente de Persona o de PersonaFisica. Por supuesto que una posible solucin (de carcter casi policial) sera
tributaAHacienda( politico->persona() );

Lo malo es que si hemos redefinido en la clase Politico alguna funcin ya establecida en la clase PersonaFisica, tal nueva funcionalidad no se aplicar en este caso, pues en el cuerpo de la funcin trabajaremos no con un objeto Politico accedido mediante un puntero a su porcin de PersonaFisica, sino con un objeto de tipo PersonaFisica que no sabe nada de Polticos o Mdicos. Y es que las funciones virtuales (lo que aqu necesitamos) slo funcionan, por su propia naturaleza, en esquemas derivativos. As que, seor notario, d marcha atrs! DIVIDE Y HEREDARS Ya que ni la simple herencia ni la composicin por capas nos solucionan satisfactoriamente el problema de los roles, por qu no usar ambos esquemas en una mixtificacin que rena lo mejor de cada uno? As, en primer lugar, tendremos una jerarqua de clases significativas de las entidades que pueden asumir roles, que por el momento simplificaremos a las siguientes, en clara relacin de herencia:
class Sujeto (abstracta) class Persona (abstracta) class PersonaFisica class PersonaJuridica

Seguidamente necesitamos modelar una estructuracin de clases representativas de los roles de tal forma que no haya que repetir para cada clase la gestin

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 120

del Sujeto que cada una contenga. Pero los sujetos pueden pertenecer a distintas clases, por lo que parece adecuada una jerarqua como la que sigue (y aqu tambin abreviaremos la descomposicin):
class Rol (abstracta) class RolDePersona (abstracta) class Politico class Cliente class RolDePersonaFisica (abstracta) class Medico class Paciente class Empleado class AmoDeCasa

Y ahora intentaremos aplicar todo lo anterior: la clase Rol contendr un puntero a un objeto de tipo Sujeto, que ser
class Rol { public: Rol( Sujeto* pSujeto ) { *sujeto = *pSujeto; } virtual Sujeto* getSujeto() { return sujeto; } private: Sujeto* sujeto; }; class RolDePersona { public: RolDePersona( Persona* pPersona ) : Rol( pPersona ) {} // Atencin: la prxima funcin es virtual, // porque aunque el tipo de retorno es distinto // del de la clase Rol, es un puntero a un tipo // que deriva pblicamente de aqul. Persona* getSujeto() { return (Persona*)sujeto; } // resto definicin de clase }; class RolDePersonaFisica { public: RolDePersonaFisica( PersonaFisica* pf ) : RolDePersona( pf ) {} PersonaFisica* getSujeto() { return (PersonaFisica*)sujeto; } // resto descripcin protocolo de clase

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 121

}; class Empleado { public: Empleado( PersonaFisica* pf ) : RolDePersonaFisica( pf ) {} Salario* getSalario(); private: Salario* salario; Date* fechaContratacion; // resto definicin de clase; };

Como vemos los roles concretos nicamente deben preocuparse de incluir cdigo en su constructor, mientras que la asignacin del sujeto, y por tanto el nudo de los problemas, se circunscribe a la clase base Rol. Necesitamos, por fin, una jerarqua de representaciones internas de los sujetos (las cartas de los sobres de Singleton, que son las clases derivadas de Sujeto), y cuya definicin se obviar por ser idntica a la anteriormente expuesta:
class PersonaFisicaRep; class PersonaJuridicaRep; // etc., etc.

Bien, esto parece funcionar, as que es momento de que el lector se cuestione: Cul es el fallo? Porque cuando el autor afirma que parece funcionar es seguro que algo falla. Bueno, bueno, ya nos vamos conociendo y se aprecian ciertos leitmotivs wagnerianos. Y s, algunas cosas no encajan bien. Lo que de todo lo expuesto en primer lugar se infiere es que, como ahora parece evidente, un rol NO-ES una persona, ni un tipo de persona, aunque, por ejemplo, Politico es claramente un tipo de Rol. La separacin de jerarquas aparece, pues, inapelable. Qu pasa, sin embargo, con la interoperabilidad en el mundo real respecto de los roles y de quienes los asumen por la que asimilamos, verbigracia, un mdico a la persona que ejerce de mdico? Qu ocurre, por otro lado, con el cambio dinmico de roles? Pinsese, por ejemplo, que tenemos la posibilidad de cambiar el objeto, de tipo Sujeto o derivado, que ostenta el rol mediante una funcin del tipo:
void Rol::cambiaSujeto( Sujeto* pSujeto ) { *sujeto = *pSujeto; }

que ser heredada por todos los roles concretos. Pero, realmente sirve de algo esta posibilidad de cambio? Puede un rol cambiar de persona, o es ms bien la

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 122

persona la que cambia de rol? Parece que, por un lado, existen ciertas capacidades bsicas o comunes asociadas a determinados roles, pero es claro que es el sujeto el que cambia, o ms bien simultanea, roles. Por otro lado, no les resulta molestamente repetitivo el mimetismo de la jerarqua de roles respecto de la sujetos? Por qu reflejar en aqulla la estructuracin de esta ltima? Qu ocurre, por otro lado, con el fin del rol? Se deber aadir a los objetos de tipo Rol un atributo de trmino del Rol que ser establecido justo antes de eliminar el objeto? Quizs todo este asunto necesite un re-enfoque, y quin mejor que los expertos para asesorarnos? Leamos el orculo. EL PATRON DE ROLES INTERCAMBIABLES Oh, oh! Patrones! Bueno, no poda ser de otra manera, pues lo que se pretende es la transmisin formal de la experiencia. El problema de los roles no es nuevo y parece lgico pensar que existan distintas sintetizaciones del mismo. Como es costumbre, empezaremos por la ms dbil: Peter Coad establece que el problema del rol se enmarca en un patrn estructural genrico que denomina Patrn de Roles Intercambiables (Changeable Roles Pattern) y que en definitiva consiste en que existe un objeto que acta de Intrprete del rol y que se relaciona con un solo objeto a la vez de una clase derivada de Rol, que a su vez es una clase abstracta base de una jerarqua similar a la expuesta. Coad establece la siguiente configuracin mnima:
class Interprete { private: Rol* rol; // ... }; class Rol { private: Time* momentoDeComienzo; Time* momentoDeFin; // ... };

De la clase Rol derivaran clases representando roles especficos (Medico, Politico, etc.). Como vemos, los papeles han cambiado: ahora se operar nicamente con intrpretes (por sujetos), y stos contendrn la informacin sobre qu rol asumen en cada momento. Este enfoque, demasiado simplista y general (Could Coad code?), presenta la ventaja de su efectividad comunicativa y dos evidentes dificultades: por un lado impide la concurrencia temporal de roles (No puede un Cliente ejercer de tal aun estando calificado como Proveedor?); por otro deja al criterio del lector la implementacin de la funcionalidad de los roles respecto del intrprete, pues es al intrprete al que se dirigirn los mensajes relativos a los

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 123

roles. Respecto del primer problema (la concurrencia) el lector me permitir una elegante elipsis hasta solucionar en alguna medida el segundo. Bien: este patrn nos ha dejado insatisfechos, as que, por qu no ms de lo mismo? EL PATRON DE ESTADOS Pree, tras constatar la inoperante genericidad del patrn de Coad, afirma que el problema de la implementacin de la relacin entre Intrprete (o Jugador) y Rol se soluciona con otro patrn: el denominado Patrn de Estados (State Pattern), que se detalla en el libro GOF de Gamma y otros. El cometido bsico de tal patrn es permitir a un objeto modificar su comportamiento cuando quiera que su estado interno cambie, apareciendo como que el objeto cambia de clase. Su implementacin en C++ es, bsicamente, la siguiente: en vez de que una clase disponga de datos miembros especficos cuyos valores en distintos objetos reflejen sus distintos estados y afecten, as, al comportamiento de sus funciones miembros, tales datos miembros y funcionalidad asociada son extrados y encapsulados en objetos aparte, de forma que el objeto original mantiene un puntero a los mismos y posee mtodos para cambiar tal apuntamiento de un objeto representativo, por ejemplo, del estado de recepcin a otro valedor de estado de envo. Si sustituimos en el patrn original los nombres Contexto y Estado por los ya usados Sujeto y Rol tendremos:
class Sujeto { public: setRol( Rol* unRol ) { rol = unRol } unMensajeCualquiera() { rol->maneja( this ); } private: Rol* rol; }; class Rol { public: virtual Rol* maneja( Sujeto*); }; class RolConcreto : public Rol { public: virtual RolConcreto* maneja( Sujeto* ); };

de manera que los mensajes (relativos al rol) dirigidos a un Sujeto seran pasados, como una llamada a una funcin virtual, al rol concreto contenido en cada caso en el objeto Sujeto. Bien: esto es mejor que lo anterior pero, a mi juicio, Pree

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 124

peca de ingenuidad (lo cual es lgico, dado el carcter anecdtico con que trata este tema, pues su libro est enfocado hacia Metapatrones y Hot-Spots). La aplicacin de este patrn no nos soluciona bien el problema planteado: pinsese que, en primer lugar, todas las funciones de todas las clases derivadas de Rol deberan declararse como virtuales en la clase base Rol, y adems luego deberan definirse en la clase Sujeto para permitir el redireccionamiento previsto. As, cada vez que aadiramos un nuevo rol deberamos modificar la clase Rol y la clase Sujeto, y recompilarlo todo! Esto, naturalmente, no encaja agradablemente con la modularidad propugnada por la Tecnologa de Objetos. Es necesario, pues, cambiar de patrn? No! Yo ms bien dira que hay que aadir algn patrn ms. EL PATRN PROXY DE SUBROGACIN Este patrn establece cmo controlar el acceso a un objeto desde otro distinto. Exactamente -es un decir- lo que queremos, pues se pretende controlar el acceso a la funcionalidad embebida en los roles a travs de objetos de tipo Sujeto. Necesitamos, pues, llamar en objetos de la clase Sujeto a funciones que no pertenecen a esta clase y s a cualquiera derivada de Rol, pero no queremos replicar este conjunto de funciones en Sujeto. Cmo solapar, pues, el chequeo esttico del compilador relativo a tales funciones? Pues con la sobrecarga del operador puntero. Apliquemos, sin ms, el patrn al cdigo:
class Sujeto { public: setRol( Rol* unRol ) { rol = unRol; } Rol* operator->() { return rol; } private: Rol* rol; }; class Persona : public Sujeto { /* ... */ }; class PersonaFisica : public Persona { /* ... */ }; class Rol { public: virtual void noPiensoDimitir(); }; class Politico : public Rol { public: void noPiensoDimitir() { cout << Lean mis labios: ; cout << N-O--P-I-E-N-S-O;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 125

};

De esta manera ahora podramos codificar lo siguiente:


PersonaFisica unaPersona( /* inicializacin */ ); Politico* politico = new Politico( /* inicializacin */ ); unaPersona.setRol( politico ); unaPersona->noPiensoDimitir();

Examinemos con ms detenimiento la ltima lnea: se le manda el mensaje -> al objeto unaPersona, de la clase PersonaFisica, y como en la clase Sujeto, base de aqulla, se define una sobrecarga del operador puntero, sta se aplica, y por tanto el mtodo asociado responde devolviendo un puntero al objeto rol contenido en unaPersona (exactamente contenido en la porcin de Sujeto embebida en unaPersona). El puntero que se devuelve apunta a un objeto de tipo Politico, pero como el operador -> devuelve un puntero a Rol, se produce una conversin implcita de Politico* a Rol*, merced a la derivacin pblica de la primera clase respecto de la ltima. Sobre este puntero se aplica ahora el operador puntero global, para que por su mediacin se llame a la funcin noPiensoDimitir(). Tal funcin es virtual por lo que, aunque se la llame a travs de un puntero a la clase base Rol, se ejecutar el cuerpo de la funcin correspondiente a la clase del objeto, sta es, Politico. Bien, esto funciona y parece suficientemente elegante, pero, como siempre, hay que explicitar algunas consideraciones, matizar algunos comportamientos y corregir ciertas inconveniencias. CONVERSIONES E INDIRECCIN Ahora tenemos dos distintas jerarquas: la de Sujetos o Intrpretes y la de Roles, pero es habitual que, en el mundo real, donde se espera la actuacin en base a un rol se admita a una persona para acometer tal accin. O sea, necesitamos que una funcin que espere un Rol admita tambin un Sujeto. Debemos, pues, definir los operadores de conversin:
class Sujeto { public: operator Rol*() { return rol; } operator Rol&() { return *rol; } private: Rol* rol;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 126

};

de manera que se puede codificar lo siguiente:


void sobornaA( Politico* unPolitico ) {} void encarcelaA( Politico& unPolitico ) {} PersonaFisica unaPersona; Politico politico* = new Politico; unaPersona.setRol( politico ); sobornaA( unaPersona ); encarcelaA( unaPersona );

As, en las dos ltimas lneas se produce, mediante la aplicacin de los operadores definidos, una conversin del objeto Persona en la parte de Rol que contiene: en la ltima lnea en forma de objeto, y en la penltima en forma de puntero a tal objeto. Naturalmente se podra objetar que lo que se necesita es precisamente lo contrario: que funciones que esperan objetos de tipo Sujeto admitan objetos de tipo Rol o derivados. Pero no, realmente no encaja bien este esquema cuando hemos estimado que el rol carece de sentido autnomo funcional (aunque no de comportamiento definido) sin el sujeto que lo desempea. Fjese el lector, con todo, que la sintaxis se va complicando: a la funcin que espera un puntero a Politico se le pasa ... un objeto de tipo Persona. Pero es que si el lector retrocede un poco ms ver tambin como el operador puntero se aplica ... a objetos! Esto conlleva algunas consecuencias:
PersonaFisica* punteroAPersona = new PersonaFisica; PersonaFisica objetoPersona = *punteroAPersona; punteroAPersona->setRol( politico ); // OK objetoPersona->noPiensoDimitir(); // OK punteroAPersona->noPiensoDimitir(); // ERROR

pues, como el hbil lector ya habr adivinado, la ltima lnea usa del operador -> predefinido y, por tanto, no se produce redireccin alguna, y dado que la funcin que se llama no pertenece a la clase PersonaFisica (ni a la seccin pblica de sus clases base), el compilador justamente se queja. Otra consecuencia es que el mecanismo virtual no funciona directamente mediante el operador -> sobrecargado, pues aqul slo funciona sobre punteros y referencias, no sobre objetos.

Hemos solucionado, con el patrn de subrogacin, una parte del problema de replicacin del interfaz, pero no completamente. Seguimos teniendo que aadir todas las funciones de las clases derivadas en la clase base Rol y recompilar cada vez. Alguna solucin? Bueno, podramos aadir una capa ms de indireccin:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 127

class Sujeto { public: Sujeto() { controlRol = new ControlRol( this ); } ~Sujeto() { delete controlRol; } ControlRol* operator->() { return controlRol; } Rol* getRol() { return rol; } private: Rol* rol; ControlRol* controlRol; }; class ControlRol { public: ControlRol( Sujeto* unSujeto ) { setSujeto( unSujeto ); } void setSujeto( Sujeto* unSujeto ) { sujeto = unSujeto; } // aqu seguira el interfaz que antes // deba replicarse en la clase base Rol: // cada funcin se reencamina hacia la // clase adecuada mediante casts. void noPiensoDimitir() { ((Politico*)(sujeto->getRol())) ->noPiensoDimitir(); } private: Sujeto* sujeto; };

De esta manera las operaciones dirigidas a objetos de tipo Sujeto mediante el operador puntero seran redirigidas al objeto de tipo ControlRol que tal contiene, y desde aqu seran redirigidas, a su vez, hacia la clase concreta, sobrepasando el mecanismo virtual. Cul es la ventaja respecto del anterior esquema? Pues que cada vez que aadamos un nuevo rol nicamente habremos de modificar esta clase externa, sin tocar ni roles ni sujetos. Parece, as, que el mal se convierte en mal menor: nos evitamos las recompilaciones, cuando menos. Richard Helm me ha confirmado que en el GOF discutieron repetidamente el Patrn de Roles (Roles Pattern), pero que al final se decidi no incluirlo en su libro catlogo, quizs por no disponer en el momento de su edicin de una solucin

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 128

que contemplara la intensa casustica a modelar. Afortunadamente parece que Erich Gamma y Richard Helm han alumbrado un nuevo patrn (ExtensionObjects), que se publicar prximamente en la columna bimensual que ambos escriben en el Dr. Dobbs Journal Windows Sourcebook, y que servira de base al esperado Patrn de Roles. La idea es aportar una clase con un interfaz que permita preguntar a un determinado objeto si soporta o asume un determinado interfaz o rol. El resultado de tal consulta sera un objeto con la funcionalidad del rol buscado, que naturalmente permitira interactuar con el objeto inicial a travs de su interfaz. Parece que tal nuevo objeto sera una suerte de Adaptador (vase el Patrn del Adaptador en el libro GOF), y permitira a sus clientes utilizar un determinado interfaz para acceder a clientes solamente si pueden asumir un rol dado. Segn Helm, lo magnifico de este patrn es que permitira definir dinmicamente nuevos interfaces de clases sin compilarlos en la declaracin de tales clases, evitando as que las clases tuvieran interfaces hiper-hinchados para reflejar todos sus posibles usos por clientes. La idea parece interesantemente afortunada, y aunque aparenta tener puntos en comn con la anteriormente expuesta, habr que esperar un poco ms para discutirla. CONCURRENCIA Y SECUENCIACIN DE ROLES Todo lo anterior est relativamente bien, pero obvia una cuestin esencial: un mismo sujeto, en un perodo de tiempo dado, suele asumir distintos roles concurrentemente. El tratamiento secuencial que hasta ahora le hemos dado a la asuncin de roles presenta, con todo, serios inconvenientes: Qu ocurre cuando sustituimos en un sujeto un rol por otro? Se crea cada vez un nuevo rol y se destruye el sustituido? Dnde queda la memoria de lo asumido? Naturalmente aqu no funciona el esquema de Singleton, pues no se intenta compartir un mismo objeto, sino ms bien mantener vivos unos objetos de tipo rol. Es claro que si el objeto de tipo Sujeto se destruye (ojo: no es lo mismo que un sujeto muera -esto es, que definitivamente cambie de estado- que el objeto que lo representa sea destruido) debern desaparecer con el todas las referencias que a l apunten, junto con todos los objetos que con exclusiva dependencia maneje. Bien: intentaremos solucionar a la vez los problemas planteados por la secuencialidad y la concurrencia de roles. En lugar de un puntero a un nico objeto de tipo Rol, necesitamos de una coleccin de punteros, as que recapitulemos:
class Rol { public: Bool activo(); Bool finalizado(); private: Time* momentoDeComienzo; Time* momentoDeFin;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 129

// ... }; class Sujeto { public: Sujeto(); ~Sujeto(); ControlRol* operator->(); void setRol(); Rol* getRol(); operator Rol&(); operator Rol*(); private: Rol* rol; // el rol actual ColeccionDeRoles* roles; ControlRol* controlRol; };

Simplificando la realidad, aceptaremos que un sujeto puede mantener varios roles concurrentemente, pero todos ellos permaneceran latentes menos uno, el rol actual, sobre el que se actuara en cada momento. Intentemos, pues, codificar la memoria de roles:
void Sujeto::setRol( unRol ) { if ( Rol* rolTemp = roles->contieneMismoTipo( unRol ) ) if ( rolTemp->activo() ) { rol = rolTemp; return; } roles->inserta( rol = unRol ); }

As distinguiremos entre sustituir un rol y finalizarlo, sirviendo el parmetro de setRol(...) nicamente para establecer el tipo (mediante typeid) del rol que se pretende activo. Naturalmente esta codificacin no es, de lejos, la ms eficiente o elegante, pero resulta convenientemente didctica y estratgicamente breve, sobre todo teniendo en cuenta que, dada la leve insatisfaccin que la solucin dada ha generado, en seguida vamos a adoptar un enfoque radicalmente distinto. EN LA ASOCIACIN EST LA FUERZA Si, desde una ptica sindical, decidimos que hay escasos patrones que realmente nos sirvan de ayuda, y que necesitamos nuevas luces, qu mejor que la asociacin? Atendamos, de nuevo, a los expertos: Para Rumbaugh un rol es un nodo de una asociacin, puesto que una asociacin binaria tiene dos roles, cada uno de los cuales puede tener un nombre de rol. Esto resulta significativamente importante. Hasta ahora hemos considerado que un Rol es un

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 130

portante. Hasta ahora hemos considerado que un Rol es un objeto de pleno derecho, pero ... y si no lo fuera? Consideremos un array o vector de objetos (de cualquier tipo): el primer objeto es, en realidad, un objeto que juega el rol de primero; naturalmente tal rol es intercambiable mediante operaciones en el objeto continente, pero ... a alguien se le ocurrira modelar tal rol como una clase Primero? Bueno, seguro que a alguien, pero es razonable tal modelado? En general parece que no. El rol se transforma aqu en un mero vocablo que designa un nodo direccional dentro de una relacin. Pero leamos a ms autoridades. Para Embley, por ejemplo, un rol es un atajo para expresar especializacin. De esta manera un rol, al nominar una conexin entre objetos, es una especializacin de la clase del objeto en la conexin cuyos objetos totalmente participan en el conjunto de relaciones en la conexin, queriendo as expresar que la nica diferencia entre una especializacin de rol y una generalizacin/especializacin es el carcter mandatorio de aqulla primera respecto de las clases que participan en la relacin: o sea, un Empleado de un hospital no tiene por qu tener pacientes asignados, pero un mdico siempre tendr al menos uno: el conjunto de los empleados de hospital que poseen pacientes es el que determina la relacin de rol. Pero curiosamente Embley parte de un Empleado como clase, quiz derivada de Persona, y segn lo expuesto parece que Empleado es un rol desempeado por una persona en relacin con una empresa: en realidad se trata de la cualificacin de uno de los nodos de una Relacin Laboral. Y ... es hora de tomar un pequeo respiro, que la cosa parece complicarse. Porque realmente un rol no es un objeto? Examinemos esta afirmacin con ms detenimiento, usando a tal fin una Relacin Laboral. Este tipo de relacin se establece entre una Persona y una PersonaFisica, de forma que la relacin se definira como (y obviaremos de momento las cuestiones de jerarqua de relaciones):
class RelacionLaboral { private: Persona* empleador; PersonaFisica* empleado; long salarioAnual; Date* fechaDeIncorporacin; Date* fechaDeCese; RangoTemporal* horarioDeTrabajo; // etc., etc. };

Toda la informacin relativa a la relacin queda as establecida en virtud de atributos de la relacin misma. Pero, qu pasa con las Personas que respecto de esta relacin asumen roles bien determinados: empleado y empleador? No poseen ahora un comportamiento adicional al que tenan como meras PersonaFisica y Persona, respectivamente, que no se modela en la propia relacin? No tiene el empleado, por ejemplo, determinados derechos y obligaciones? Bueno, tenemos dos opciones: bien significamos estos comportamientos en la propia relacin, con apropiados parmetros, bien aprovechamos todo lo expuesto y

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 131

aadimos sendos objetos de tipo Rol a la relacin. Optaremos -razones de economa tipogrfica- por el segundo caso, as que roles siguen siendo objetos. Vemoslo:
class RelacionLaboral { private: Persona* empleador; Empleado* rolEmpleador; PersonaFisica* empleado; Empleador* rolEmpleado; // resto protocolo clase };

Pero, por qu no encapsular los objetos de tipo Rol en los sujetos, como se expuso anteriormente, en lugar de aadirlos a la clase Relacion? Pues porque de tal manera los roles quedaran sin conexin con la relacin que los genera, de manera que encapsulndolos en la relacin podemos tener, verbigracia, tres roles de tipo Empleado bien diferenciados. Como quiera, por otro lado, que todas las relaciones cualifican a los sujetos relacionados en virtud de roles direccionales, necesitamos extender la asuncin de roles a ms entidades, para lo cual debemos ampliar la jerarqua de intrpretes, que ahora pasarn a ser Entes, resultando algo singularmente ms extenso que lo siguiente:
Ente Bien BienInmueble Finca BienMueble Arma Prenda Bolso Cartera Gafas Joya Vehiculo Bicicleta Ciclomotor Motocicleta Turismo Persona PersonaFisica PersonaJuridica AsociacionDeVecinos SeccionOrganizativa Ubicacion ComunidadAutonoma Localizacion Provincia Pais

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 132

Poblacion Via Calle Carretera Cruce

Bajo esta nueva situacin se puede fcilmente hablar, por ejemplo, del rol de propietario que asume una sociedad limitada respecto de un vehculo, que a su vez asume el rol de posedo, ambos roles siempre respecto de una relacin binaria de pertenencia. Pero sigamos: dado que todas las relaciones binarias encierran entes asumiendo roles, por qu no encapulsar tal comportamiento en una clase base? Y de paso, por qu no tipificar las relaciones entre distintos tipos de entes? Intentmoslo:
class TipoDeRelacionEntreEntes { public: TipoDeRelacionEntreEntes( const Ente&, const Ente&, Rol* = 0, Rol* = 0 ); ~TipoDeRelacionEntreEntes(); private: // los entes se tratan como referencias para // obligar a su inicializacin en el momento // de la construccin de los objetos, y forzar // la inmutabilidad de los tipos tras esto. // El ente en s no importa: slo su tipo. Ente& origen; // nodo inicial Ente& destino; // nodo final // nombre de la relacin (v.b. "Propiedad") String* nombreGenerico; // relacin del origen respecto del destino // (v.b. "Posee" es propietario de) String* nombreRelacion; // relacin del destino respecto del origen // (v.b. "es posedo por" es propiedad de) String* nombreRelacionInversa; // objetos roles asumidos por los entes Rol* rolOrigen; Rol* rolDestino; // etc., etc. }; class RelacionEntreEntes { public: RelacionEntreEntes(); RelacionEntreEntes( Ente*, Ente*, TipoDeRelacionEntreEntes* = 0 ); ~RelacionEntreEntes(); // funcin de modificacin void set( Ente*, Ente*, TipoDeRelacionEntreEntes* ); // funciones de acceso

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 133

Ente* getOrigen(); Ente* getDestino(); TipoDeRelacionEntreEntes* getTipoRelacion(); private: Ente* origen; Ente* destino; TipoDeRelacionEntreEntes* tipoRelacion; // etc., etc. };

De esta manera contamos con la posibilidad de trabajar bien con meras asociaciones nominadas bien con relaciones especializadas resultantes de aplicar la herencia a aqullas. Naturalmente sobre lo anterior cabra aplicar sendos interfaces grficos: En primer lugar deberamos ocuparnos de una coleccin que mantenga de forma dinmica los tipos de relacin activos en cada momento aplicables a los Entes. Hay que tener en cuenta que los tipos de Entes en tales relaciones representan la clase base a que son aplicables (la mnima base comn), de forma que la bsqueda de relaciones ser fundamentalmen-te polimrfica. Seguidamente el interfaz bsico de los tipos admitidos para una determinada relacin. Lo que estamos haciendo es, en definitiva, aislar de la clase Relacion y de sus derivadas el chequeo de tipos exactos de Entes aplicables para la asuncin de roles. Tal flexibilidad nos permitira mdelar con facilidad, incluso grficamente, prolijas relaciones de roles entre objetos, como por ejemplo las siguientes:

FIGURA RELACIONES DINMICAS

Naturalmente estamos planteando una asuncin dinmica de roles susceptible de generar consultas tambin dinmicas. Como vemos ahora el objeto Rol est contenido en objetos TipoDeRelacionEntreEntes, que a su vez estn contenidos en objetos de tipo RelacionEntreEntes o derivados, que a su vez contiene objetos de tipo Ente. Todo el esquema singular anterior (objetos roles contenidos en objetos de tipo Sujeto) deber ser convenientemente modificado respecto de la clase Ente: los operadores de conversin habrn de ser dotados de mecanismos de resolucin (se podran aplicar distintos roles), los redireccionamientos (mediante el operador ->) debern buscar primero una relacin adecuada para despus devolver el rol correcto, etc., etc. Pero esto se deja como ejercicio al inteligente lector (le doy mi palabra que no aparece ningn concepto realmente nuevo o no tratado en este captulo ... bueno, al menos en una versin elemental).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 134

LA CITA DEL DESASOSIEGO Terminemos con una interesante puntualizacin de autor reconocido (y que nos perdone Don Fernando): En buena parte de la literatura sobre Inteligencia Artificial se nota que los roles temticos especifican la relacin de un objeto con una determinada accin, significada por un verbo o frase verbal, con los consiguientes problemas de ambigedad contextual que esto supone. Jacobson aboga porque se embeba completamente la accin en un objeto rol explcito, as que propone que se denomine a las relaciones que determinan un rol por un sustantivo mejor que por un verbo: esto es, resultara ms adecuado decir El objeto Persona interpreta el rol de un Conductor respecto del Coche que Un Coche es conducido por una persona o Una Persona conduce un Coche, y basa su criterio en que un nombre expresa mejor la unidireccionalidad de las asociaciones: parece claro que en la relacin matrimonio o estar-casado-con, el marido conoce a la esposa y viceversa, pero en la relacin, por ejemplo, ser-rey-de, el sbdito conoce al soberano, pero no necesariamente viceversa, por lo que Jacobson concluye que la mayora de relaciones en el mundo real son unidireccionales y no bidireccionales, como implcitamente sugieren las formas verbales conduce o esconducido, claramente reversibles. Quizs este criterio supone una esquematizacin extrema, pero la idea que en l subyace es la de la visibilidad inter-roles, algo que el mtodo OORASS trata con particular detalle. REFERENCIAS DIRECTAS Aparte de los ttulos que seguidamente se detallan (por orden de aparicin en el captulo) el lector inquieto puede estudiar el mtodo originariamente denominado OORASS (Object-Oriented Rles Analysis, Synthesis and Structuring), desarrollado por un equipo liderado por Trygve Reenskaug para Taskon, y que actualmente se denomina OORAM. Este mtodo, partiendo de un enfoque ciertamente original, busca reas de actuacin (concern areas) para modelarlas usando agentes y objetos que pueden asumir distintos roles, en la misma posicin estructural, respecto de distintos contextos. A los Roles, como objetos de primera categora, les son aplicables requerimientos, operaciones y competencias, y adems tienen relaciones con otros Roles, generalmente unidireccionales (un rol conoce de otro, pero ste no conoce de aqul). En fin, demasiado para tan pocas lneas. Lea, lector: lea. Program Design by Informal English Descriptions, R.J. Abbott, 1983, Communications of the ACM, 26(11), 882-94. Object-Oriented Systems Analysis: Modeling the World in Data, Sally Shlaer & Stephen Mellor, 1988, Prentice Hall, 0-13-629023-X. Object-Oriented Analysis and Design with Applications, 2nd Edition, Grady Booch, 1994, Benjamin/Cummings, 0-8053-5340-2.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 135

Advanced C++ Programming Styles and Idioms, James O. Coplien, 1992, Addison-Wesley, 0-201-54855-0. Object-Oriented Patterns, Peter Coad, 1992, Communications of the ACM, 33(9). C++ Strategies and Tactics, Robert B. Murray, 1993, Addison-Wesley, 0-20156382-7. Design Patterns for Object-Oriented Software Development, Wolfgang Pree, 1995, Addison-Wesley, 0-201-42294-8. Design Patterns: Elements of Reusable Object-Oriented Software, Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides, 1995, AddisonWesley, 0-201-63361-2. Object-Oriented Modeling and Design, James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy & William Lorensen, 1991, Prentice Hall, 013-629841-9. Object-Oriented Systems Analysis: A Model-Driven Approach, David W. Embley, Barry D. Kurtz & Scott N. Woodfield, 1992, Prentice Hall, 0-13-629973-3. Patterns discussion mailing lists, GOF y otros, 1995. Asistencia Tcnica para la Mecanizacin de la Polica Local de Logroo, Ricardo Devis, 1994, Infoplus SL. Object-Oriented Software Engineering: A Use Case Driven Approach, Ivar Jacobson, Magnus Christeron, Patrik Jonsson & Gunnar vergaard, 1992, Addison-Wesley, 0-201-54435-0.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 136

8
BASES DE OBJETOS DATOS ORIENTADAS-A-

n alguno de los cursos de Tecnologa de Objetos que imparto muestro una transparencia con el ttulo Diseo de Bases de Datos para seguidamente, tras una estudiada pausa, superponer otra con una seal de prohibicin, a la vez que afirmo categrico: No hay diseo sustantivo de bases de datos. Y punto: nada que aadir. Naturalmente el buscado efectismo intenta comunicar que si en Tecnologa de Objetos el abismo (gap) semntico entre Anlisis y Diseo se difumina, tal solapamiento debiera ampliarse a las etapas de codificacin y almacenamiento. O sea, las entidades que se encuentran en la fase de anlisis de requerimientos se correspondern biunvocamente con clases/objetos en las de anlisis y diseo, para despus mantener su integridad modular y conceptual tanto en la implementacin como en el esquema de persistencia. Para abreviar: el objeto finalmente almacenado en la Base de Datos se corresponder estructuralmente con aqul encontrado en el dominio del problema, significando as que queda sin sentido el trabajo de descomposicin en estructuras de datos asumibles por gestores concretos que luego habrn de ser nuevamente compuestas para su uso efectivo. La cuestin es desmontara usted cada noche su coche en piezas para reconstruirlo en la maana siguiente, cuando desee usarlo? Evidentemente no 29, al menos directamente. El enfoque ms elegante sera dejar que un guardacoches responsable se ocupara del auto, sin necesaria sujecin a un garaje dado, y nos lo entregara cada maana en perfecto estado de funcionamiento. Y es aqu donde aparecen las bases de datos orientadas-a-objetos en sus distintas graduaciones. DEGRADADO DE BASES DE DATOS Como las verduras en las pequeas tiendas de barrio, la Orientacin-a-Objetos en Bases de Datos posee distintos grados de pureza. Helos aqu:

29

Cuando formulo esta pregunta ante equipos de anlisis y diseo estructurados la respuesta invariablemente es: Por supuesto! Es lo que hacemos a diario!

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 137

Bases de Objetos Puras (ODBMSs: Object DataBase Manager Systems): Los productos que se enmarcan en esta categora usualmente ofrecen la misma funcionalidad que puede encontrarse en gestores relacionales maduros (integridad, concurrencia, distribucin, persistencia, recuperacin de errores, etc.), con la particularidad de basarse en un estricto modelo de objetos, significados por OIDs (Object Identifiers). La naturaleza avanzada de los mismos procura adems, por lo general, servicios de migracin de objetos, soporte de trabajo en grupo, transacciones distribuidas, etc. Gestores de Almacenamiento Persistente (PSMs: Persistent Storage Managers): En entornos de ingeniera y CAD, donde lo que importa es la focalizacin del equipo en el trabajo real, los PSMs proporcionan servicios de persistencia que aislan al usuario especializado de las tareas de segmentacin, almacenamiento y composicin de entidades, usalmente con identidad propia temporal. Diramos que se trata de OODBMSs especializadas que, en esa razn, carecen (o disponen pobremente) de algunos de los servicios genricos de stas, como control avanzado de integridad de datos, evolucin dinmica de esquemas, etc. Envoltorios de Objetos (OWs: Object Wrappers): Se trata de capas software que se constituyen, como el envoltorio de un caramelo, en interfaz entre el usuario y el pegajoso interior relacional. Las estructuras segmentadas en tablas pueden ofrecer, as, un interfaz orientado-a-objetos susceptible de interactuar con otros similares interfaces. Esta opcin aparcese de forma natural cuando se intentan compatibilizar las tcnicas de orientacin-a-objetos en anlisis/diseo y GUIs con bases de datos relacionales pre-existentes, o aun con la imposibilidad prctica de operar con gestores reales de objetos. El peligro es, naturalmente, que pueda llegar a confundirse wrapper con front-end o, aun peor, con un mero interfaz-de-dibujitos. En realidad los envoltorios que aqu se detallan son usualmente no visuales, constituyndose as en mediadores (O/R bridges) entre las vistas y la informacin tabulada que manejan. As, por ejemplo, el evento/mensaje clicked aplicado/enviado al botn de una determinada vista resultar en el envo del mensaje ejecutaQuery a un objeto envoltorio de tipo, verbigracia, ClienteWrapper, que a su vez se ocupar, mediante la implementacin interna (como funcin miembro en C++) de una funcionalidad contenedora de una frase SQL, de acceder y unir (JOIN) varias tablas para devolver, de forma conceptualmente unificada, una respuesta coherentemente encapsulada30. El wrapper se transforma as en un intermediario que encierra cuestiones de implementacin especficas de el/los gestor/es re-

30

El equivalente gastronmico es claro: el cocinero eficaz es, a efectos del comensal, un wrapper entre los simples alimentos y las pesadas composiciones culinarias. Evidentemente, cuando las viandas poseen calidad, sabor y textura per se, el cocinero se troca en mero transportista: vamos, la anttesis de la nouvelle cousine.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 138

lacional/es a que accede, separando as, de una forma adecuada para los sufridos mantenedores de aplicaciones, la oscura parte tabular de los voltiles dibujos de ventanas. Hay que decir, empero, que subsisten -naturalmente- los problemas de eficacia relacionados con la gestin de informacin compleja: un vale de entrada y el abandono de andrajos facilitan la asistencia a la pera, pero en absoluto ayudan a la inmersin musical en las obras. Bases de Datos Relacionales Extendidas (RDBMS/Os) o con-orientacion-aobjetos (a-algunos-objetos, que dira ms de un malicioso usuario): De las chisteras de las grandes compaas de RDBMSs aparece, de tanto en tanto, alguna porcin de lo que nos presentan como conejo y que, sin embargo, es mayormente gato. Ahora una patita (procedimientos almacenados), luego esos bigotes (disparadores/triggers), ms tarde ... qu? La presin del mercado consigue que lo que debiera presentarse como RDBMSs mejoradas -y ciertamente es as- aparezca en mercantilista calidad de Bases de Datos Relacionales Orientadas-a-Objetos. Naturalmente este tipo de producto se debe al casi siempre loable afan de supervivencia base de la evolucin darwiniana, y aunque algunos puedan decir que la evolucin del dimetro de la cabeza para albergar ms ideas no es sino simple mixomatosis, la verdad es que las cuestiones de compatibilidad se imponen: sea cual sea el tamao de la cabeza lo cierto es que seguir gobernando el mismo cuerpo, lo cual es bueno y malo. Bueno porque se aprovecha sin merma toda la estructura de informacin pre-existente; malo porque nueve gineclogos no reducen a un mes el perodo de preez de una gestante: encapsulacin, herencia y polimorfismo son conceptos en buena medida ajenos a estos gestores. Qu producto usar depende en gran medida del lenguaje, de las herramientas, del tipo de aplicacin. Y aunque lo usual es empezar por el mbito ms relacional e ir escalando caractersticas de objetos segn se encuentran problemas o imposibilidades, yo recomendara comenzar con las bases de objetos puras e ir bajando a esquemas con mayor componente relacional conforme no se cumplan las caractersticas de eficacia, rapidez, etc. Deseadas. Pero vayamos a la parte humana de los objetos. LOS DESEOS DEL PROGRAMADOR Seguro que los programadores, como clase, albergan toda suerte de deseos nocivos, pero entre ellos uno destaca por su inters morboso: el de liberarse de las repetitivas codificaciones de acceso y recuperacin de datos en bases de datos. Si, de acuerdo con el esquema involutivo en espiral (de fuente o de piscina) de las fases de anlisis y diseo, la mayor parte del tiempo se pasa intentando generar un interfaz limpio de clases para su implementacin, por qu no dedicar el tiempo restante a la codificacin algortmica inteligente, en vez de tratar con aspectos que podran ser en gran medida mecanizados o, cuando menos, obviados

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 139

por sistemas de gestin de ms alto nivel? La respuesta a la pregunta retrica es obvia. El lector se cuestionar, empero, el calificativo morboso: lo cierto es que la solucin de las cuitas aqu planteadas pasa por una degradacin de la profesin misma de programador, cuya funcionalidad bsica ha sido, tradicionalmente, trasladar a cdigo los resultados exactos de la fase de diseo. Si, con el nuevo esquema del ciclo de vida del software, la codificacin queda grandemente sustituida por la lectura y el reuso de clases insertas en bibliotecas y entornos-marcos, y adems prcticamente se elimina la codificacin final de almacenamiento, qu queda para el programador? No resulta ms rentable y efectivo, ms an teniendo en cuenta el gran acervo actual de herramientas software, que el mismo diseador traslade al cdigo los resultados del diseo? Edward Berard afirma que la figura del programador habr de ser sustituida por la del Analista del Dominio del Problema Orientado-a-Objetos (OODA: Object-Oriented Domain Analyst). Tal presuncin es un tanto efectista, pero la idea subyacente es prudentemente razonable. De cualquier forma el hecho es simple: el programador tiende a desear un gestor de almacenamiento transparente (por invisible), o cuando menos translcido. El presupuesto inicial es sencillo: el manejo de instancias de objetos en memoria ha de ser igual o muy parecido al manejo de los mismos objetos en un espacio de almacenamiento fsico. As, si consideramos que la memoria es el almacenamiento primario (AP) y, verbigracia, el disco el secundario (AS), el esquema ideal de cosas pasara por considerar que los objetos (instancias) pueden, merced a mecanismos muy simples, pasear entre AS y AP considerando stos como zonas de un hbitat global para nuestras instancias. PERSISTENCIA, TRANSITORIEDAD Y MATRICES La persistencia es, en esencia, la cualidad de un objeto o grupo de objetos de sobrevivir al proceso o CPU que los cre. Esto es, los objetos podrn, tras ser usados, ser accedidos todava por otros objetos, pues anidarn en la zona persistente del espacio de almacenamiento unificado. Los objetos transitorios (transient objects) son, en contraposicin a los persistentes, aqullos cuyo acceso no puede garantizarse tras terminar el proceso que los cre y/o us. Y fjese bien el lector: no es que no puedan ser accedidos ocasionalmente, sino que no puede garantizarse en general tal acceso. Tenemos, pues, dos caractersticas que, junto con las zonas de almacenamiento (AP y AP), generan una matriz que puede complicar la vida al programador dependiendo del enfoque que haya adoptado el producto de base de datos. La cuestin depende, bsicamente de la dependencia entre la cualidad de persistencia y la clase de la instancia que se pretende persistente. ORTOGONALIDAD DE PERSISTENCIA Y TIPO La ortogonalidad se refiere, segn el Manifiesto de Sistemas de Bases de Datos Orientadas-a-Objetos, Tokyo, 1.989, a la independencia entre el tipo de un objeto

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 140

y su capacitacin para asumir caractersticas persistentes. Al decir ortogonal se pretende indicar una relacin similar a la de dos ejes perpendiculares en un plano, representativos de distintas dimensiones y, por ende, independientes. La dicotoma queda reflejada en los siguientes distintos enfoques: La persistencia es una cualidad o capacitacin de todas las instancias de una clase o clases dadas: en esta variante un objeto de una determinada clase (de cualquier clase, en un modelo ms amplio pero que aqu no consideraremos debido a la serie de debilidades prcticas que conlleva) automticamente se convierte en persistente al crearse. Digamos que existiran clases (en un modelo restringido, mucho ms flexible) cuya persistencia no merecer la pena y otras cuyas instancias contengan informacin no voltil. En la prctica, un enfoque muy extendido para insuflar la cualidad de persistencia a una clase es hacerla derivar de otra que encierre los mecanismos de persistencia (generalmente denominada Persist o algo parecido). El problema que suele plantear este enfoque es el apuntamiento de objetos desde el AP al AS y viceversa, que se troca muchas veces casi inmanejable en objetos compuestos. Imaginemos, por ejemplo, que nuestra clase Cliente genera instancias persistentes. Pero la clase contiene muchos atributos, pertenecientes, a su vez, a otras tantas clases, algunas de las cuales sern transitorias y otras no. Si, de acuerdo con el esquema flexible planteado, una instancia de Cliente contiene un atributo, verbigracia, apodo de una clase Apodo de tipo no persistente, la vida se va a complicar para el programador: no pueden incluirse para este atributo mecanismos de inicializacin equivalentes a los usados en Bases de Datos Relacionales, pues lo usual es que no podamos controlar si un objeto persistente apuntado (la instancia de Cliente) est en cada momento en una zona transitoria o en una zona persistente, de tal manera que habra que aadir cdigo de comprobacin e inicializacin en cada funcin que intentara acceder al atributo voltil. Pero el problema se agrava cuando tal atributo es accesible mediante una consulta a la OODB. Naturalmente una opcin muy practicada es evitar la mezcla, siquiera en composicin, de clases -y aun de objetos- persistentes y transitorios. Cualquier instancia de cualquier clase puede ser persistente o transitoria: de esta forma no se pretenden incluir mecanismos especficos en la clase, directamente o por herencia, sino que ms bien el sistema gestor se encarga de traspasar o no la cualidad de persistencia merced a comportamientos influenciables por el usuario. Una prctica muy extendida, adoptada por GemStone y O2 entre otros sistemas, es que el sistema conste de unos objetos persistentes predefinidos, de manera que una instancia cualquiera se convertira tambin en persistente si es apuntada por alguno de aqullos objetos. Este esquema, ms complejo que el no-ortogonal, elimina, sin embargo, buena parte de la complejidad de la matriz Espacio de Almacenamiento x Persistencia: si una instancia transitoria de la clase, verbigracia, Persona con identificador miTio se troca en persistente por su inclusin, por ejemplo, en el objeto persis-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 141

tente de tipo agregado con identificador miFamilia, las instancias concretas significadas por variables en nuestro objeto miTio se trocarn tambin en persistentes. La persistencia se perder cuando la instancia deje de ser apuntada por objetos persistentes (cuando, por ejemplo, miTio sea expulsado de miFamilia por crpula). Naturalmente este enfoque es el preferido por los programadores, porque convierte en invisible la gestin de almacenamiento. Desgraciadamente, tambin, sus implementaciones actuales muchas veces no se ajustan a lo requerido. CRTICA DE LA RAZN PRCTICA Bien, bien. Las cuestiones prcticas son: realmente funcionan las Bases de Objetos? Facilitan las tareas de codificacin y, por ende, favorecen la ejecucin de proyectos? La velocidad y eficacia son aceptables? Puedo contar, al menos, con las mismas caractersticas disponibles en el sector relacional? Puedo ... ? S, s, s, s y ... err ... no. La tecnologa anda en buena medida renqueando tras los productos comerciales, as que los esquemas de persistencia, recuperacin de errores, versionamiento, concurrencia, integridad referencial31, etc. dependen del producto en cada caso elegido. Mi experiencia seala que los conceptos que aqu se han apuntado, siquiera someramente, son asimilados con cierta eficacia cuando pueden ejemplificarse aplicndolos a un producto concreto. La comprehensin aumenta cuando los mismos ejemplos se refieren a porciones conceptuales de una aplicacin homognea. As que lo mejor ser emplazar al lector para que use (y abuse) de una Base de Objetos comercial. Bueno: la intencin es lo primordial. INTERNET: CMO NO? Los interesados en las cuestiones aqu esbozadas pueden acercarse por el grupo de noticias de usenet comp.databases.object, excelente punto de partida para novicios, donde encontrarn interesantes discusiones e informacin prctica de uso de productos. Las tpicas preguntas, por otro lado, sobre productos comerciales relacionados con las Bases de Objetos obtendrn su respuesta en la FAQ informal del grupo que, con el calificativo de mini-faq, mantiene y actualiza regularmente Tim Harvey. Yo mismo mantengo, de acuerdo con Tim, una copia de esta mini-faq en http://www.well.com/user/ritchie/mini-faq.html.

31

Incidentalmente cabe notar que, como en otros mbitos, la mejor manera de solucionar los problemas de integridad referencial es precisamente ignorarlos. GemStone, por ejemplo, impide la eliminacin efectiva de cualquier objeto apuntado por otro, posponiendola hasta que el objeto quede totalmente desreferenciado y entre en marcha el recolector de basura.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 142

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 143

9
CONSIDERACIONES PRCTICAS

a generacin de aplicaciones, en su justa acepcin de construccin de modelos representativos de sistemas de informacin con funcionalidad en el mundo real, ha experimentado cambios sustanciales en los ltimos aos debido, sobre todo, a la hiper-influencia de los entornos grficos de usuario que, de forma necesaria pero abruptamente demoledora, han redefinido los roles personales clsicos respecto del uso de los aplicativos software. De esta manera, no se da en la prctica una distincin clara entre programas finales (v.b.: MS Word for Windows), herramientas de ayuda al usuario (v.b.: macros o shortcuts), herramientas verticales de desarrollo asistido (v.b.: wordbasic, el "lenguaje de programacin de MS Word"), etc. La patente exigencia del mercado resulta, por otro lado, meridianamente clara: aplicaciones "amigables" (desafortunada traduccin de "friendly") basadas en sistemas grficos multi-ventanas, apoyados en sistemas operativos o shells con capacidades para compartir, o al menos simular compartir, tareas y procesos. Esta serie de circunstancias, tan sucintamente sobrevoladas, ha conducido a claros desajustes en los esquema de desarrollo que, finalmente, se han asentado sorprendentemente como "estndares implcitos de facto" en la mayora de las empresas de programacin. As, por ejemplo, las herramientas de desarrollo se han transformado (o pretenden hacerlo) en "entornos visuales de desarrollo" (bajo la irnica mirada de los expertos en autnticos lenguajes visuales, cuyas batallas y gestas discurren en la ms alejada ucronia de aqullos) donde los modelos de informacin se unen de forma "flexiblemente indisoluble" (segn afirma una conocida empresa del sector, rea de crimen lingustico-publicitario) y todo resulta "drag-n-drop", "apropiado para RAD" (rapid application development), "idneo para RPD", etc. Hasta aqu pudiera parecer que el autor mantiene una absurda batalla contra los entornos grficos: nada ms alejado de la realidad! En realidad el firmante es un acrrimo defensor de los entornos grficos de usuario (y actualmente de los sistemas WIMP, tan viejos en el tiempo), pues estos tienden (y desgraciadamente en muchos casos slo tienden) a generar aplicativos ms intuitivos en los que la tontera, si realmente la hay, es ms evidenciable. Lo que al fin se lamenta es la falta de normalizacin de estructuraciones bsicas que permitan desarrollos grficos modulares no basados nicamente en su propia y discutible representacin visual

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 144

(sorprende, por ejemplo, constatar que no existen estndares en la confeccin de cuadros de dilogo, en la arquitectura de aplicaciones grficas, en la disposicin de controles visuales, etc.). Se gener, as, lo que Kafka llamaba "El Pozo de Babel" y que, en esencia, es un acopio de procedimientos propietarios en un esquema recolectivo que podramos llamar de "basurero", del que la fuerza del mercado y mayormente de la publicidad rescatan algunos productos, con toda su carga de decisiones y soluciones particularizadas. En definitiva: el nfasis grfico ha llevado a la construccin de aplicaciones (no a todas, afortunadamente) a un punto donde lo que se est viniendo en denominar "ComponentWare" resulta un eufemismo peligrosamente atractivo: los sistemas de informacin se segmentan, bsicamente, as, en una capa modelable como repositorio de informacin (tpicamente mediante un gestor de base de datos relacional -RDBMS) y otra asimilable como front-end que posibilite el acceso intuitivo, cmodo, efectivo y "grfico" a aqulla. Pero, esto no suena mal! Dnde est, pues, ese "grave error" que se desprende del tono de este anlisis? Vemoslo. PANORAMA PARA MATAR Resulta que la construccin eminentemente grfica de modelos de informacin en la actualidad se basa, de forma desproporcionada, en la ligazn entre el interfaz grfico y el interfaz del gestor del repositorio, segn lo expresado en el epgrafe anterior. As, por ejemplo, un caso tpico de esta dicotoma se refleja en la opcin de uno de nuestros clientes, con una facturacin anual de ms de $30,000,000, al decidir originariamente soportar con front-ends en "Visual Basic" la informacin tabular gestionada por "Oracle". Los "campos" grficos se convierten, as, en espejo rgido de los "campos" tabulares de la base de datos relacional: campos para introducir fechas, campos para introducir nmeros, campos para introducir decimales, etc. La mayora de herramientas CASE tradicionales (y aun de 4Gs), con extensiones a objetos o no, recaen en este mismo esquema. Naturalmente esto facilita la automatizacin de la produccin de cdigo, pero imposibilita, por otro lado, la reutilizacin del mismo (tanto del modelo como del interfaz grfico): un interfaz devendr inservible cuando cambie la estructuracin interna de la informacin que mantiene, a la vez que es posible que un cambio en el interfaz signifique una modificacin de los componentes tabulares a los que accede. Veamos con ms detenimiento algunos ejemplos de tal constrictora ligazn: La propia arquitectura inducida en los aplicativos software por los sistemas grficos, usualmente restringida a esquemas monomodales, origina graves desajustes en la concepcin de la representacin del sistema de informacin a modelar: la secuencialidad (o la ilusin de secuencialidad) inducida por el esquema grfico soportado origina la necesidad de construir enlaces (links) entre estructuras de datos, de manera que stas puedan "comunicarse" (la profusin de vocablos "en-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 145

trecomillados" no es en absoluto casual, como el lector habr ya adivinado), producindose el curioso efecto de que las deficiencias de la arquitectura grfica ocasionan deficiencias en la informacin que sus componentes manejan, lo que a la vez provocar un rediseo cada vez ms pernicioso de los mismos interfaces grficos, que repercutir de nuevo en la estructuracin interna de la informacin, y as hasta ... que el "schedule plan" obligue al lanzamiento del producto. En realidad los enlaces que se generan son tan frreos que las aplicaciones resultantes suelen ser "monolticas", proporcionando una apariencia de diversidad similar a la que tiene un recluso cuando, el primer da, recorre su celda en la oscuridad. REFLEXIONES REBAJADAS Existe una solucin global para los problemas y deficiencias expuestos? No, por supuesto! An ms: se dira que en absoluto es deseable un blsamo de fierabrs que restae y cure todo lo curable, en lo que a software se refiere. Es difcil pensar que la diversidad natural, difcilmente asimilable en su completitud, de los sistemas de informacin pueda ser simplificada en un nico esquema mecanicista. Lo que se pretende, al fin, con este modesto captulo, es explicitar una serie de criterios, decisiones y esquemas estructurales que habran de conformar las bases estticas y de comportamiento dinmico de un grupo mayoritario de sistemas software, teniendo en cuenta que, puesto que tales circunstancias normalmente sern presupuestos de migracin entre tecnologas (usualmente de RT a OOT), se habr de ponderar ms la inmediata practicidad tangible que la formalidad huera del efectismo tecnolgico, de dudosa utilidad en relacin con una aproximacin conscientemente simplificada cual es la presente. A fin de facilitar la comprensin de las ideas arquitectnicas propuestas, stas se expondrn en epgrafes en buena medida autosuficientes, a la vez que los ejemplos de aplicacin se presentarn en C++, intentando proporcionar un asidero prctico de aplicacin de lo en cada caso expuesto: Distribucin Jerrquica Csmica de Clases El esquema jerrquico de clases del sistema a modelar se entender directamente csmico: esto es, todas las clases derivarn de una clase base especial para la aplicacin y tambin para el propio cliente y sus futuros desarrollos. Se trata de la clase BaseObjeto, que implementar estados y comportamientos comunes, a la vez que forzar la adecuacin de todas las clases a ciertas funcionalidades (mediante funciones virtuales y funciones virtuales puras). Tal clase permitir, tambin, estructurar de forma adecuada el polimorfismo de vistas, en el ms puro estilo Smalltalk. Un esquema de clases no-csmico, o multibase, podra haber resultado mucho ms elegante, pero hubiera conllevado, tambin, el enfrentamiento con problemas de codificacin que requeriran un conocimiento no-trivial (por no decir extremadamente pulido) del lenguaje de programacin (C++) y del

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 146

paradigma aplicado de orientacin-a-objetos, no aportando, empero, ninguna caracterstica adicional de efectividad o seguridad en proyectos tpicos de migracin (en realidad el firmante trabaja casi siempre con esquemas no csmicos y hace uso intensivo de la herencia mltiple, pero tal no es de pedaggica aplicacin aqu). El Paradigma M2VC La arquitectura del sistema se basar en una matizacin del paradigma MVC que denominaremos M2VC. En primer lugar atendamos a lo que MVC (siglas de Model View Controller) significa: se trata de la separacin de los mdulos de un sistema software en tres capas: la del modelo, la de la vista y la del controlador, interactuando de la siguiente forma: un objeto perteneciente a la capa del modelo slo puede ser accedido por un objeto perteneciente a la capa de la vista, que, a su vez, enva y recibe mensajes del objeto controlador. Existe un objeto controlador por cada aplicacin activa, y es tal objeto el encargado de transformar las arquitecturas subyacentes en estructuras orientadas-a-objetos, trocando las llamadas a funciones y eventos en mensajes comprensibles para las vistas. Aunque el paradigma MVC se ha demostrado enormemente eficaz, no existe ninguna exposicin terica del mismo que sobrepase, en esencia, las sucintas notas anteriormente expuestas, aunque s se pueden examinar multitud de sistemas basados en el mismo. En realidad el enfoque MVC fue el adoptado, de facto, por Smalltalk-80, y aparece omnipresente en los trabajos de Adele Goldberg y Alan Kay. Este paradigma facilita sobremanera la independencia de un objeto respecto de su representacin visual o interfaz con los usuarios, de forma que tales interfaces podran variarse sin afectar apenas a la estructura de la aplicacin. La nica desventaja que tal enfoque presenta es, a nuestro juicio, que las vistas son jerrquicamente anteriores a los objetos, de forma que no se producen llamadas a objetos, sino a vistas que a su vez llaman a objetos: esto obliga a que, si se cambia un interfaz, deba modificarse el cdigo de la llamada al mismo en la aplicacin. Para solventar esta situacin hemos decidido aplicar una matizacin de este enfoque que nosotros denominamos M2VC. Se trata, en definitiva, de que las llamadas a las vistas las gestiona el objeto en s. De esta manera, todos las clases tienen acceso a una funcin miembro que genricamente denominamos "dialog()" o "dialoga()", que se hace "virtual" en la clase base csmica "BaseObjeto" y que permite acceder al interfaz apropiado de cada objeto con independencia del conocimiento de su tipo exacto. As, el cuerpo tpico de tal funcin en una clase dada responde al siguiente esquema:
miClaseModelo::dialog() { new DlgClaseModelo( controlador->getFocus(), this ); }

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 147

Esto es, se crea un objeto de tipo vista (derivado, en nuestro caso, de BaseDialogo), no persistente, al que se la pasa como parmetros la vista que actualmente retiene el focus en el entorno grfico (para poder "ahijar" la nueva vista), adems de un puntero al mismo objeto del modelo para que la nueva vista lo pueda asimilar como el puntero al modelo que se cita en el epgrafe Gestin de Objetos a travs de Vistas. La ventaja de esta matizacin es que si se cambia la vista a travs de la que se accede a un objeto de una clase dada, nicamente habr que cambiar la implementacin de tal clase, sin tocar en absoluto el cdigo de la aplicacin. Y aun, en un esquema de "Constructores Virtuales" de vistas, ni siquiera habra que cambiar la implementacin de la clase modelo, sino aadir un nuevo objeto esttico de tipo vista a la cadena de vistas asociada a una clase dada, aunque este ltimo enfoque es excesivo para una primera aproximacin a C++/OOP/OODB. El enfoque M2VC conlleva, como lgica consecuencia, una mayor facilidad en el tratamiento del interfaz de los objetos, pues estos pueden ser accedidos a travs de un puntero al objeto con independencia del conocimiento exacto de su tipo. De esta manera se puede iterar por una coleccin de objetos de distinto tipo y hacer aparecer, de forma polimrfica, el interfaz en cada caso apropiado. De hecho, usualmente los mens conducen a objetos de tipo agregado (derivados de BaseColeccion), que llaman a su propio interfaz de tipo contenedor, a travs del que se accede a los objetos "simples" y, por ende, a sus interfaces pertinentes. Pero esto ser examinado en ms detalle en el epgrafe Gestin de Objetos mediante Colecciones. Arquitectura Grfica MultiModal Existen dos tipos bsicos de arquitecturas en sistemas software respecto de la secuencialidad o no de los procesos (o mensajes o eventos) que conforman y caracterizan a las vistas respecto del entorno en que se apoyan. Se trata, abusando de los barbarismos, de arquitecturas "modales" y "nomodales" (o mejor, multimodales). La aproximacin modal se basa en la estricta secuencialidad temporal de la focalizacin de los interfaces grficos (denominaremos en adelante interfaces grficos a las vistas en general, aunque stas pudieran ser construidas en entornos textuales o, en un mbito ms amplio, pudieran ser esencialmente multimedia): esto es, cuando una vista aparece en la pantalla, todos los eventos y mensajes son necesariamente dirigidos a ella, de forma que los mensajes al resto de las vistas son ignorados o, a lo sumo, procesados de forma uniforme (un pitido, una condicin de error, etc.). Esto significa que el focus de la aplicacin no puede traspasarse de una vista a otra de forma voluntaria. Examinemos brevemente, para esto bien entender, la sustancia comn que anima la construccin de vistas en entornos grficos: una vista no puede crearse de la nada, sino que forzosamente ha de depender de una vista anterior que, como la razn ltima de las cosas del de Aquino, finalmente ha de ser el entorno grfico en s. Naturalmente esto no es un modelo terico, sino ms bien una imposicin prctica que facilita

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 148

la gestin de vistas. Naturalmente, tambin, podra haberse obviado tal aproximacin y trabajar con un esquema dinmico (y voluntario) de dependencias, pero la realidad es que el primer esquema permite montar, como una mera disgresin o curiosidad, el segundo, de forma que no hay contradiccin ni solapamiento: nicamente comportamiento prctico por defecto. De esta manera existe una vista que calificamos de Vista Principal de la Aplicacin y que directamente depende del entorno grfico elegido en s. Esta Vista nica (de acuerdo con las normas CUA) contiene mens desplegables y se constituye en "padre" de todas las dems vistas de la aplicacin, con el siguiente esquema: cualquier vista creada directamente desde la Vista Principal mantiene a sta como "padre" y la vista en cuestin pasa a ser la "hija" de aqul (quiz en un entorno menos masculino deberamos hablar de "madre" e "hijo", o de "progenitor" y "progenie", pero en este caso dejaremos que el lenguaje, con sus gneros y traducciones, nos arrastre). As, repetimos, la Vista Principal produce Vistas Primeras, directamente dependientes de aqulla; pero stas, a su vez, pueden generar Vistas Secundarias (las adjetivaciones de las vistas son, por supuesto, nicamente pedaggicas), y stas generar otras, y as ad nauseam (o hasta que "se acaben los recursos", segn rezan algunos inopinados mensajes de ciertos entornos grficos -lisez MS Windows). De esta manera resulta que, puesto que cada "padre" conoce a sus "hijas", stas habrn de conocer a su "padre" (notnse las caractersticas educacionales y canallescamente sociales de esta asercin). En un entorno grfico nicamente una vista puede retener el focus en un momento dado: esto significa que siempre hay una nica vista localmene activa: o sea, los mensajes que dirijamos al sistema se "focalizan"" sobre la vista activa y de sta se dice que "retiene" o posee el "focus" (foco, en un castizo menos latino). Los mensajes a otras vistas son generalmente, pues, ignorados o sobreestimados. La aparicin de una nueva vista (siempre dependiente de una anterior, o "padre") origina que el focus se traspase a sta, as como la misma podra automticamente traspasarlo a otra de la que dependa. En un arquitectura modal el focus es retenido por una vista mientras no se destruya (con lo que el focus pasara automtica al "padre" del que depende) o cree una vista depeniente a la que traspasarlo. A efectos de codificacin esto significa que si en una lnea del programa se produce una llamada, directa o indirecta, a una vista derivada, sta asumir el focus y no lo devolver a la vista en que se produce la llamada hasta que desaparezca. Naturalmente esto sugiere e invoca una inevitable secuencialidad en el esquema de mensajes entre vistas (y aun entre objetos). Significa, tambin, que la secuencialidad del cdigo es absolutamente determinista: esto es, tras la lnea que llama a la vista (en un ejemplo tpico con C++):
void ClaseCualquiera::llamaAVista() { DialogoCualquiera* miDialogo = new DialogoCualquiera();

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 149

el control indefectiblemente, tras la desaparicin del dilogo, pasar a las siguientes lneas, que podran perfectamente ser las siguientes:
// extrae informacin del objeto miDialogo delete miDialogo; }

de tal manera que se podra interrogar al dilogo por los objetos o estados de stos que nos interesen. Este esquema fuerza un tipo de codificacin demasiado basada en las dependencias casuales entre los distintos tipos de vistas. Obliga, tambin, por su propia naturaleza basada en dependencias jerrquicas, a cancelar una vista para poder acceder a otras o, en el peor de los casos, a incluir en una vista controles grficos que permitan acceder a otra nueva vista sin cancelar la primera. Por supuesto que esta ltima estrategia, usada de forma intensiva por la prctica totalidad de las empresas de desarrollo de software, es particularmente nociva y origina con demasiada facilidad vistas o interfaces en absoluto reutilizables fuera del contexto para el que fueron creados. Qu ofrece, por otro lado, el enfoque multimodal? Pues sencillamente la posibilidad de traspasar voluntariamente el focus desde una vista a otra cualquiera, actualmente visible o no (normalmente mediante el uso del ratn, pero tambin del teclado u otros medios). Esto causa que los interfaces no habrn de depender de las relaciones que entre ellos se establezcan dinmicamente, reforzando, al descontextualizar su uso, la reutilizabilidad prctica de los mismos. Se derivan, a la vez, nuevas e importantes consecuencias con respecto de la secuencialidad del cdigo: una lnea tpica de llamada a una vista (en C++) sera la siguiente:
void ClaseCualquiera::llamaAVista() { new DialogoCualquiera(); }

y aqu se aprecian modificaciones evidentes: no hace falta identificador de la vista, ni se procede a su destruccin, como tampoco a su chequeo a efectos de extraer informacin sobre los objetos que tal vista ha manejado. Hay que pensar que tras la ejecucin de la lnea en la que -en este caso- se crea la vista simplemente no ocurre nada secuencialmente previsible. Esto es, la vista se crea -en nuestro caso- y literalmente "se abandona" para que interacte, de la forma ms adecuada, con otros objetos de tipo "Vista". Pero, segn vemos, la memoria necesaria para la construccin de la vista se asigna dinmicamente: quin se encargar, pues, de desasignar tal memoria? La propia vista, claro est! El esquema es el siguiente: una Vista Padre crea una Vista Hija y, como en los peores folletines (y tambin en los mejores), la abandona a su suerte en un mundo con vistas de todo tipo, calaa y condicin. El usuario, como metaobjeto de la aplicacin, se convierte, as, en el nico responsable de que tal o tales vistas permanezcan o no en su terminal, pudiendo en cualquier momento optar por su eliminacin o destruccin

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 150

concreta o por una ms general desasignacin (el cierre de la aplicacin entera). As, el cdigo de destruccin de una vista estara -naturalmente- escondido en el destructor de sta (y volvemos a la nomenclatura C++), de la forma:
DialogoCualquiera::~DialogoCualquiera() { // desasigna la memoria dinmica // asignada en el constructor }

Pero, quin llama a este destructor? El usuario! Esto es: el usuario manda un mensaje a la vista requiriendo su desaparicin bien directamente (lanzndole un mensaje "cirrate" o "close"), bien indirectamente (lanzando un mensaje "close" a cualquiera de sus padres o accionando una operacin de la misma -tpicamente "aceptar" o "cancelar"-). o aun lanzando una orden de cierre masivo de vistas (como la procurada por el cierre de la aplicacin). Naturalmente el esquema antes apuntado se mantiene, y, por ende, cualquier Vista conoce a sus hijos (mantiene, en definitiva, una coleccin de punteros a los mismos, en lenguaje coloquial o de programador). Bien: no hay problemas con la memoria, pero se plantean dos nuevas cuestiones: qu ocurre con los objetos que una vista ha gestionado, ledo y/o modificado? qu ocurre, por otra parte, cuando en una vista se leen o modifican objetos o algunos de los atributos de estos que, a su vez, estn siendo ledos y/o modificados por otras vistas, o aun por otras vistas en otros terminales o clientes? Bien, esta ltima cuestin es oportunamente tratada en el epgrafe dedicado a la Gestin de Concurrencias, mientras que la respuesta a la primera perfectamente corresponde al esquema multimodal como solucin aplicativa, pero ser tratada en detalle en el epgrafe dedicado a la Gestin de Objetos a travs de Vistas. Y este es el momento de anunciar que el "multimodo" es, de hecho, una generalizacin del comportamiento "modal", por lo que lo establecido para aqul puede perfectamente ser aplicado en ste, aunque no a la inversa. Gestin de Concurrencias El esquema de control de concurrencias se basa en que cada usuario de un objeto o grupo de objetos, identificado por el acceso nico al interfaz de stos, trabajar con un conjunto intermedio de punteros a los objetos de la base de objetos en cada caso manejados. Se trata, en definitiva, de una "shallow copy" (copia superficial) de los objetos en cada caso utilizados por el usuario (naturalmente esto incluye objetos simples a la vez que colecciones y, en general, objetos de tipo agregado). Se trata, por tanto, de que cada interfaz, en correspondencia biunvoca con el usuario nico que lo accede respecto del terminal en que anida, utiliza un objeto intermedio del mismo tipo que el objeto al que se intenta acceder, teniendo en cuenta que se trabaja en un entorno grfico multiusuario y multimodal. Los casos posibles son: un objeto simple (que puede contener enlaces navegacionales a otros objetos) y una coleccin, o agrupacin de objetos (simples o co-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 151

lecciones a su vez). En cualquiera de los casos, en orden a la arquitectura grfica elegida (el paradigma matizado M2VC), tales objetos intermedios sern manejados nicamente por las vistas (interfaces grficos de los objetos correspondientes), pudiendo ser o no persistentes, aunque una elemental prudencia inicial aconseja su inclusin en la memoria transient, toda vez que este sistema no necesita de persistencia de objetos intermedios para recuperar fallos en el sistema. Veamos los comportamientos por separado: Acceso a un objeto simple: El interfaz partir directamente con el puntero al objeto que forma parte de su representacin interna o que, en algunos casos, se pasa como parmetro al objeto (normalmente por medio de su constructor), pero, como se detalla en el epgrafe dedicado a la Gestin de Objetos a travs de Vistas, se generar una copia temporal. Como quiera que se trabaja en un entorno multimodal y, por ende, el focus no se retiene necesariamente por la vista, esto significa que mientras que se trabaja con la lectura esttica, traspasada a los controles, de los atributos del objeto accedido, ste podra estar cambiando en otra vista, en el mismo terminal o en otro distinto. La poltica a aplicar ser simplemente que la ltima modificacin es la que vale, con independencia del esquema de refrescos o posibles actualizaciones de la informacin respecto del interfaz en que aparece. Acceso a una coleccin (objeto de tipo agregado): El interfaz trabajar directamente con un puntero al objeto de tipo Coleccion al que se quiere acceder, pero los accesos se realizarn mediante una coleccin intermedia, cuyo funcionamiento se detalla en el epgrafe Actualizacin de Vistas, que conservar la biunivocidad del orden con respecto del control de la vista (tpicamente listboxes o comboboxes) en que se visualizan los objetos contenidos en la misma. En tal coleccin intermedia se insertarn los punteros a los objetos que se deseen manejar, y, a la vez o iterando en una secuencia posterior, se pasar la representacin visual de cada uno de ellos al control apropiado de la vista, de forma que, por ejemplo, el undcimo tem en una combobox siempre habr de corresponder al undcimo objeto contenido en la coleccin ordenada intermedia. Para la modificacin de cada uno de los objetos individuales que la coleccin contenga se llamar al interfaz particular de stos y se seguir el esquema observado en el prrafo anterior sobre el acceso a objetos simples. La insercin o borrado de un objeto en la coleccin original no afectar, pues, a la relacin biunvoca entre el control grfico y la coleccin intermedia. Los dos casos detallados ofrecen, empero, un problema relacionado con el borrado de objetos: qu ocurre si se intenta acceder mediante el puntero que maneja una vista a un objeto que ha sido fsicamente borrado por mediacin de otra vista. Bien, este caso simplemente no se puede producir. Veamos el esquema:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 152

Eliminacin de objetos: en ningn caso se producir la eliminacin fsica directa de los objetos persistentes, sino que se utilizarn recolectores de basura (garbage collectors) a aplicar sobre objetos desreferenciados. Esto supone que el acceso desde una vista a un objeto (va puntero) est siempre garantizado, pues al ser apuntado precisamente por la vista tal objeto no puede desaparecer, manteniendo a la vez la posibilidad de que el mismo objeto pueda ser aparentemente borrado o apartado del interfaz accesible por un usuario dado o un conjunto de stos. Cmo se consigue sto? Se pueden dar dos casos: si el objeto est en una coleccin de uso, se procede a su extraccin de la misma desde el interfaz de sta y se deposita bien en el extent (para su posible reutilizacin ulterior) bien en una coleccin genricamente denominada "basurero" (de la que ser fsicamente eliminado cuando quiera que ningn otro objeto lo referencie); si el objeto est nicamente en el extent, la eliminacin consistir en su insercin (en la insercin de un puntero que lo apunte) en un objeto "basurero". Naturalmente la eliminacin aparente o no de un objeto generar una incidencia interna auditable, segn se detalla en el epgrafe Incidencias de Usuarios. El principio de "la ltima modificacin es la vlida", como ya se ha expresado, puede ocasionar disfuncionalidades inesperadas en el acceso a distintos objetos (es posible, por ejemplo, que un usuario est modificando un objeto y su vista sea anterior a la ltima modificacin realizada por otro usuario, de forma que al concluir el proceso, se estar sobrescribiendo una modificacin que ni siquiera se ha visualizado). Por eso, opcionalmente, se propone un sistema alternativo al de bloqueos que pueda manejar adecuadamente la concurrencia de usuarios sobre un mismo objeto. La idea bsica es que, como quiera que un interfaz puede tener tres niveles de acceso, segn lo expuesto en el epgrafe de Seguridad del Sistema, este sistema de concurrencia ser aplicado por las mismas vistas (dilogos derivados de BaseDialogo) nicamente cuando alguna de ellas acceda a un objeto en modo "total" (esto es, con posibilidad de escritura o modificacin). El sistema de indicadores (o "flags", en un acertado barbarismo onomatopyico) realmente no funciona, pues en caso de que se marque un determinado objeto como bloqueado, si la aplicacin en la consola del usuario bloqueador termina abruptamente, el objeto en cuestin seguir marcado. Nuestro enfoque es matizadamente distinto: se trata de que cuando una vista tenga acceso "total" a un objeto, tal objeto se insertar en una BaseColeccion que se podra denominar "BloqueosActivos", pero tal coleccin no ser persistente, sino que anidar en la base de objetos global "transient" (o transitoria, en desafortunada traduccin). De esta manera cada vez que una vista acceda a un determinado objeto, chequear primero si el tal objeto se encuentra contenido en "BloqueosActivos", y si es as impedir el uso de la funcin "set(...)" sobre el mismo. Hara falta, de esta manera, codificar nuevas funciones y datos miembros en la clase base "BaseDialogo" de la siguiente guisa:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 153

class BaseDialogo : public Dialog { public: boolean estaBloqueado( BaseObjeto*, long = 0 ); private: // coleccin de objetos bloqueados en // la OODB transient (en memoria primaria) BaseColeccion* bloqueosActivos; // sigue resto descripcin de clase }; boolean BaseDialogo::estaBloqueado( BaseObjeto* modelo, long insistir ) { if (bloqueosActivos->contiene( modelo ) ) { if (!insistir ) { VReport::warning( "Objeto Bloqueado", this, "Este objeto est bloqueado\npor otro usuario."); return FALSE; } else { // activar "timer" para que cada n segundos // reintente la llamada hasta un nmero x // de iteraciones, o bien llamar de nuevo // recursivamente a la funcin de chequeo de // bloqueos hasta un cierto lmite. } } else return TRUE; }

As en cada vista, adems de habilitar o deshabilitar ciertos controles o botones en razn del acceso del usuario en cada caso pertinente (desactivar los botones de modificacin o eliminacin en el caso de acceso "soloLectura" ), la mera llamada a la funcin set(...) de cada objeto del modelo ser sustituida por la siguiente condicin:
if ( estaBloqueado ( BaseObjeto* ) ) modelo->set(...);

a la vez que en el constructor de la vista se aadirn las lneas:


// "modelo" es el puntero al objeto que gestiona la vista if ( usuario->nivelAcceso( this ) == total && !estaBloqueado( modelo ) ) bloqueosActivos += modelo;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 154

pudindose sustituir la doble condicin por una funcin nica en la clase base "BaseDialogo", de la misma forma que se ha hecho con la funcin "estaBloqueado( BaseObjeto* )". Este es, a nuestro parecer, el enfoque menos intrusivo, pues no afecta al modelo de la aplicacin, sino nicamente a las vistas que lo manejan. Gestin de Objetos a travs de Vistas Una Vista contiene una referencia (puntero, en C++) al objeto que habr de manejar, acceder, leer o modificar, siempre mediante el interfaz pblico de ste. De esta manera tenemos un cdigo similar al siguiente:
class DialogoCualquiera { private: ObjetoCualquiera* punteroAlObjeto; // resto representacin interna dilogo };

donde la lectura se realizara siempre por medio de una funcin que, por razones que se evidenciarn en el epgrafe Actualizacin de Vistas, denominaremos "refresca":
void DialogoCualquiera::refresca() { // editLineN son miembros privados de tipo EditLine // y representan campos grficos de edicin de textos editLine1->putText( punteroAlObjeto->getAtributo1() ); editLine2->putText( punteroAlObjeto->getAtributo2() ); // etc., etc. }

mientras que los accesos para modificacin (y aqu se obviarn los aspectos relacionados con la concurrencia, como se ha hecho respecto de la lectura) se codificarn en las funciones (callbacks) a ser llamadas como resultado de la accin sobre un elemento grfico (tpicamente un botn):
void DialogoCualquiera::callbackOkButton() { punteroAlObjeto->set( /* actualizacin de atributos */ ); // termina el dilogo y pasa el objeto // al dilogo padre getParent()->admite( punteroAlObjeto ); }

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 155

Pero este simplificado esquema origina una grave dificultad: como se ha visto la actualizacin del modelo (objeto) al que apunta cada vista (aunque tambin se pueden dar vistas multimodelo, sin que en absoluto cambie el esquema de actuacin) se realiza mediante una funcin, usualmente denominada set(...), que efectivamente cambia los atributos (o datos miembros) del objeto apuntado. Pero, en el caso ms general, posiblemente una vista dependa de otras vistas "padres" de sta, de manera que un cambio en el estado del objeto (u objetos) que la vista maneja haya de ser validado por cualquiera de los objetos apuntados por una o ms de las vistas "padres", y si en algn caso tal validacin resultara negativa, los cambios habran devenido irreversibles, por lo que el sistema se encontrara con un cul de sac de sesgada solucin. Imagnese, por ejemplo, que una Vista es el interfaz de una coleccin de HombresCuyoNombreEmpiezaPorX, y que de tal deriva (o se ahija) una vista que modela objetos del tipo HombreCualquiera. Si en esta ltima vista se cambian los atributos de un determinado HombreCualquiera, perteneciente originariamente a la primera coleccin, y el nuevo atributo de nombre, ya irremediablemente cambiado, no empieza por X, la vista que accede a la coleccin rechazar la insercin o actualizacin de tal objeto en la coleccin y no podr, por otro lado, recuperar el antiguo nombre, producindose un deadlock (bloqueo mortal, en la ms pura tradicin hollywoodense) cuya posible resolucin ser naturalmente oscura para el usuario. Cmo evitar esto? Pues estableciendo un mecanismo que permita el "backtracking" o vuelta atrs a partir de una modificacin de atributos (esto es, un acceso de tipo escritura, siguiendo la ms tradicional nomenclatura de gestores de bases de datos). Tal mecanismo puede implementarse, bsicamente, mediante las tres formas distintas siguientes (o, por supuesto, por cualquier combinacin de ellas): versionamiento (versioning) transacciones anidadas (o bloqueos anidados con roll-back) copias temporales de trabajo Las transacciones anidadas no son de aplicacin, a estos solos efectos, en un entorno multimodal, pues dado que el focus puede traspasarse de una vista a otra dejando a aqulla activa ab aeternum, las transacciones (o cualquier otro esquema de bloqueo, conjuntado o no) deberan mantenerse durante ms tiempo del prudentemente deseable, y adems hacerse extensivas a los hijos de una vista dada, incluyndolas normalmente como inicio en el constructor de la vista y como final en el destructor de la misma, pues tal sera la nica forma de que en un momento dado se pudiera realizar un "roll-back" y devolver los objetos a su estado anterior a las modificaciones realizadas. De hecho, el sistema de bloqueos globales desde vistas no puede funcionar bien en un esquema multimodal, y su uso industrial se restringe, salvo expresas necesidades, a los entornos modales, de previsible secuencialidad.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 156

El versioning representa un esquema general que incluye, como concrecin, el de las copias temporales de trabajo y, por tanto, parece el ms adecuado para gestionar "versiones temporales" de objetos, que en cualquier momento pueden "olvidarse" (forget) o, ms bien, sustituir de forma efectiva a la anterior (aunque sin perder la informacin de partida). El versioning, empero, necesita de unos gestores tpicamente imbricados con bases de objetos, de manera que no es naturalmente accesible desde el modelo relacional, y a pesar de resultar la opcin ms elegante, clara y rpida, como quiera que obligara al uso de determinadas herramientas de implementacin y restringira, a efectos prcticos, los resultados del diseo, hemos optado por considerar como eminentemente prctica la ltima opcin: copias temporales. Cul es el funcionamiento de las copias temporales, cundo tal esquema ha de aplicarse y qu objetos lo gestionarn? Vayamos a ello: nicamente hace falta una copia temporal por cada objeto que se est manejando en un momento dado, lo que equivale a afirmar que se necesita, al menos, una copia temporal de cada objeto accesible desde cualquier vista activa. Esto inmediatamente sugiere que no es responsabilidad en s del objeto original mantener un tal sistema temporal, sino ms bien de las vistas que actualmente lo acceden. De esta manera resulta que ser la vista la que, en una secuencia ms de su construccin (y ntese que estamos siempre hablando de vistas no-persistentes) crear un objeto temporal del mismo tipo de cada objeto que maneja y copiar en l sus mismos atributos (presumiblemente, en C++, mediante un constructor de copia o por la sobrecarga de un operador de asignacin, o por la aplicacin de una funcin virtual de clonado). El cdigo sera el siguiente:
DialogoCualquiera::DialogoCualquiera() { // asigna valores iniciales a atributos de la vista // seguidamente crea un objeto temporal punteroObjetoTemporal = punteroAlObjeto->clone(); // sigue resto constructor vista }

De esta manera se sobreentiende que cada vista poseer como atributos (como datos miembros privados, en C++), aparte del puntero a los objetos que maneje, de acuerdo con el paradigma MVC, sendos punteros a los objetos temporales que se clonen a partir de stos, de forma que puedan ser accedidos desde cualquier lugar dentro del protocolo de descripcin de la clase y con una formalizacin similar a la siguiente:
class DialogoCualquiera { private: BaseObjeto* pObjetoOriginal; BaseObjeto* pObjetoTemporal;

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 157

// sigue resto descripcin clase };

Pero esto plantea un nuevo problema de eficacia: una copia por objeto es razonablemente efectiva y no supone penalizacin en tiempo de ejecucin, siempre que el objeto a copiar no sea de tipo agregado. Esto es, el sistema de copia funciona mientras que se aplique a objetos simples y no a colecciones, pues en stas se producira una copia de cada uno de los objetos contenidos en la coleccin, y tal es simplemente aberrante. Quiere esto decir que, al no usar de objetos temporales, no hay posibilidad de roll-back en colecciones? Efectivamente! Y, de hecho, ste es el esquema general normalizado en entornos grficos ( y bien se dice general porque podra darse el caso de una aplicacin concreta del esquema de copia en colecciones de nmero determinado y corto de elementos, pero tal no sera sino lo mismo que aplicar las copias a una secuencia tambin bien determinada y corta de objetos manejados por una vista). En resumen: las copias temporales slo se aplicarn a objetos simples de tipo no-agregado. Hay que tener en cuenta, no obstante, que usualmente una vista manejar un solo objeto del modelo, de forma que las colecciones las manejarn vistas especializadas, mientras que el acceso a los objetos concretos contenidos en la coleccin se realizar mediante vistas tambin especializadas para los mismos: no hay, pues, solapamiento de esquemas. Cada vista conoce, pues, por su propia especializacin, si ha de aplicar o no el esquema de copia. Situndonos de nuevo en la copia temporal de objetos simples (no-agregados no-colecciones), cul ser el esquema de modificacin de un objeto dado? Como anteriormente vimos, la lectura de los atributos del objeto a manejar (y ntese que el singular se aplica aqu como mera salvaguardia pedaggica) se realiza mediante una funcin virtual refresca() de la vista, que simplemente lee tales atributos a travs de funciones miembros del objeto accedido mediante su puntero, dato miembro privado de la vista, y los copia, usualmente como cadenas de caracteres, en los controles de la vista (tpicamente editlines, editboxes, comboboxes, etc.). El usuario con perfil suficiente podra, a partir de aqu, modificar las cadenas de caracteres de los controles, previendo, de forma transparente, una modificacin de los atributos del objeto de los que tales son espejo. Naturalmente tales modificaciones en los atributos habrn de producirse en el Objeto Temporal, y nunca directamente en el Objeto Original, pero caben dos distintos esquemas: bien que tras la edicin de cada control se produce un cambio en el atributo afectado, bien las modificaciones se producen de forma global al accionar un determinado control (tpicamente el botn "aceptar" u "OK"): cul aproximacin es la idnea? La primera de ellas necesitara que el objeto dispusiera de una funcin miembro pblica especfica para la modificacin de cada atributo y generara un inelegante y complejo rosario de funciones, a la vez que supondra captar, en un prolijo esquema, las pulsaciones de teclas, los cambios de focus, etc., de manera que las actualizaciones se realicen de la forma intuitiva esperada; la segunda, en cambio, necesitara del objeto a modificar nicamente una funcin pblica, usual-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 158

mente denominada set(...), que sera llamada tras pulsar el botn adecuado, como por ejemplo:
void DialogoCualquiera::aceptar() { pObjetoTemporal->set( atributo1, atributo2, atributo3 ); // ... }

la cancelacin, por otro lado, nicamente causara la salida del dilogo sin haber llamado a tal funcin. Parece evidente, as, que la modificacin de atributos resulta ms elegante, clara e intuitiva mediante el esquema de modificacin global. Pero si la modificacin se produce al final, y pinsese que el comportamiento esperado (que no normalizado, desafortunada o afortunadamente) de un tpico botn "aceptar" es que la vista se cierre, por qu no aplicarla directamente sobre el objeto original? Pues, bsicamente, porque el proceso de validacin depender, de acuerdo con los presupuestos arquitectnicos en que se basa la presente aplicacin, del objeto, jerrquicamente anterior, que posibilita la modificacin de ste: se aplica, as, el comportamiento notado anteriormente sobre colecciones y reflejado en el ejemplo "HombresCuyoNombreEmpiezaPorX". Pero, si no se produce validacin, qu ocurre cuando se cierra el dilogo? Pues que tal vista (dilogo) habr de "enviar" a la vista "padre" desde la que se gener el par compuesto por el ObjetoOriginal y el ObjetoTemporal, de forma que sta, tras acceder al modelo al que a su vez apunta, pueda decidir si se produce o no actualizacin de los atributos conforme a lo requerido por el usuario, o ms bien se cancela tal modificacin y se notifican al usuario los problemas encontrados. En C++, la codificacin se parecera a la siguiente:
void DialogoCualquierHijo::aceptar() { pObjetoTemporal->set( /* lista de atributos */ ); // getParent() devolvera un puntero a la vista padre // mientras que parDeObjetos(...) sera, tpicamente, // la instanciacin de una plantilla del tipo // par< class T, class T >, // o tambin una coleccin de dos elementos getParent()->admite( parDeObjetos( pObjetoOriginal, pObjetoTemporal ) ); }

mientras que en la vista padre encontraramos:


void DialogoCualquierPadre::admite( ParDeObjetos* par ) // compara los objetos contenidos en el par: // si ambos son iguales (lo que significa // que no ha habido modificacin) // o la copia est en blanco (se ha producido {

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 159

// una cancelacin) // entonces simplemente no hace nada // y luego destruye el temporal if ( !( par.sonIguales() ) && !( par->getCopia()->esBlanco() ) ) // si los objetos son distintos entonces // chequea la validez de las // modificaciones realizadas en el temporal (o copia) if ( chequea( par->getCopia() ) ) // y si el chequeo es vlido, entonces // copia los atributos del objeto // temporal en el original (suponemos definido el operator=) getOriginal() = getCopia(); // se destruye despus el objeto temporal delete getCopia(); // seguidamente realiza con el objeto original ya modificado // las acciones pertinentes, como por ejemplo su insercin // en una coleccin dada, de la forma: // miColeccion |= getOriginal(); }

Como fcilmente se aprecia, buena parte del cdigo (y por ende, del comportamiento) aqu mostrado sera comn para todas las vistas, de manera que se podra, y de hecho as se har, traspasar a la clase base de todas las vistas: BaseDialogo, mientras que cada vista poseera una funcin virtual chequea(...) que sera llamada desde BaseDialogo::admite(...), aunque esto deber ser examinado con ms detenimiento en tal clase base. Incidencias de Usuarios Toda modificacin o alteracin de los elementos del sistema deber ser registrada, de manera que quede constancia auditable de las mismas. Esto aqu se consigue merced a un esquema de gestin de lo que en adelante llamaremos incidencias del sistema, o simplemente Incidencias, unido al mecanismo general de autorizaciones de acceso imbricado en lo que se denominan Perfiles. La asuncin bsica es que las eliminaciones (y aqu se trata de extracciones de objetos de colecciones dadas, pues ya se estableci que no se producen eliminaciones fsicas directas) se producen normalmente por desuso prctico del item eliminado, y su aplicacin por naturaleza se adscribe a la gestin de Colecciones Activas, aunque tambin podran producirse por error anterior en la creacin o insercin en una determinada coleccin del tem. Las modificaciones, por otro lado, se entendern siempre realizadas por causa de un error anterior: esto es, en un Sistema de Informacin (como pretenden ser la mayora de aplicaciones en los entornos comercial e industrial), los atributos de los objetos no pueden ser cambiados simplemente debido a una actualizacin de la informacin que soportan,

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 160

pues tal poltica desdibujara la esencia bsica del sistema (por ejemplo, si se constata que una persona vive en tal domicilio, distinto de aqul que se mantena por el sistema, no ha de producirse una mera actualizacin del objeto Domicilio referenciado por persona, sino que lo que se espera, y este es realmente el comportamiento de la aplicacin, es que se genere una nueva relacin de domicilio con fecha (pinsese que la mayora de la informacin asumida por el usuario final como parte de sus necesidades negociales puede poseer momento cronolgico de entrada, pero difcilmente observar momento de finalizacin: es normalmente constatar la caducidad de una determinada informacin). Este esquema de modificacin por error resulta en que cada modificacin (y una eliminacin se entiende como tal) generar una Incidencia que recoger el objeto Original, el objeto Modificado (ambos encapsulados en un objeto de tipo ParDeObjetos), el momento de la Modificacin y un posible comentario, automtico o no, razonando la incidencia:
class IncidenciaAuditable { friend class DlgIncidenciaAuditable; public: IncidenciaAuditable(); IncidenciaAuditable( ALTiempo*, Usuario*, ParDeObjetos*, BaseString* = 0 ); ~IncidenciaAuditable(); void dialoga(); private: ALTiempo* crono; Usuario* usuario; ParDeObjetos* parDeObjetos; BaseString* comentario; set( ALTiempo*, Usuario*, ParDeObjetos*, BaseString* = 0 ); };

Las llamadas explcitas generadoras de la Incidencia sern implementadas por el equipo de programacin en cada clase de tipo Vista que maneje la validacin de modificaciones (y, por ende, de eliminaciones), fsicas o no, de objetos. As, tp icamente, tales llamadas se darn en los objetos de tipo agregado: BaseColeccionesActivas, BaseColecciones, etc. Faltara, naturalmente, controlar el acceso a la visualizacin y posible correccin (?!) de Incidencias, pero por su sencillez (se trata de una coleccin de Incidencias desde la que se accede al interfaz propio de cada una de ellas, siguiendo el esquema tantas veces repetido en la presente arquitectura, permitiendo el acceso nicamente a usuarios con cierto perfil) y en aras de una seguridad inicial neutra, se deja su implementacin al criterio del equipo de programadores. He aqu un ejemplo de tal interfaz simple: {bmc incidaud.shg}

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 161

Actualizacin de Vistas Se trata de que al modificar un objeto, siempre a travs del interfaz pblico de ste (usualmente mediante la funcin set( ... )) y mediante mensajes dirigidos a travs de la correspondiente vista que lo referencia, el resto de vistas deberan ser convenientemente actualizadas para reflejar tales cambios, provocados por el mismo usuario o por otros en otros terminales. Examinemos estos dos casos por separado, pues cada vez que una vista expresamente realiza una modificacin en un objeto (agregado o no), se pueden seguir dos polticas de actualizacin del resto de las vistas, dependiendo de las capacidades del entorno en que el sistema se asiente: local: las modificaciones slo se comunican a las vistas del terminal que directamente las gener. El resto de los posibles terminales opera con vistas desactualizadas en tanto no se genere un refresco de stas debido a una condicin de salto (bien mediante un timer, bien mediante chequeos funcionales de atributos). Naturalmente el acceso desde uno de tales terminales a un objeto modificado con posterioridad a su lectura resultar en que el usuario trabaje con informacin distinta de la real, de manera que puede llegar a modificar el objeto por el solo hecho de pulsar el botn aceptar con la informacin antigua. La ventaja, por otro lado, es que no se producen largas secuencias de inactividad debido a las modificaciones inter-usuarios en un entorno medio-grande. cliente-servidor: se requiere al servidor para que notifique las modificaciones a todos los clientes. Esto origina que todos los terminales son actualizados tras una modificacin. Esto significa, tambin, que el focus en cada terminal ir variando en razn de tales refrescos, y causar retrasos de difcil explicacin intuitiva, a la vez que perjudicar la efectividad global del sistema. Una solucin prctica sera, naturalmente, mantener colecciones de asociaciones de objetos con las vistas que deberan ser actualizadas, pero este esquema obligara a mantener mecanismos independientes de validacin de vistas. En las presentes notas nos decidimos por el primer caso, la actualizacin local, matizada por un mecanismo que impedira el solapamiento inadvertido de modificaciones en objetos. Pero antes de nada examinemos lo que conlleva la modificacin de objetos. Existen dos tipos bsicos de modificaciones, cualificadas en razn del tipo del objeto a modificar: las de objetos simples y las de objetos de tipo agregado o colecciones. En el caso de colecciones, las modificaciones se refieren a la variacin de la estructura interna que las compone: esto es, a la adicin y extraccin de elementos, junto con la creacin y destruccin de objetos del tipo de la coleccin precisamente. Consideramos, pues, que la modificacin de la representa-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 162

cin interna de un objeto perteneciente a una coleccin se adscribira al primer caso, en su propia calidad de objeto simple. Examinemos ambos casos: Modificacin de una Coleccion: como se detalla en el epgrafe Gestin de Concurrencias, en ningn caso la modificacin de una coleccin puede producir el inmediato borrado fsico de un tem contenido en la misma, sino nicamente su extraccin y, en algunos casos, reposicionamiento en otras colecciones. La eliminacin visual de un tem originara, pues la coleccin efectivamente habra cambiado, un mensaje de refresco local que llamara iterativamente a las funciones refresca(...) de cada vista que gestione una coleccin, de manera que se produzca una nueva lectura de la coleccin y se traspasen los punteros a los objetos a la coleccin intermedia, para desde aqu actualizar la vista (usualmente el combobox o listbox que contiene las cadenas de caracteres que representan los objetos). Como quiera que el objeto permanece persistente, las relaciones de referenciacin por parte de otros objetos permanecern, tras el borrado lgico, invariantes y estables. En el caso que se produzca una insercin de un objeto en una coleccin, el procedimiento sera el mismo detallado, procedindose a la relectura de la coleccin y a la insercin de lo ledo en las correspondientes colecciones intermedias. Asimismo la modificacin de los atributos de un item originara un refresco en la coleccin, pues la vista de la coleccin mantiene la representacin visual de los tems que contiene, de forma que cuando, como veremos en el prrafo siguiente, la vista que gestiona el objeto simple contenido en la coleccin devuelva, en un par, el objeto modificado, si la coleccin acepta tal modificacin generar un mensaje de actualizacin para que se refresquen las correspondientes cadenas de las vistas. Modificacin de un Objeto Simple: siguiendo el mecanismo de copias temporales especificado en el epgrafe Gestin de Objetos a travs de Vistas, un par de objetos (original + copia) sera devuelto al padre de la vista, que podr as slo validar los cambios o tambin, y en una secuencia inmediatamente posterior, efectuar modificaciones en el objeto al que tal vista "padre" apunta (verbigracia, mediante la insercin de tal objeto en una coleccin, etc.). Esto significa que cada vista deber decidir si manda directamente mensajes de actualizacin o si los delega en vistas "padre". El enfoque aqu adoptado es local-local: esto es, las vistas que manejen objetos simples no generarn ningun mensaje directo de actualizacin tras una modificacin, sino que simplemente pasarn el control a su ventana padre (pinsese que el comportamiento esperado en un entorno grfico es que, tras aceptar la informacin a modificar, la vista afectada se cierre y se traspase el focus a la vista padre de sta), y sta decidir, tras chequear en su caso si las modificaciones realizadas son vlidas, si enva o no mensajes de actualizacin al resto de las vistas del mismo terminal. Se plantean aqu varias cuestiones:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 163

cmo determinar qu vistas manejan objetos simples y cuales no? qu tipo de mensaje de actualizacin hay que envar y cmo habr que preparar a las vistas para que respondan al mismo? Se dar algn esquema de optimizacin de actualizaciones, a fin de no mandar el mensaje de refresco a vistas que no lo necesiten? Bien, vayamos por partes. Existen dos tipos de refrescos posibles: el selectivo y el global. El selectivo obliga a establecer de antemano asociaciones del tipo uno-a-muchos respecto de los tipos de un BaseObjeto y varios BaseDialogos. La implementacin se realizara creando objetos del tipo actualizacin:
class Actualizacion { public: // constructor y destructor Actualizacion( const TipoBaseObjeto&, BaseColeccion* ); ~Actualizacion(); // objeto TipoBaseObjeto getTipoObjeto(); // llama iterativamente a la funcin refresco // de cada una de las vistas del terminal activo // cuyo tipo coincida con alguno de los contenidos // en la coleccin de tiposVistas refresca(); protected: private: TipoBaseObjeto tipoObjeto; BaseColeccion* tiposVistas; };

Pero este esquema obligara a implementar un sistema esttico de reconocimiento de tipos, a la vez que forzara una dependencia entre vistas y objetos no explicitada en el diseo. El refresco global simplifica mucho la implementacin, actuando de la siguiente manera: cuando una vista desea mandar un mensaje de actualizacin simplemente enva un mensaje de refresco a la Vista Principal de la aplicacin, y sta, iterativamente, porque todo padre conoce a sus hijas, lo aplica a cada una de las vistas que de ella dependen. El cdigo resultara de la siguiente guisa:
class VistaPrincipal { public: static void refresca(); // sigue resto descripcin clase }; class BaseDialogo { protected:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 164

//llama a VistaPrincipal::refresca(); virtual void actualiza(); // implementa polimorfismo en refrescos virtual void refresca() {}; // sigue resto descripcin clase };

La clase BaseDialogo es la clase base de todos los dilogos de la aplicacin, por lo que todos ellos podrn usar de la funcin de actualizacin. A la vez implementa la funcionalidad bsica de refresco a travs de la funcin "refresca()", que ser redefinida en las clases derivadas de BaseDialogo y que siempre equivaldr a una lectura del objeto u objetos a los que la vista en cuestin apunta. De esta manera, en una clase derivada de BaseDialogo, como por ejemplo:
class EmpleadosActivosDlg : public BaseDialog { private: BaseColeccionActiva* empleados; BaseColeccionIntermedia* empleadosTemporal; void refresca() { // lee los tems de la coleccin de analitos // y los sita en una coleccin intermedia, // para despus (o a la vez) insertar las // cadenas que los representan en un combobox } // sigue resto descripcin clase };

Podra argumentarse que el refresco global resulta demasiado costoso, pues no incluye optimizacin ninguna: todas las vistas son actualizadas. No hay que olvidar, empero, que siguiendo un esquema local-local, solamente se actualizan las vistas en un nico terminal y que el proceso ser tanto ms costoso cuantas ms vistas estn disponibles en un terminal en un momento dado, pero sta es una opcin que slo posibilita la arquitectura multimodal, por lo que los beneficios compensan de forma clara los posibles defectos. Se ha comprobado, por fin, que la mayora de usuarios de este tipo de sistemas mantienen un nmero relativamente bajo de vistas abiertas a la vez. La simplicidad del mismo lo hacen, por fin, particularmente adecuado para su implementacin en un primer proyecto orientado-a-objetos, cual es el presente, sin olvidar que las polticas de optimizacin pueden aplicarse en una segunda fase, pues las modificaciones que habra que realizar seran nicamente las siguientes:
class BaseDialog { private: void actualiza( BaseObjeto* ); // sigue resto clase };

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 165

class VistaPrincipal { public: static void refresca( BaseObjeto* ); // sigue resto clase };

de tal manera que la funcin VistaPrincipal::refresca(...) actualizara nicamente las vistas del tipo asociado al tipo del objeto que se le pasa como argumento, segn la relacin establecida en los objetos de tipo Actualizacin detallados anteriormente. Se debe redefinir la funcin virtual refresca() en todos los descendientes de BaseDialog, esto es, en todas las vistas de la aplicacin? No! nicamente se producir tal redefinicin en las vistas que gestionen objetos no simples, para evitar as actualizaciones secuenciales masivas. La cualificacin de tales vistas ser expresamente establecida por la documentacin de diseo mediante la inclusin o no de la redefinicin de tal mtodo. Seguridad del Sistema Cmo se accede a los objetos? A travs del interfaz pblico de la clase a que pertenecen. Y cul es tal interfaz en un entorno grfico? El representado por las vistas, o dilogos! Esto parece querer decir que el acceso a los objetos se restringe al que proporcionan los dilogos que los manejan o gestionan (ver Gestin de Objetos a travs de Vistas): como si el puro interfaz de clase de los objetos a acceder se moldeara, restringiera o extendiera merced al interfaz propio de la vista. Pero en realidad tal esquema no resulta tan simple. El acceso a objetos nicamente a travs de las vistas que los manejan supondra que las clases a que aqullos pertenecen no disponen de interfaz pblico de acceso alguno, pues si as fuera el acceso se podra realizar directamente por medio de las funciones que a tal interfaz pertenecieran. Esto es, si tenemos
class TipoDeSuceso { public: // establece el dato miembro "nombre" set( const BaseString& main& ); private: BaseString nombre; // resto descripcin clase }; class TipoDeSucesoView { protected: void aceptar() { // ... set( const BaseString& ); // ... }

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 166

// sigue resto descripcin de clase };

resulta que efectivamente la modificacin se produce a travs de la vista (del tipo TipoDeSucesoView) y en esta pueden codificarse las restricciones de acceso pertinentes, pero lo cierto es que nada impide que cualquier otro programador que desee ampliar o modificar la aplicacin codifique lo siguiente:
TipoDeSuceso miTipoDeSuceso; miTipoDeSuceso.set( "Traicin" );

y esto ocasionara la evidente vulneracin de la restriccin de acceso a la informacin que se pretenda mantener mediante la vista. Hay que pensar que las funciones tpicamente denominadas "set" no suelen establecer chequeo ninguno de validacin y ni siquiera devuelven valor que permita comprobar su correcta ejecucin, pues una de las decisiones tomadas en el diseo de la presente arquitectura es que "todas las validaciones de modificacin de objetos se producirn en las vistas, en su calidad de interfaces prcticos de estos". Cmo tapar, entonces, este aparente agujero de seguridad? Bien, la solucin ms obvia es no hacer accesible las funciones de tipo "set" ms que a las vistas que tengan que manejar los objetos, de forma que habra que eliminar tales funciones de la seccin pblica de sus respectivas clases. Donde situarlas, pues? En la seccin protegida, posibilitando la modificacin desde clases derivadas! Pero esta decisin arrostra nuevos problemas: para que las vistas pudieran acceder a tales funciones de modificacin se les deberan dar niveles de acceso que slo pueden conseguir mediante una declaracin de "amistad" del tipo:
class TipoDeSuceso { friend class TipoDeSucesoView; // sigue descripcin de clase };

Pero este enfoque plantea dos inconvenientes: por un lado se est ligando de forma tajante el modelo de la aplicacin a una vista determinada, de manera que si se quiere cambiar de vista (de clase de vista) se deber modificar la clase del modelo; por otro lado, la declaracin de "amistad" no trasciende a las posibles clases derivadas de la vista, de manera que no se podra dar un comportamiento polimrfico inmediato en los dilogos. Naturalmente esto tiene solucin (y muy elegante, a fe ma) mediante el uso de herencia mltiple: se tratara, as, de establecer una clase base de todos los posibles dilogos (vistas) para una clase dada (del Modelo de la aplicacin), de forma que tal clase accediera, mediante una relacin de "amistad" al miembro "set(...)" protegido del modelo, dotndose de una funcin protegida, a su vez, de tipo "set(

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 167

tipoModelo, ... )", que podra ser utilizada por sus clases derivadas. As, toda clase de tipo dilogo debera derivar de "BaseDialogo" y tambin de nuestra nueva clase "DlgBaseModelo", nica para cada modelo, distinta de BaseDialogo en tanto que no necesita de las caractersticas heredadas de la vista, sino que es un cruce, a su vez, de funcionalidad con vista. Para intentar aclararlo, seguidamente se ejemplifica:
class Etiqueta { friend class DlgBaseEtiqueta; public: Etiqueta(); Etiqueta( const BaseString& ); ~Etiqueta(); protected: set( const BaseString& ); private: BaseString* nombre; }; class DlgBaseEtiqueta { protected: set( Etiqueta*, const BaseString& ); private: Etiqueta* etiqueta; }; class DlgEtiqueta : public BaseDialogo, public DlgBaseEtiqueta { public: // sigue resto descripcin normal de clase };

Se plantea, empero, un problema: parece que no habra ningn problema en vulnerar este esquema protectivo mediante la creacin de clases derivadas bien de DlgBaseEtiqueta o de Etiqueta (en este caso), desde las que se podra acceder a la funcin set(...) cuyo acceso se intentaba restringir. Bien, esto sera as si se permitiera a cualquier programador insertar sin traba alguna un nuevo modulo en la aplicacin y enlazarlo en el ejecutable. La solucin es, naturalmente, impedir esto mediante la creacin de una lista jerrquicamente enlazada de objetos estticos de cada una de las clases de la aplicacin, de forma que la creacin de nuevos objetos se produzca mediante la llamada a una funcin polimrfica de clonacin ( virtual CLASE* clone() ). Esta solucin est perfectamente detallada en la obra de James O. Coplien "Advanced C++ Programming Styles and Idioms" y se denomina de "Constructores Virtuales". Existe, pues, una opcin ptima de seguridad arquitectnica para el sistema, pero quiz no sea la opcin ms adecuada para un primer proyecto de OOP/C++. De esta manera, nuestro consejo es que se utilice un esquema simple inicial, donde las funciones "set(...)" sean pblicas en el modelo, y se acceda a ellas a

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 168

travs de las vistas (cualesquiera que stas sean) que lo manejen. La seguridad se dara, as, a nivel de usuario y no a nivel de programacin, segn lo ya expresado, pero este enfoque permite pasar, en futuras versiones (2.0, 3.0 o aun 6.3.7.4.9) al ya expresado de "Constructores Virtuales", sin apenas tener que variar la codificacin (nicamente habra que cambiar las llamadas a los constructores por llamadas a la funcin de clonacin usando del RTTI -RunTime Type Identification de C++. Seguidamente se podra pasar al esquema de herencia mltiple si as se desea, aunque, como ya se ha expresado en otra seccin, en la presente arquitectura slo se est usando, en aras de la simplicidad, de la herencia simple. Segn lo expuesto, queda nuestro consejo en concentrar la codificacin en la seguridad a nivel de usuario. Como quiera que todas las vistas contienen un puntero al objeto que manejan, tienen evidentemente acceso a la funcin set(...) (pblica en nuestro caso) de la clase del mismo, de forma que podrn modificarlo a voluntad, con las nicas restricciones y condiciones impuestas por la propia vista y las anteriores que produjeron su llamada (pinsese en ColeccionesActivas, etc.). Queda, empero, por resolver los filtros de acceso de usuarios: esto es, no todos los usuarios deben tener acceso a toda la informacin, ni de la misma forma. Vayamos a ello. Obviando esquemas polimrficos demasiado generalistas y, por ende, endiabladamente complejos, atenderemos nicamente a una solucin prctica: la creacin de perfiles de usuario, con tres nicos niveles de acceso para cada una de las vistas de la aplicacin:
sin acceso lectura escritura (sinAcceso) (soloLectura) (total)

De esta manera, aparece una clase nueva:


class Usuario { friend class DlgUsuario; private: enum Acceso { sinAcceso, soloLectura, Total }; PersonaFisica* persona; BaseString* nombre; BaseString* contrasena; // Coleccin de pares de objetos donde uno de ellos // es la clave y el otro el objeto asociado. // (la class VDictionary existe en C++/Views). // En nuestro caso la clave sera un objeto de tipo // vista (derivado de BaseDialogo), sobre el que se // aplicara el mecanismo RTTI para identificarlo, // mientras que el objeto asociado sera el enumerador // de Acceso. // El interfaz del VDictionary sera moldeado a travs

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 169

// de la vista DlgUsuario (clave tambin del mismo). VDictionary* accesos; };

Para saber qu usuario est activo en cada momento, a la clase ApplicationView deber serle aadida una funcin del tipo
ApplicationView::setUsuario( Usuario* );

a la vez que se aadir un parmetro de tipo "Usuario*" al constructor de ApplicationView:


ApplicationView( Usuario* = 0 );

y se chequear en su cuerpo que si el puntero a Usuario es nulo habr de exigirse la introduccin del nombre de un usuario y de su contrasea, que se almacenarn como un nuevo dato miembro de ApplicationView, con una funcin de acceso de la siguiente guisa:
class ApplicationView { private: static Usuario* usuario; // sigue resto descripcin seccin privada public: static Usuario* getUsuario(); // sigue resto descripcin seccin pblica };

Dado, por otro lado, que todos los dilogos de la aplicacin derivan de BaseDialogo, habra que hacer una modificacin leve en el comportamiento de stos: 1) aadir al constructor de BaseDialogo, y por tanto al de todos los dilogos, un parmetro adicional de acceso, que por defecto ser "sinAcceso":
MiDialogo( MyWindow*, MyFont*, Acceso = sinAcceso );

de forma que cuando se cree un nuevo dilogo sin asignacin expresa de nivel de acceso, no tenga acceso en absoluto. En realidad no hara falta incluir tal parmetro adicional a menos que se desee controlar el nivel de acceso diferencialmente desde las clases derivadas de BaseDialogo (bastara nicamente, en otro caso, con establecer tal nivel de acceso en el cuerpo del constructor de BaseDialogo). 2) aadir cdigo en el constructor de BaseDialogo (que siempre se ejecutar para cada dilogo, como clase base en la inevitable secuenciacin de constructores) para que se modifique el nivel de "sinAcceso" al
Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos Pgina 170

constructores) para que se modifique el nivel de "sinAcceso" al correspondiente para tal dilogo al usuario a obtener desde "ApplicationView::getUsuario()". En cuanto al interfaz de la clase Usuario, bien, se seguir el proceso tpico: inicialmente habr un usuario "Supervisor" con contrasea nula a travs del cual se podrn crear nuevos usuarios y asignarles niveles de acceso. Cmo acceder, sin embargo, a la lista actualizada de vistas disponibles en la aplicacin? La solucin ptima sera el uso del esquema de "Constructores Virtuales" notado anteriormente, pues un recorrido por la cadena de objetos estticos devolvera, usando de RTTI, el tipo de cada vista disponible. En caso que, como se aconseja, no se implante tal sistema inicialmente, la lista habr de ser forzosamente esttica y compuesta expresamente. La garanta, a este respecto, es que una vista que el programador no incluya en la lista no podr ser accedida por ningn usuario; la desventaja es que habr que asignarle al usuario Supervisor expresamente el acceso total a cada nueva vista introducida. De cualquier forma es el enfoque recomendado para esta primera aproximacin. El interfaz grfico, en s, vendr dado por una lista de usuarios activos (una BaseColeccionActiva) a travs de la que se acceder a un dilogo DlgUsuario, compuesto por un campo de edicin para nombre, un campo de edicin secreto para contrasea y un listbox con los nombres de las vistas de la aplicacin, donde cada una se asociar con un radiobutton de un grupoExclusivo (sinAcceso, soloLectura, Total). Tanto este sistema de interfaz como el de IncidenciasAuditables pertenece a la zona que podramos denominar "de Sistema" de la aplicacin, y que no se debe modelar en el prototipo. El sistema de seguridad propuesto no interfiere en el sistema de mens, pues siempre aparecen todas las opciones, modelando nicamente el acceso a las vistas. Una clara consecuencia de este enfoque es que un determinado nivel de acceso en un dilogo originar que los dilogos hijos de ste mantengan el mismo nivel de acceso. Gestin de Objetos mediante Colecciones As como en las RDB (Bases de Datos Relacionales) los registros (como equivalente a objetos), que contienen campos (como equivalentes a atributos), estn dispuestos en tablas, en las OODBs (Bases de Datos Orientadas a Objetos) no existe unanimidad en cuanto al trato de equivalencia a dar a las tablas, aunque en ODMG-93 (el estndar de facto en OODBs) y en la mayora de productos comerciales se mantienen conjuntos de objetos de un mismo tipo que se denominan "extents". Cada extent englobara a todos los objetos de una misma clase (persistentes o no). En realidad, as como en las RDBs las nicas formas de acceso son EPs (Entry Points: puntos de entrada) cualificados como tablas, en las OODBs los objetos pueden ser accediros via EPs arbitrarios, via queries (consultas globales) y mediante bsqueda navegacional (de hecho las OODBs son tambin llamadas bases de datos navegacionales).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 171

Nuestro enfoque se basa en crear, si es que la OODBs comercial concreta no lo provee implcitamente, tantos EPs como clases de modelo aniden en el presente sistema, de tal manera que cada objeto creado ser automticamente insertado en una Coleccin que representar el extent de tipo del mismo. Usualmente tales extents sern accedidos por una clave alfanumrica, representativa del nombre de la clase de objetos que manejan. Cuando un objeto se destruya ser extrado de su extent. Se perfila as el extent como un dato miembro esttico de la clase correspondiente, conocido por todos los objetos instanciados de la misma. No se ha modelado expresamente esta funcionalidad porque algunas OODBs incluyen tal comportamiento sin intervencin del operador. Pero aunque los extents resultan eficaces, no se puede trabajar con todos los objetos todo el tiempo: pinsese que el extent agrupa a TODOS los objetos de un tipo dado: los ya no-usados, los temporales, etc. De esta manera, la mayora de los objetos son modelados a travs de colecciones que denominamos ColeccionesActivas, donde se insertan los objetos (adems de en el extent, siempre) con un significado concreto para tales colecciones. As, por ejemplo, una coleccin de agentes de polica en plantilla contendr nicamente objetos de tipo "AgenteDePolicia" que mantengan una relacin actual laboral con la Polica Local, conteniendo el extent de "AgenteDePolicia" la coleccin total de "agentes", en plantilla o no. La extraccin de un objeto de una coleccin activa nunca significa la extraccin del mismo del extent al que, por su tipo, pertenece. Las ColeccionesActivas pueden ser consideradas, tambin, como EPs, aunque como tambin estarn contenidas en un extent podran ser seleccionadas en tiempo de ejecucin en funcin de un parmetro adicional o de una actuacin polimrfica. Nuestro enfoque, siempre en pos de la sencillez, ser calificarlas como EPs. {bmc alcolact.shg} La mayora de llamadas desde los tems de los mens de la aplicacin sern, pues, del tipo:
void PoliciaView::itemMenuAgentesPlantilla() { miColeccionActiva->dialog(); }

donde el identificador "miColeccionActiva" habr sido debidamente inicializado bien en el constructor de la vista, bien como variable esttica de la aplicacin antes del comienzo de sta. Esquema de Consultas El esquema habitual de consultas se basa en menus ad-hoc que conducen a interfaces especficos que, en base a una seleccin un tanto arbitraria de atributos, procuran un resultado conceptualmente pre-determinado aunque de extensin

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 172

variable. Naturalmente cada vez que se necesita informacin en nueva disposicin es necesario acometer la generacin de nuevos interfaces y modificar los puntos de acceso (mens, controles, etc.). El enfoque a adoptar, sin embargo, en la presente esquematizacin es esencialmente genericista y de planteamiento basado en la reutilizacin del software ya generado, usando de los mismos interfaces utilizados para la lectura y modificacin de los atributos de los objetos. Esquema Terico La idea bsica es que las consultas de los usuarios se circunscribirn a un determinado tipo de objeto (o clase), toda vez que todos los entes del dominio del problema que cubre la aplicacin, e incluso las relaciones que podran unirlos, estn modelados como clases. As se partir del siguiente interfaz genrico, que ser consecuencia de la aplicacin de la funcin virtual "dialog()" a un objeto de tipo "Consulta":
class Consulta : public BaseColeccion { public: void dialog() { new DlgConsultaSeleccion( } private: SQLString SQL; };

notifier->getFocus(), this );

{bmc querycol.shg} sobre el que la ampliacin de la seleccin originar la creacin de un nuevo objeto del tipo seleccionado (de la capa del modelo), pero con un comportamiento adicional que hasta ahora no ha sido tratado. De alguna manera se debe encapsular la capacidad de seleccin de consulta en cada clase, de forma que puedan generarse caminos complejos de bsqueda con una delimitacin clara de responsabilidades, en vez de crearlos cada vez para cubrir una necesidad especfica. Para cumplir con este requerimiento se insertarn nuevas funciones en la clase base BaseObjeto:
class BaseObjeto { public: virtual SQLString SQL( const SQLString& ) = 0; boolean estaVacio( BaseObjeto* objeto ) { if ( objeto && !objeto->estaVacio() ) return TRUE; return FALSE } virtual boolean estaVacio() = 0; // sigue resto descripcin de clase

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 173

};

Tal nueva funcin, de obligada redefinicin en las clases derivadas de BaseObjeto (todas las de la aplicacin, por su estructuracin csmica), ser la encargada de recorrer todos los datos miembro de la clase afectada para generar as una porcin de la condicin WHERE de una clusula SQL estndar:
class Etiqueta { public: SQLString SQL( const SQLString& ); private: char* nombre; // sigue resto descripcin de clase }; SQLString Etiqueta::SQL( const SQLString& identifier ) { if ( !estaVacio( nombre ) ) // el operador + est sobrecargado en la clase // SQLString (derivada de BaseString) para aadir // si fuera necesario nexos conjuntivos (AND) return ( identifier + "nombre = " + nombre ); }

o, en un ejemplo ligeramente ms complejo y bastante autoexplicativo:


class Clase { public: SQLString SQL( const SQLString& ); private: OtraClase* otraClase; }; class OtraClase { public: SQLString SQL( const SQLString& ); private: Etiqueta etiqueta; Etiqueta* pEtiqueta; }; SQLString Clase::SQL( const SQLString& identifier ) { if ( !estaVacio( otraClase ) ) return ( otraClase->SQL( identifier + "otraClase->" )); } SQLString OtraClase::SQL( const SQLString& identifier ) {

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 174

SQLString tmp; if ( !etiqueta.estaVacio() ) tmp += etiqueta.SQL( identifier + "etiqueta." ) ); if ( !estaVacio( pEtiqueta ) ) tmp += pEtiqueta->SQL( identifier + "pEtiqueta->" )); return tmp; }

que devolvera la cadena:


this->otraClase->etiqueta.nombre = NOMBRE1 .AND. / this->otraClase->pEtiqueta->nombre = NOMBRE2

De esta manera, al codificar adecuadamente el rastreo SQL en cada clase se posibilita la relacin genrica de bsqueda entre clases. En caso, naturalmente, que aun siendo el puntero a un objeto no nulo sus atributos no fueran sino objetos en blanco, la funcin SQL() devolver la cadena nula, y no se producir modificacin de la frase SQL, aunque lo ms prctico sera usar de la funcin estaVacio() que chequea cada miembro del objeto de la clase dada. Evidentemente, tambin, por otro lado, la relacin entre objetos susceptible de bsqueda podr ser tan compleja e intrincada como se quiera y, lo que es ms importante, usando de los mismos interfaces ya codificados para el uso normal de la aplicacin. Bien, el esquema secuencial es el siguiente: al seleccionar un tipo o clase de objeto en el interfaz anterior, se instancia un objeto "vaco" o "en blanco" de tal clase y se inicializa el SQLString con la frase "SELECT clase FROM objectDatabase WHERE" (donde "clase" es el identificador de la clase seleccionada y "objectDataBase" es la base de objetos accesible como variable esttica de la aplicacin). Seguidamente se produce la llamada al interfaz del objeto en forma de la funcin virtual "objetoQuery->dialog()", de forma que al operar con tal interfaz se pueden crear nuevos objetos relacionados con el primero, directa o indirectamente, que generarn la aparicin de interfaces que sern validados o cancelados, hasta que se valide el interfaz del objetoQuery primero, y entonces, con el objeto ya montado con los atributos de bsqueda deseados (en la relacin interobjetos que se desee), se llamar la funcin constructora de la sentencia SQL en tal objeto, pasando como parmetro usualmente la cadena "this->" (la forma ms extendida en OSQL y sus derivados), pasndose seguidamente a ejecutar tal sentencia (presumiblemente con un preprocesador SQL de la base comercial de objetos). El resultado ser almacenado en una BaseColeccion de Consulta y mostrada en el interfaz anteriormente explicitado. Tal coleccin podr ser ampliada (con una nueva seleccin de bsqueda en disyuncin), restringida (con una seleccin en conjuncin, que en la prctica sustituye la base de objetos por la BaseColeccion de resultados) o limpiada (vacado de la BaseColeccion).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 175

Como fcilmente se comprender, el objeto de tipo Consulta no necesita ser persistente, aunque s podra ser interesante (quizs para controlar la frecuencia de ciertas consultas) hacer persistente al objeto que representa los atributos de seleccin, de forma que esto se deja al criterio del equipo de programacin, aunque se recomienda un tal control nicamente en las fases de prueba y validacin de estabilidad de la aplicacin final. Quedan, sin embargo, algunas cuestiones por resolver. En primer lugar, cmo se accede a la coleccin de tipos disponibles? Aqu aparece la misma opcin discutida en otros epgrafes: bien la lista dinmica enlazada de objetos estticos (uno por cada tipo disponible) bien una lista esttica directamente codificada para la aplicacin. Nuestro consejo es, como en otras ocasiones, empezar por la segunda opcin, pero, aun as, enhebrndola en una solucin ms elegante que la de escribir expresamente en el cdigo la lista de clases como un mero "switch": habra que mantener la estructura jerrquica de las clases hacindola persistente, para lo cual es necesario crear una jerarqua de colecciones de colecciones. O sea, habra que mantener objetos de la clase TipoEnJerarquia, relacionados por su inclusin o no en la bolsa de tipos derivados de cada tipo.
class TipoEnJerarquia : public BaseColeccion { public: TipoEnJerarquia(); TipoEnJerarquia( BaseObjeto*, TipoEnJerarquia* = 0 ); ~TipoEnJerarquia(); BaseObjeto* getTipo() const; TipoEnJerarquia* getTipoBase() const; private: BaseObjeto* tipo; TipoEnJerarquia* tipoBase; // la coleccin heredada por derivacin // contiene objetos de clase TipoEnJerarquia // derivados del presente: // BaseColeccion* tiposDerivados; };

De esta forma, una vez instanciado un objeto de cada tipo, mediante un interfaz accesible slo para el equipo de programacin, para formar la lista necesitada de tipos slo habra que iterar por el grafo de relaciones de inclusin formado. Esta solucin evita tener que codificar el acceso a tipos expresamente en cada porcin de la aplicacin que se necesite, pero tiene la desventaja, frente a la lista dinmica de objetos estticos con capacidad de clonacin, de que no se garantiza automticamente la inclusin de tipos. Se mantendra, as, una coleccin de tipos empezando siempre por el propio de BaseObjeto. En cuanto a las consultas, por otro lado, hemos visto que hay que dotar a cada clase de un "constructor SQL" (algo susceptible, en este enfoque, de ser perfectamente mecanizado a travs de un preprocesador, en una aproximacin similar

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 176

a la de los preprocesadores de persistencia comerciales). En un esquema similar al de persistencia utilizado por algunas bibliotecas de clases, el encardinado SQL se lleva hasta tratar con tipos predefinidos (char, long, etc.). Pero en realidad, se est asimilando la seleccin nicamente con la igualdad de atributos? Qu ocurre con los rangos (de fechas, de cadenas alfanumricas, etc.)? Bien: dado que la codificacin es nuestra, podemos dotar a tales funciones del comportamiento que en cada caso resulte ms apropiado. As, por ejemplo, en el caso de bsqueda en objetos de tipo BaseColeccionActiva, la insercin en un tal objetoQuery de un nuevo objeto significar, y as deber ser codificado, que lo que se busca es una BaseColeccionActiva (del tipo adecuado, si acaso) que contenga al menos un tem con los atributos especificados (este sera el caso, por ejemplo, para encontrar los agentes en plantilla cuya brigada sea una dada). Este enfoque ampla los lmites del problema de bsqueda, pero no soluciona la cuestin de los rangos: qu hacer si deseamos a todos los empleados en activo nacidos entre el 01-0160 y el 01-09-64? De entre todas las posibles implementaciones, y en fidelidad a la idea de reutilizacin de interfaces, examinaremos nicamente una: rangos por interfaces. La delimitacin de rango mediante el interfaz se basa en que los controles de los dilogos admitan la insercin de operadores de comparacin y de cadenas regulares. As, por ejemplo, para buscar sujetos cuyo nombre est comprendido entre "Antonio" y "Casimiro" habra que introducir la expresin ">=Antonio AND <= Casimiro" en la lnea de edicin del interfaz de sujeto correspondiente al nombre. Igual pasara con las fechas, que admitiran as expresiones del tipo "<=02-09-94". Dado que la prctica totalidad de los campos de edicin disponen de scroll horizontal automtico, la longitud de la cadena de comparacin no representa ningn problema. Sera, pues, el interfaz el que leera los resultados de todos los controles y los pasara por un analizador lxico (que se puede encontrar ya montado en multitud de bibliotecas de clases), controlando los operadores e interpretando las expresiones regulares encontradas (del tipo "A*"). Pero tal comportamiento no debe darse ms que cuando se est en disposicin de bsqueda. De esta manera tenemos que el interfaz, como clase derivada de BaseDialogo, tendr dos posibles estados (independientemente de los niveles de acceso explicitados en el epgrafe Seguridad del Sistema): de edicin y de consulta. En estado de consulta la validacin del mismo interfaz admitir operadores y expresiones regulares, generando las subexpresiones SQL correspondientes. Esquema Recomendado El anterior esquema terico resulta enormemente elegante, pero supone algunas modificaciones importantes sobre la arquitectura de la capa del modelo, y de entre ellas la que supone el mantenimiento para ciertos objetos de estados internos (datos miembros) de carcter esencialmente distinto al que su comportamiento presupondra. As habra que cambiar, verbigracia, la clase "Fecha" para que, en un aparte, sostuviera una mera cadena SQL (no asimilable como fecha sin cam-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 177

bios sustanciales). De hecho tal enfoque supone un reestructuracin arquitectnica difcil de asumir en un primer proyecto orientado-a-objetos. Cul es, pues, nuestra recomendacin? Pues que se use la conceptualizacin detallada anteriormente, pero transladndola al interfaz. O sea: se usar el mismo esquema navegacional detallado, pero tales funciones miembros constructoras de la frase SQL estarn implementadas en la clase que defina el interfaz de acceso a los autnticos objetos (esto es, en los dilogos que los manejan). De hecho bastar con implementar un tal mecanismo navegacional genrico en la clase BaseDialogo con las caractersticas anteriormente sealadas para la clase BaseObjeto. La diferencia sustancial respecto del anterior planteamiento es que en el presente no subyace ninguna representacin real de la capa del modelo. Se trata, sin ms, de aprovechar el escalonamiento jerrquico de los dilogos (padre-hija) para construir las frases SQL correspondientes (naturalmente el esquema de tipos explicado sigue siendo vlido). Esto significa, tambin, que no ser posible una reconstruccin navegacional automtica de las frases SQL generadas (bueno, se puede hacer, pero esto supondra que los dilogos dispondran de analizadores lxicos de implementacin no elemental). El esquema recomendado se basa, pues, en la siguiente secuenciacin: del dilogo de Consulta bsico se irn llamando a dilogos afectos a la modelizacin SQL que se pretende, con la anexin del siguiente dilogo auxiliar: {bmc sql.shg} donde aparecern las sentencias SQL determinadas por los dilogos y que actuar como gestor de la construccin de la frase. Dado que una secuencia de tales dilogos podra ser muy larga y, en principio, la cadena SQL se construira con la aceptacin o validacin de lo que en cada dilogo aparece, tal gestor dispone de un pushbutton que automatiza la aceptacin en cadena de los dilogos de seleccin. Tras la construccin de la frase, el gestor ser el responsable de ejecutarla, apareciendo los resultados en el dilogo primero de "Consulta". De esta forma la aceptacin en los dilogos de expresiones regulares no presente ningn problema, pues no habra que mapearlos a objetos reales del sistema. Lo que se podra archivar, as, es la propia sentencia SQL dotada de un ttulo. Este esquema puede ser naturalmente extendido para soportar consultas genricas introduciendo marcas en expresiones que, en su ejecucin (por compilacin) requieran la cooperacin del usuario. Gestin de Dependencias entre Vistas Ya se ha dicho que cada vista (dilogo, ventana, ...) mantiene apuntadores respecto de las vistas que ahija, de forma que un dilogo conoce qu dilogos ahija (dependen de l) y de qu dilogo depende (cul es su padre). Usualmente la implementacin en C++ se sostiene con una Coleccin Ordenada de Vistas en cada vista ms un puntero a la vista padre en cada caso correspondiente.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 178

Este esquema de dependencias supone que cuando una vista se destruye, minimiza o esconde, la accin pertinente es traspasada a sus vistas hijas. Naturalmente el caso crtico es el de destruccin. Pero, es siempre posible mandar un tal mensaje a una vista actualmente con hijas? Examinemos esta cuestin desde el punto de vista polar de la arquitectura elegida: modal o no-modal. En el caso del comportamiento modal resulta que el focus permanece en la ltima vista creada y no puede ser modificado o traspasado a otra vista por el usuario mediante el uso del teclado o el ratn. De esta manera resulta que cuando el usuario ocasione el cierre o destruccin de una vista, forzosamente sta no tendr hijas activas, pues en otro caso el focus estara en la ltima de tales hijas, y desde sta no se podra cerrar una de las vistas padre. Naturalmente es posible codificar un acceso desde una vista a su vista padre, pero tal conllevar, forzosamente, un chequeo expreso de las condiciones de cierre y, en general, de la dependencia entre vistas, pues es condicin en una arquitectura modal que el flujo secuencial del programa retorne a la lnea de cdigo siguiente a aquella desde la que se llam a un dialogo ahijado. Vemos, pues, que el comportamiento modal automticamente mantiene un control de dependencias a nivel de usuario. Vayamos ahora a lo interesante. En aplicaciones basadas en una arquitectura no-modal completa, cual es el presente caso, cualquier vista puede ser accedida en cualquier momento, pues no existe retencin automtica del focus. Qu ocurre, pues, cuando se cierra un dilogo bien para validar la informacin en el introducida bien para cancelar la visin o edicin del mismo, y ste posee dilogos hijos en activo (y esto se produce bien al cerrar el dilogo -a travs del men de sistema- bien al pulsar el botn "aceptar" o "cerrar" del mismo)? Pues que, por defecto, y en base nicamente a los presupuestos que conforma la capa de la vista, se cerraran (por destruirn) los dilogos hijos. Pero, claro, es posible que algunos dilogos ahijados se encuentren en un estado inestable y no puedan o deban ser cerrados en ese momento. Lo que necesitamos es un esquema de reconocimiento que gestione la accin comandada en el dilogo padre. La cuestin es, pues, implementar en la clase base BaseDialogo un mtodo que podramos denominar "compruebaHijos" y que, en definitiva, seguir el siguiente esquema: se recorrer la coleccin ordenada de dilogos hijos y se preguntar a cada uno (con una funcin virtual llamada "boolean puedoCerrar()", definida tambin en BaseDialogo para proporcionar el adecuado polimorfismo) si se puede cerrar. Si un dilogo se puede cerrar se seguir examinando el siguiente en la cadena de iteracin. Si no se puede cerrar directamente (esto es, no est en estado estable), entonces aparecer un dilogo de usuario que preguntar algo as como "En este dilogo se ha producido una modificacin. Desea salvar tal modificacin? SI, NO, CANCELAR". Si el usuario pulsa "S" entonces se llamar a la funcin de validacin de tal dilogo (una tpica boolean aceptar(), tambin defini-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 179

da en BaseDialogo), lo que ocasionar una nueva cascada de validaciones con el mismo mtodo, tras la cual continuar la iteracin de comprobacin de dilogos. Si el usuario pulsa "No" entonces se llamar a la funcin virtual "boolean cancelar()" que simplemente eliminar las modificaciones realizadas en el interfaz y ocasionar, de nuevo, una cascada de reconocimientos tras la cual seguir la iteracin principal. Si el usuario, finalmente, responde "Cancelar", entonces simplemente se cancelar la iteracin principal en tal punto. Esta es la secuenciacin ms elemental y permite una rpida y segura implementacin. Pero examinemos la funcin de validacin individual de dilogos. La funcin "boolean puedoCerrar()", tambin conocida en muchas bibliotecas como "boolean canClose()", admite, en esencia, dos posibles implementaciones: la esttica (de identificadores -flags-) y la dinmica. El uso de flags supone que la clase de la vista mantiene un control estricto sobre las modificaciones realizadas en los controles visuales que la componen. De esta manera, por ejemplo, un procesador de textos sabe, captando las pulsaciones de teclas, si un texto ha sido modificado (aunque una posible modificacin deje el texto en un estado idntico al inicial). As habra que captar todos los eventos (perdn: mensajes) que el usuario dirigiera al dilogo y, en base a la repercusin de aqullos en ste, establecer el valor lgico de un identificador de modificacin (originariamente FALSE). Naturalmente la funcin "puedoCerrar" devuelve el valor lgico de tal identificador. El enfoque ideal, si se adopta el esquema esttico, es crear nuevas clases derivadas para todos los controles que contengan tal identificador (las clases de edicin de texto suelen ya contar con l en la mayora de las bibliotecas), de tal manera que la funcin "puedoCerrar" chequee, en vez de un nico identificador por dilogo, que ninguno de los identificadores de los controles (accedidos como ventanas hijas del dilogo por iteracin) ha cambiado. La implementacin dinmica, por otro lado, se basara en la construccin, con la informacin del interfaz, de un objeto del tipo del que se accede (en realidad se tratara de rellena, con la informacin del dilogo, el objeto "copia" del par de objetos que maneja la vista, como se detalla en el epgrafe Gestin de Objetos a travs de Vistas), para luego comparar (presumiblemente con el operador de comparacin) el objeto "original" con tal copia. Cul es el enfoque que recomendamos? Pues, como siempre, el ms sencillo y eficiente: una mixtura de ambos. Se trata de que la funcin virtual "puedoCerrar" se implemente en cada dilogo de la forma ms efectiva. Si un dilogo es visual y formalmente simple, entonces quiz el sistema dinmico sea ms efectivo, mientras que si el dilogo contiene controles con gran cantidad de informacin (como editores de texto, etc.), el sistema esttico ser ms adecuado.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 180

10
GESTIN DE PROYECTOS
EL SNDROME DE ESTOCOLMO Es opinin antigua, firme y consensuada que no existe una bala-de-plata en relacin con la OT32 (o sea, que la panacea software universal sigue estando en el terreno de la alquimia), pero tambin se acepta de forma unnime que la OT proporciona ventajas evidentes en el desarrollo genrico de software. Naturalmente lo ms fcil es pensar que los nuevos mtodos que la OT propugna no van a facilitar el trabajo diario real en empresas y departamentos de desarrollo de software, pero ocurre que los que accidental o incidentalmente caen en ellos pronto incuban lo que los no-convertidos denominan un OOSS (Object-Oriented Stockholm Syndrome) y que resulta en una persistente y malsana atraccin por las nuevas tcnicas. Los atractivos de los objetos aparecen innegables y, de acuerdo con Lorenz, las siguientes etapas personales se cubren de forma inexorable: Novicio (3-6 meses): se mixtifica el cdigo eminentemente funcional modificndolo y aadindole porciones significadas en objetos. Aprendiz (3-6 meses): aqu se produce el despertar del que hablan los textos de Zen, se ve el verdadero significado de la orientacin-a-objetos y se empiezan a bosquejar diseos pertinentes. Postulante (6-18 meses): los conceptos ya se aplican con soltura en el desarrollo, pero todava se dan algunos problemas con el modelado. Experto (guru): todo son objetos, y el sujeto se pregunta: cmo pude pensar antes de otra manera? Este estadio no siempre se alcanza, naturalmente (afortunadamente, segn algunos).

32

OT es la abreviatura inglesa de Object Technology: Tecnologa de Objetos. TO suena demasiado castizo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 181

Bien: todo esto, unido a la gran profusin de noticias sobre objetos en la prensa especializada, resulta muy emocionante y atractivo, pero en las empresas necesitan de mtodos fiables, estables, bien documentados y a los que d soporte un buen conjunto de soluciones software desarrolladas con ellos. Hay, pues, que examinar el estado de la OT para decidir. Pero aqu empiezan -o siguen- los problemas. ANLISIS Y DISEO ORIENTADOS-A-OBJETOS Si echamos una ojeada al actual panorama de anlisis y diseo orientados-aobjetos nos encontraremos con pocas metodologas y muchos mtodos, buena parte de los cuales observan un carcter bsicamente propietario, siendo muy pocos los que cubren el ciclo completo de vida del software. Aparecer claro, a la vez, que existe un escaso inters, ajeno a las cuitas comerciales, en estandarizar los mtodos: es ms: cuando el OMG (Object Management Group), en un intento normalizador, requiri la colaboracin de los autores de mtodos de OOA/OOD, un nutrido e importante grupo de stos replic con una carta pblica en la que afirmaban que tal estandarizacin no era en absoluto deseable. Parece que es ridculo pensar que existe un mtodo orientado-a-objetos bueno-para-todo, como es risible afirmar que no existe ningn hombre absolutamente estpido. Se aprecia, tambin, la difuminacin del hasta ahora habitual gap semntico entre anlisis y diseo: pero aun esto resulta turbador, pues la planificacin prctica usualmente necesita de fases claras que permitan la evaluacin de resultados y los pertinentes controles de integridad y estabilidad. Las grafas, por ltimo, resultan sospechosamente parecidas entre s, y oscilan entre la simplicidad sospechosa y la prolijidad culpable. Tras todo lo anterior no dejen que el tono les intimide: la orientacin-a-objetos -de la que el autor es firme defensor- realmente funciona, y ya existe un importante acervo prctico de soluciones software basadas en anlisis y diseos orientadosa-objetos. Pero tambin existe un nada despreciable anecdotario de fracasos y despropsitos. La realidad es que el camino de la productividad, como el del infierno, est fatalmente empedrado de ilusiones e intentos aventurados. Necesitamos alguna luz. Intentemos una revisin de los mtodos comerciales. MTODOS COMERCIALES DE OOA/OOD Es opinin extendida que en la arena de los mtodos OOA/OOD existen dos corrientes principales, dividiendo a estos en: estticos (enfocados-a-datos), en los que lo importante es la estructura de datos anexa a los objetos y las operaciones que sobre ella operan.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 182

dinmicos (enfocados-a-comportamientos o enfocados-aresponsabilidades): un objeto tiene sentido en estos mtodos cuando exhibe un comportamiento diferencial respecto del resto de los objetos. Tal comportamiento puede referirse bien al objeto en s (los cambios que pueden operarse en su representacin interna) bien a sus relaciones con otros objetos.

Pero la verdad es que sta es una diferencia puramente acadmica. Lo cierto es que la mayora de los mtodos viene desplazndose, afianzados en el borboteo comercial de las Bases de Objetos (OODBMSs), hacia esquemas puramente dinmicos. Y es que divisiones como la anterior pueden encontrarse con demasiada frecuencia en la literatura, cada vez ms extensa, sobre el tema, fundamentalmente debido a la gran profusin de mtodos con bases tericas un tanto difusas. Y si no chenle un vistazo a algunos (imposible disponer de una lista actualizada de todos ellos) de los actuales mtodos de OOA/OOD (intencionadamente desordenados, para no generar falsas esperanzas):

Anlisis y Diseo Orientados-a-Objetos Mtodos Object Oriented Design Object Behaviour Analysis Methodology for Object Oriented Software Engineering of Systems General Object Oriented Design Object Oriented Software Engineering Visual Modeling Technique Texel Object Modeling Technique Better Object Notation Object Oriented System Analysis Object Oriented Structured Design Systems Engineering OO Syntropy Object Oriented Jackson Structured Design Hierarchical Object Oriented Design Object Oriented Analysis Object Oriented Design Object Oriented System Analysis Colbert Frame Object Analysis Semantic Object Modelling Approach Siglas OOD OBA MOSES GOOD OOSE VMT OMT BOM OOSA OOSD SEOO OOJSD HOOD OOA OOD OSA FOA SOMA Autores Grady Booch Rubin & Goldberg Henderson-Sellers & Edwards Seidewitz & Stark Ivar Jacobson IBM Texel Rumbaugh y otros Nerson Shlaer & Mellor Wasserman et al. LBMS Cook y otros Jackson ESA Coad & Yourdon Coad & Yourdon Embley y otros E. Colbert Andleigh/Gretzingr Ian Graham

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 183

Berard ADM3 Ptech Object Oriented Rle Analysis, Synthesis and Structuring Fusion Desfray Responsability Driven Design

OOA&D OORASS

Berard Donald Firesmith Martin & Odell Reenskaug et al. Coleman y otros Softeam Wirfs-Brock et al.

CRC

Como el lector avisado fcilmente comprobar, en la anterior tabla se mezclan mtodos de anlisis y de diseo porque, pese a lo que anuncien sus autores o aun su mismo nombre, la distincin entre anlisis y diseo se difumina, como antes comentbamos, de forma turbadora (aunque claramente deseable respecto de la modelizacin de la realidad). SOBRE LISTAS Y COMPARACIONES Naturalmente sera deseable disponer de una suerte de catlogo bien documentado en el que se explicitaran, compararan y evaluaran las claves exactas, bondades y flaquezas de cada mtodo de OOA/OOD. As los interesados simplemente slo tendran que dilucidar, tras una somera revisin del documento, el mtodo que mejor se ajustase a las caractersticas del proyecto a desarrollar. Podra pensarse, tambin, que tales comparaciones ya existen (y de hecho as es: libros, artculos, juegos y productos software presumen de haber completado tal tarea). La realidad es, sin embargo, que mal pueden evaluarse y compararse mtodos cuando no existen mtricas orientadas-a-objetos, ni tan siquiera criterios claros e indiscutibles, para tal fin. Los mismos autores no se atreven a afirmar que sus mtodos son universales, aunque desafortunadamente tampoco establecen sus lmites de aplicacin. De esta manera resulta que la mayora de papeles sobre el tema se suelen limitar a un resumen textual de ideas, donde se comparan las subjetivas quintaesencias de cada mtodo. Resulta as, por fin, que tales revisiones son vlidas sobre todo para aquellos lectores que conocen suficientemente los mtodos estudiados. Pero ejemplifiquemos estas flaquezas: Wirfs-Brock favorece las responsabilidades frente a los atributos, mientras que Rumbaugh (OMT) enfatiza la importancia de las asociaciones entre clases; Jacobson (Objectory) es el autor de los casos-de-uso (usecases) y afirma que su metodologa soporta el ciclo total de vida del software orientado-a-objetos; Booch, por otro lado, introduce la nocin prctica de visibilidad en su mtodo de OOD. Shlaer/Mellor (OOSA) modifican los DFDs en Action-DFDs y soportan una gradual descomposicin de las acciones en el modelo-de-estados en procesos en el modelo-deprocesos. Embley, Kurtz y Woodfield (OSA) amplan y matizan OMT

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 184

aadiendo el modelo-de-interaccin-de-objetos (OIM). Coad/Yourdon aportan en su mtodo unario (OOA/OOD) las plantillas de objetos y de descripcin de mtodos. Etc., etc., ... ad nauseam. Como el lector fcilmente podr apreciar, la legibilidad no es lo que aqu ms importa: las anteriores frases tienen sentido sobre todo para el que ya tiene una opinin formada sobre los distintos mtodos. La comprensibilidad s se echa en falta: es fatalmente difcil asimilar opiniones como las anteriores sin conocer en suficiente detalle cada uno de los mtodos tratados, y tanto ms en cuanto que tales no representan unidades de comprensibilidad autnoma, pues cada uno refleja una particular visin, usualmente basada en la experiencia de sus autores en proyectos reales, del ciclo de desarrollo de software. Y entonces? Pues que, aun a riesgo de parecer estpidamente trivial, debo sostener que para aplicar un mtodo de OOA/OOD (o un refrito de algunos de ellos) hay que conocerlos casi todos. Pero examinemos con ms detenimiento esta -aparentemente- sorprendente conclusin. CSAR O NADA A poco que el lector bucee en los textos y artculos de anlisis y diseo orientados-a-objetos se encontrar con afirmaciones tales como que los mtodos de OOA/OOD se dividen en unarios y ternarios, o que los mtodos de segunda generacin pueden usar de uniones de mtodos de primera generacin, o simplemente que si un anlisis contiene un solo DFD es que hay que rehacerlo (Coleman?!). Y es que no hay final donde no existen claros principios: si aun se discute la esencia ortodoxa de la orientacin-a-objetos (si la persistencia es una caracterstica, si la herencia es simplemente un mecanismo, bla-bla-bla), cmo abundar en tantas clasificaciones y divisiones? Epore il muove, como dira Galileo, pues lo cierto es que los sistemas orientados-a-objetos comercial y realmente funcionan. Debe ser posible, pues, extraer tcnicas prcticas de los mismos, pues tales normalmente se basan directamente en las experiencias prcticas (que s suelen funcionar) de sus autores. Pero existe algo bueno en cada mtodo que se pueda aislar y usar en un entorno separado? Absolutamente no, aunque quizs s con cierta matizacin. Resulta que los objetos no estn ah para cogerlos (objectpicking), sino que ms bien el analista (OODA: Object-Oriented Domain Analyst) los crea en cada anlisis, y de aqu que la pertinencia de que cada mtodo o tcnica deban ser especficamente evaluados en cada proyecto. Y precisamente para esto hay que conocer muchos de ellos, pues si no limitaramos de forma peligrosa la arquitectura, y aun el resultado final, de nuestros proyectos. Pero tal no es exclamar, en un remedo barojiano, o Csar o nada: se trata ms bien de ponderar si la base metodolgica del equipo de anlisis y diseo es suficiente para abordar proyectos no-triviales, y dado que no existen todava criterios inamovibles de evaluacin metodolgica en OOA/OOD, parece que habr que dejar, en buena medida, la concreccin de elementos bsicos arquitectnicos en la

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 185

construccin de software al buen criterio de tal equipo. Pero aqu surgen lgicas inquietudes: es posible dedicarse al estudio de las corrientes OOA/OOD sin perder el rumbo del trabajo diario? cmo se ajusta el anunciado eclecticismo, de connotaciones subjetivas, con la deseable normalizacin de la gestin de proyectos en las empresas de desarrollo? cmo determinar la bondad prctica de los mtodos basndose solamente en consideraciones tericas? no existe, al fin, un cierto rango de soluciones suficientemente probadas en anlisis y diseo? Bien: vayamos a las respuestas. LA SOLUCIN ECLCTICA La experiencia y la revisin real de la gestin de proyectos orientados-a-objetos en distintas empresas muestra que el exito siempre ha ido acompaado de una visin particularizada de OOA/OOD/OOP acorde con la poltica de la empresa, las pecularidades del equipo de desarrollo, la experiencia en determinados lenguajes de programacin y la naturaleza concreta de cada proyecto, dentro de unos mrgenes ms o menos estables de actuacin. Resulta as que, mayormente, es una cuestin de afinidades electivas, como dira Goethe. La gran cuestin es, por supuesto, quin elige? Y aqu slo una respuesta: un experto, naturalmente. Es moneda comn que la resolucin de proyectos exitosos, en tanto la empresa no adquiere una slida cultura de objetos, se debe al consejo y mentorizacin externa o interna- de expertos o gures (la barbarizacin de OGs: Object Gurus) que, merced a su experiencia en distintas empresas, pueden elegir con fundamento el enfoque idneo para cada cometido software. Es labor de tales expertos asesorar sobre el equipo de desarrollo, arquitecturas, metodologas, generacin de documentacin, lenguajes de programacin, gestin del proyecto mismo, herramientas de desarrollo, tcnicas y herramientas de validacin, etc. Con todo, y para que el lector no se quede con una amarga sensacin, s puede explicitarse un cierto ncleo metdico: Las fichas CRC y el enfoque a responsabilidades facilitan mucho la labor en las primeras etapas del OOA/OOD (que bsicamente trabajan sobre unas especificaciones obtenidas en la etapa del OORA, Object-Oriented Requeriment Analysis, pero esto es otra batalla); despus una modelizacin tipo OMT OSA ayuda bastante, junto con aspectos de la metodologa de Booch y la aplicacin de casos-de-uso (use-cases) de Jacobson, e incluso diagramas de transicin de estados y redes de Petri. Al final se obtienen fichas tanto de objetos como de sus relaciones, pero tales son, como casi todo, susceptibles de ser mecanizadas. Naturalmente si todo lo anterior se envuelve en un entorno visual (lisez VMT, de IBM), las cosas mejoran bastante. Si a este entorno aadimos capacidades de prototipacin rpida y de documentacin del diseo, entonces parece que tendramos la herramienta adecuada, con lo que entramos en el resbaladizo terreno del CASE (OOCASE ahora).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 186

HERRAMIENTAS OOCASE Como una requeteconocida multinacional oficiosamente afirma: Prescinde de herramientas OOCASE, pero si has de operar con una procura que sea la ms barata. Lo cierto es que el mercado de tales herramientas est un tanto desquiciado: cuando pareca que estaban en franco decaimiento, la orientacin-aobjetos les proporciona un soporte nuevo sobre el que extender su funcionalidad. La realidad, empero, es que tales herramientas son aun bastante primitivas: el soporte de los distintos mtodos es cuestionable, la reingeniera no funciona (los problemas son incontables si se toca el cdigo), y muchas de ellas se limitan a la parte grfica (son al menos sinceras y resultan simpticas las que comercialmente afirman que slo sirven para eso: para los grficos). El otrora espinoso asunto de los repositorios parece solucionado mediante Bases de Objetos, pero existe un gap insondable entre los resultados de tales herramientas y el cdigo de produccin que se supone (como el valor a los soldados) generan. Los mejores resultados aparecen, no obstante, en herramientas ntimamente ligadas a entornos de programacin, como smalltalk, pero lo que aqu se consigue es, en esencia, extender tales entornos de una forma que pronto asumen los propietarios de los mismos (Parts de Digitalk, VisualAge de IBM, etc.). Hasta qu punto un entorno orientado-a-objetos con capacidades visuales/textuales de documentacin, modelizacin y prototipacin necesita de una IOOCASE? Naturalmente la cuestin pasa primero por la revisin de tales entornos, y ms tarde por la adecuacin de los posibles mtodos de OOA/OOD elegidos a las herramientas OOCASE disponibles para su uso. Cuestin de expertos, sin duda. Pero la experiencia muestra que la herramienta que mejor satisface los requerimientos de un proyecto orientado-a-objetos es la que no existe: esto es, usualmente se utilizan esquemas textuales caseros, mientras que el uso de herramientas comerciales se basa en razones corporativas de normalizacin documentaria (as es frecuente encontrar severos desajustes entre la documentacin generada por la herramienta y el proyecto real, tan lejos uno de del otro como lo est un poltico de Utopia). Lo ms prudente es determinar, con la ayuda de un experto, el direccionamiento hacia estas herramientas. GESTIN DE PROYECTOS ORIENTADOS-A-OBJETOS Si los anteriores captulos parecen borrosos, echmosle una ojeada ahora al OOPM (Object-Oriented Project Management): Qu documentos deben generarse y utilizarse en el desarrollo de un proyecto software orientado-a-objetos? Y en qu momentos? Cules son los puntos crticos y cules los de control del proyecto? Cmo pueden, por otro lado, evaluarse los rendimientos del equipo de desarrollo? Existen mtricas formales? Bueno, son muchas preguntas. Y las respuestas aparecen en los manuales. S, en los escasos manuales de OOPM existentes y que se deben, en su prctica totalidad, a grandes firmas consultoras. Otra cosa es su practicidad: hay que soportar grupos de kernels de cuatro dg i-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 187

tos y mapeos de componentes a documentaciones y responsabilidades. Lo que es incuestionable es que algunos roles cambian, otros aparecen como nuevos, mientras que otros desparecen por completo (como, verbigracia, el del mero programador). Con la documentacin (o los deliverables) ocurre otro tanto: dado que el ciclo de vida del software es diferente (Analiza un poco, disea un poco, implementa un poco y evala un poco, segn Berard), no existen fases estancas y, por tanto, una fase no puede basarse en resultados completos de una supuesta fase anterior, de lo que resulta que la documentacin ha de generarse, tambin, de forma involutiva. Parece claro, no obstante, que han de documentarse clases, mtodos y relaciones. Pero lo que definir la estrategia de documentacin normalmente se define en la etapa de OORA (la gran desconocida, en manida frase): especificaciones estticas y dinmicas, de interfaces y comportamientos, de modelizacin y control, etc. Trabajo de expertos, de nuevo. El lector podr encontrar, empero, descripciones de particulares gestiones de proyectos, con diferentes niveles de abstraccin, en Lorenz, Berard, Firesmith, etc., pero difcilmente podrn ser aplicadas a un proyecto concreto con limitaciones humanas, temporales y dinerarias, cual suele ser el ms comn caso. Desesperanza, entonces? No: simplemente una cuestin de monitorizacin: suele acertar quien se ha equivocado antes, directa o indirectamente; y usualmente la gestin de proyectos necesita de una experiencia interdisciplinar en campos dispersos. SSIFO REDIVIVO Quedronse muchas cosas en el tintero: Bases de Objetos, Lenguajes de Programacin, OORA, etc., etc. Pero se trataba aqu de generar en el lector un cierto grado de insatisfaccin, complemento del caramelo comercial orientado-aobjetos que nos invade de forma inmisericorde. Y recuerden a Chesterton: slo se permite dudar el que sinceramente cree, alejado de todo fanatismo. Cada uno tiene un mtodo de OOA/OOD, como cada matemtico tiene un lgebra. Quiz la mejor descripcin del proceso de desarrollo de software orientado-a-objetos sea esa que explica que se trata con plastilina en lugar de con bloques de metal, y que la cuestin no es generar componentes inamovibles, sino ms bien refinarlos gradualmente desde borradores ms o menos acertados. Se trata, al fin, de un proceso reiterativo que asimila al analista a Ssifo, subiendo incesante una piedra que vuelve a caer a la ladera para volver a ser subida. Y aqu, como en el ensayo de Camus, podemos sentir la sonrisa de Ssifo cuando baja la pendiente para volver a empujar la piedra.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 188

11
MODELOS DE ROLES
Qu es lo que, por encima de otras caractersticas, identifica a todos los lenguajes de programacin orientados-a-objetos? Los objetos, naturalmente!, como quiera que en cada caso puedan llamarse. Pero tras stos sigue una legin de lenguajes que incorporan lo que se denominan clases, sean stas propiamente objetos o no, intentando proporcionar estructuras que encapsulen las comunalidades de conjuntos de objetos. Teniendo en cuenta, por otro lado, que los esquemas de diseo, y ms tarde de anlisis de sistemas, debieran provenir del estudio de las estructuras lingusticas aplicadas en la implementacin real de soluciones software, resultar evidente al lector por qu la mayora de los mtodos de OOA/OOD se basan en el pre-establecimiento de una dicotoma inamovible: clases y objetos. Pero, atencin, si se examina brevemente esta aseveracin parece que algo falla: todos los sistemas reales se modelarn slo en base a clases y objetos? Es sta la solucin definitiva? Humm, atendamos a una pequea disgresin: como el lector sabe, los distintos mtodos, tcnicas, trucos y conjuros que conforman el grueso de lo que pomposamente se ha dado en llamar Anlisis y Diseo en Ingeniera de Software no son sino resoluciones ms o menos afortunadas del problema genrico de la traslacin de la realidad al dominio software. Tradicionalmente tal correspondencia se ha basado, como antes se expuso, en una inferencia posibilista basada en modelos prcticos de funcionamiento efectivo: esto es, primero se han modelado, ms o menos desconexamente, multitud de sistemas, para ms tarde extraer de stos conclusiones genricas tericamente aplicables a problemas similares a los modelados. Actualmente, sin embargo, la creciente explosin informativa ha dado en generar un fenmeno harto curioso que yo denominara recursin desplazada. Tomemos, por ejemplo, el Anlisis y Diseo Orientado-a-Objetos: originariamente bienintencionado y basado en simulaciones reales (lisez aqullas basadas en Simula, Smalltalk-80, etc.), pronto desemboc en un precipicio involutivo con ribetes atractivamente comerciales (lisez Coad&Yourdon, Booch, etc.), mencin aparte de las cualidades reales de cada mtodo (bien escasas, con todo, en su relacin con la gestin real de proyectos). As, como cuando se llevaron conejos a Australia, estas primeras incursiones se asentaron en un terreno sorprendentemente frtil, e, igual que ocurri con aquellos animales, la profusin de mtodos devino alarmantemente rpida, ocasionando a la vez similares destrozos (y la mixomatosis no parece ser

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 189

aqu, tampoco, buena solucin). Si a todo esto aadimos la avidez informativa que caracteriza a estos ltimos aos obtendremos una situacin en que las experiencias quedan aplastadas por las inferencias: esto es, como no se da tiempo a que se generen experiencias slidas fiables para cada uno de los mtodos publicados, de forma que sobre ellas pudiera basarse una revisin de los mismos, los nuevos mtodos han de basarse, por fuerza, en las versiones ms recientes de mtodos anteriores: o sea, nos elevamos tirndonos de las orejas. De esta manera, finalmente se convierte en incontestable esencialidad lo que fue contingencia primeramente: los nuevos mtodos33 orientados-a-objetos dan, as, por supuesto que la base de su estructura y notacin son, a la vez, objetos y clases, usualmente aderezados despus con sofisticadas, prolijas, tendenciosas o ridculas consideraciones contextuales y de establecimiento de capas comprehensivas (ya sabe el lector, esas que consiguen hacer mnimamente abordables composiciones de 3.000 clases, 15.000 conexiones, 20.000 flechas, etc.): aparecen, as, subsistemas, entornos de visibilidad, relaciones tipificadas, abstracciones de variacin de estados ... y multitud de artefactos intelectuales que intentan suplir las carencias de una eleccin inicial cuando menos sesgada. Pues si slo se dan inicialmente clases y objetos, como slo se dieron Adn y Eva 34, forzosamente ha de construirse inicialmente un modelo esttico de relaciones entre entidades (agrupemos la dualidad), para despus estimar comportamientos, interacciones y reacciones dinmicas: todo un pastiche gastronmico que podra haberse evitado eligiendo mejor las viandas principales. Y, claro, lo que faltan son los roles -apuntar el impaciente lector. Vaya, as es! Y es que he dado muchas pistas. Pero esto es una afirmacin tan gratuita como la que asegura la sola necesidad de clasesobjetos -seguir el lector crtico- Por qu sta s y aqullos no? Humm, obviando la importante cuestin que el enfoque de roles que aqu se expondr incluye al de clases-objetos, y aplazando temporalmente la inmersin en definiciones y procedimientos, intentar dar satisfaccin al lector atacando, antes de entrar en el modelado genrico de roles, distintos aspectos esenciales a la construccin de sistemas software, singularmente basados en la interpretacin de la realidad y extrados, en buena parte, de mi experiencia personal. ESCENARIOS Y APREHENSIONES Imaginen a una gran empresa rediseando su sistema de facturacin y gestin comercial: como se trata de un proyecto crtico para la compaa, no basta un simple redibujado de lo hasta entonces utilizado: hay que replantearse los su-

33

Observe el lector que conscientemente evito el vocablo metodologa en un vano propsito, sin duda, de resaltar con la repeticin en la omisin cierta intencin irnica, cuando no despectiva. 34 Oh, Adn y Eva se dieron entre s de manera que vocablos como conocimiento y congreso adquirieron su sentido exacto. Y es que seguro que a estas alturas el lector ya habr asimilado la subrepticia comparacin entre la dicotoma clase-objeto y el Concilio de Trento. Claro que, se equiparar OOram al Concilio Vaticano II? Demonios, espero que no!

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 190

puestos bsicos en que se apoya el sistema; de hecho hay que volver a analizar el problema. Pero ... se trata de un sistema complejo, con demasiadas interacciones para ser asimilado conceptualmente en una sola vista! Solucin? Oh, usemos una herramienta CASE -podra exclamar el impaciente lector. Mejor si es OOCASE -asumir aquel otro lector, quizs un tanto receloso. Alegradme el da -podra anunciar entonces yo, empuando con soltura una Magnum. Porque, para qu demonios quiero yo traspasar la complejidad del mundo real al plano de los dibujitos inanimados35? Lo que aqu hace falta es algn enfoque comprehensiblemente simple que permita reducir la complejidad en el ataque para domar el problema. Naturalmente no nos sirven, y ms bien nos perjudican, las composiciones de tablas: incontables entidades, con atributos de todos los tipos y colores, que se relacionan mediante una inaprensible maraa de lneas con cardinalidades explcitas (0,n) por doquier, usualmente construidas mediante una herramienta visual que genera los scripts de creacin de tablas relacionales para una amplia gama de gestores. Y es que en estos esquemas una entidad (por ejemplo, una Persona) tiene los mismos atributos (columnas) respecto de muchsimas otras entidades, lo cual parece razonable en el contexto del diseo de tablas, pero resulta descorazonador cuando respecto de una entidad concreta, como por ejemplo un Asistente Tcnico, nicamente necesita de su direccin. Por qu repetir, pues, todos los atributos en todas las situaciones? Pues porque, simplemente, no se consideran las situaciones en s, sino slo las relaciones estticas entre entes. Oh, las relaciones dinmicas tambin se estiman en los posteriores diagramas de transicin de estados (y tcnicas adlteres), pero slo de manera que se rellenan y cambian algunos atributos del total que rene la entidad: esto es, cada situacin dinmica mantiene un conjunto invariante de atributos, que nicamente se deduce por su omisin del modelo dinmico, de forma que los defectos del presupuesto inicial de diseo de tablas contaminan el proceso entero de anlisis/diseo. Adems este planteamiento supone una visin conciliadora que pasa por muchas consideraciones, decisiones de diseo y soluciones sesgadas que en absoluto quedan documentadas con el mero diseo de las tablas. Me explico: yo puedo decidir, por ejemplo, que el Cliente de este escenario es el mismo Abonado de aquel otro, y que ambos son, en el fondo, instancias, quizs con diferentes estados internos, de la entidad/clase Persona Fsica, que fcilmente es una clase derivada de Persona, con la que operar ms genricamente (tambin las Personas Jurdicas son Clientes y Abonados). Todo esto est muy bien, pero son decisiones que, a lo sumo, se documentarn de forma externa al diseo de marras, pues en ste lo que finalmente aparecer ser una clase/entidad con demasiados atributos/columnas y alguna breve calificacin textual. Y es que no podemos abordarlo todo a la vez: segn G.I. Miller, la memo-

35

Las neurosis de Walt Disney, a pesar de la animacin, construyeron una realidad comercial asexuada y muy cercana a los sueos infantiles del Estrangulador de Boston: muecos que no hablan y que siempre ensean ambas manos, y ... Pero bueno! Qu clase de bicho es Goofy? El sueo de un psiclogo rogeriano!

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 191

ria a corto plazo slo puede asimilar simultneamente tres bloques conceptuales con un mximo de tres elementos cada uno (una variacin de la regla, tambin suya, del 7 ms/menos 2), as que para comprender hay que segmentar: Divide et Impera. Pero, cmo encontrar los subsistemas, escenarios o porciones autnomas sobre las que aplicar nuestra cuestionable inteligencia analtica? Examinemos algunas posibilidades: 1. Use Cases (Casos de Uso): Fiamos la delimitacin del escenario a nuestra intuicin en la adecuada apreciacin de los procesos esenciales al sistema a modelar, concretados en razn de los estmulos externos que los generan. Se trata, en breve, de reflejar el flujo secuencial temporal de mensajes/respuestas entre clases/entidades 2. Responsibility-Driven Design Walkthroughs (Revisin de Escenarios en Diseo Orientado-a-Responsabilidades): Tras identificar las clases del sistema y las responsabilidades que asumen, basadas en la poltica contractual de colaboraciones cliente-servidor, el analista se plantea escenarios posibilistas e intenta adaptar, refinar o inferir nuevas interacciones entre entidades. 3. Escenarios: Un atractivo trmino resonante ( uzzword) que encierra, b como el infierno de don Ramn, ms intenciones que realidades. Los escenarios son ubicuos, como se quisiera que fuese dios, pero igualmente difciles de encontrar e identificar. Oh, estas opciones suenan distintas pero adolecen de la misma indeterminacin primera: Cmo establecer los escenarios de un sistema a modelar sin usar heursticos cosmognicos o tcnicas dolosamente arbitrarias? Esto es, cmo identificar escenarios que no resulten tan voltiles como para que su cambio no afecte a la arquitectura del sistema? Bueno, la experiencia sirve, sin duda, pero slo a los expertos36. Necesitamos algo ms: una suerte de tabula rasa en la que basar nuestra segmentacin de la realidad. TRAS DIVIDIR HAY QUE MULTIPLICAR Volvamos a nuestro sistema de gestin comercial: no hay ninguna forma de establecer mdulos de trabajo a modo de componentes con los que construir, mediante su integracin, el sistema final? Naturalmente que s! Un primer acercamiento incruento (al menos respecto del Jefe de Departamento, usualmente bien pertrechado de arrojadizos laborales) sera intentar modelar procesos (o mejor

36

El lector deber perdonarme el refrito de la infatigable verdad El dinero llama al dinero. Yo mismo habr tambin de perdonarme, pues ciertamente aborrezco la incontinente vulgaridad de la franqueza social de la que los refranes son odioso reflejo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 192

actividades) a la manera de los casos de uso, controlando los estmulos externos que afecten a la identidad del sistema (no las colaboraciones ni las cadenas de mensaje), tambin como las repercusiones externas, pero recabando que los roles a que se pueden adscribir las entidades del mismo conforman un modelo conceptual claro y presumiblemente inamovible en ese contexto. O sea, en la prctica se tratara de modelar por separado situaciones en las que en primer lugar no se d variacin del rol asumido por cada entidad, pudiendo integrar despus los intercambios de roles en el mismo modelo. As una bienintencionada primera fase prctica pudiera ser la de reconocimiento de los roles que se juegan en razn de los procesos actuales que se dan en el dominio del problema: existe, por ejemplo, un proceso de Servicio de Reparacin de Averas en el que se dan los roles de Abonado con Problemas, Mecnico, Punto de Servicio, Servicio Afectado y Material Estropeado, entre otros. Nuestros punto de control respecto de los lmites de esta porcin seran los de transicin en una entidad de un rol a otro. As, por ejemplo, si como consecuencia de una avera irreparable el Abonado decide rescindir el servicio, o contratar ms garantas para el mismo, el rol que juegue habr dejado de ser el de Afectado, pasando a desempear el de activo Contratante, pero tales nuevas actividades deberan permanecer fuera de nuestro modelo de Servicio Asistencial. Hay que recabar, tambin, que en esta etapa en absoluto se prejuzga qu tipo de entidad o clase es la que implementar (y este calificativo es importante) cada uno de los roles encontrados: de esta manera en cada escenario (o mejor, modelo de roles) se detallan nicamente los atributos que interesan al modelo en estudio. Naturalmente en algn momento habr que integrar o sintetizar tales atributos para componer la entidad de implementacin (clase o usualmente tabla): para conseguir tal habr que considerar, ms o menos informalmente, cmo la unin de modelos de roles afecta al modelo de roles resultante (pues eso es lo que obtenemos, en buena lgica). Lo que as estamos consiguiendo es estratificar con lmites semnticos bien definidos cada una de las porciones de que se compondr nuestro sistema, y la verdad es que las perspectivas son halageas: si el enfoque funcional se est abandonando en favor del de objetos/entidades, para evitar la volatilidad de los sistemas, por qu no ir un paso ms all y afianzar el diseo en modelos fcilmente comprensibles, reutilizables y componibles en distintos contextos? Ah, estos son los modelos de roles. Pero no suena todo lo expresado un tanto etreo, como muy dejado a la imaginacin del analista? Bien, quizs suene as, como puede sonar a tarareo una pera de Verdi desde muy lejos, as que habr que acercarse un tanto: en lo que sigue examinaremos muy muy brevemente los aspectos ms importantes de un mtodo, Ooram, analticamente completo, intelectualmente satisfactorio y con muchos aos de experiencia a sus espaldas. As que lo propio ser recaer en el libro en que se explicitan, mejor que aqu, tales ideas.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 193

EL LIBRO Working with Objects: The OOram Software Engineering Method, por Trygve Reenskaug, Per Wold y Odd Arild Lehne, 1996, Manning Publications, 1-88477710-4 (Prentice Hall 0-13-452930-8). Atencin, lector: a mi entender este es uno de los textos ms importantes publicados en los ltimos aos sobre construccin de sistemas software, de forma que arriesgarse a ignorarlo es comprometerse con la oscuridad. Sepa el lector, de cualquier forma, que no soy fantico: slo vehemente. Esto es, en el texto se explicitan muchas ideas que a m me parecen no slo naturales y adecuadas, sino tambin inteligentes, efectivas y, finalmente, humanas. Es curioso que sean los trabajos europeos, y sobre todo los del norte, los que enfaticen la primordial importancia del factor humano en la construccin de sistemas software. El libro contiene, adems, un importante componente pedaggico, pues evidencia los importantes logros conseguidos mediante el uso prudente de Smalltalk y de la ms general Tecnologa de Objetos en una empresa (Taskon) a lo largo de ms de 25 aos. El autor principal, Trygve Reenskaug, es, adems de un reputado experto en el campo de la Orientacin-a-Objetos, el creador del concepto Modelo-Vista-Controlador (MVC) que seguro todos conocen. En fin, para abordar el contenido del libro intentar resumir los captulos ms significativos. IDEAS PRINCIPALES El mtodo OOram se define como un marco de referencia para una familia de metodologas orientadas-a-objetos, tras lo que se muestran las mejoras que el mtodo introduce en las tres dimensiones tpicas que componen el grueso de metodologas: Tecnologa (conceptos, notacin, tcnicas y herramientas): donde se muestran el poderoso modelado de roles en anlisis y su integracin posterior -sntesis en Ooram-, junto con los conceptos bsicos (roles, puertos -que anuncian la visibilidad de un rol respecto de otro-, etc.) y algunas herramientas. Es interesante resaltar la referencia de distintos conceptos a abstracciones: Objeto es es, como rol es por qu, mientras que tipo es qu y clase es cmo. Proceso con Entregables (la secuencia de pasos y la documentacin que los acompaa): OOram distingue tres distintos procesos: creacin del modelo, desarrollo del sistema y construccin de piezas reutilizables.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 194

Organizacin (las maneras en que la empresa acoge lo anterior): aqu se explicitan las dificultades de disear para reutilizar y las ventajas que supone el uso de cadenas de valor. MODELADO DE ROLES El modelo de roles es una abstraccin del modelo de objetos donde reconocemos un patrn de objetos y lo describimos como un corespondiente patrn de roles. Y es que la clase se apoya en las capacidades (funcionalidad absoluta) de los objetos, mientras que el rol se apoya en la posicin y responsabilidades de un objeto respecto de una estructura de otros tantos, que es precisamente lo que percibimos cuando examinamos un conjunto de entidades/objetos en colaboracin. Pero el modelo de roles no representa la descripcin de la estructura entera de objetos observada, sino ms bien de porciones de la misma, segmentadas temporalmente, denominadas reas de inters (areas of concern), y que muestran fenmenos colaborativos de inters. Resulta, as, que un modelo de roles es un modelo orientado-a-objetos de una estructura de objetos. En OOram las tcnicas de identificacin de roles no resultan muy lejanas a aqullas expuestas en el libro de Wirfs-Brock con la ayuda de fichas CRC, de forma que tras haber encontrado el modelo de interaccin, mediante la separacin en reas de Inters, para su visualizacin comprehensiva OOram plantea tres distintas perspectivas: contextual, externa e interna, y provee diferentes vistas aplicables segn mejor convenga, siguiendo la acertada idea de que no hay que usar todos los recursos para describir un modelo, y que determinadas vistas, reunidas en un subconjunto concreto, tornan el modelo ms comprensible que otras. As OOram provee las siguientes vistas: Vista del Area de Inters, Vista del EstmuloRespuesta, Vista de la Lista de Roles, Vista Semntica, Vista de Colaboraciones, Vista de Escenario, Vista de Interfaces, Vista de Procesos, Vista de Diagramas de Estado y Vista de Especificacin de Mtodos, cada una de ellas con su propia notacin, enlazada empero respecto de un objetivo global de modelado. SNTESIS DE MODELOS DE ROLES Se trata aqu de integrar en un modelo ms general (o modelo derivado de roles) los diferentes modelos de reas de inters, de manera que un sistema se configura finalmente como sntesis, que no mera agregacin las ms de las veces, de las partes que lo componen. La sntesis puede darse, as, bien por superposicin (los mensajes de estmulo en el modelo bsico siguen siendo mensajes de estmulo en el modelo derivado), o por agregacin (un modelo de base se integra como una caja negra o subrutina en el modelo derivado), que se califican de tc-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 195

nicas seguras de sntesis, bien por lo que se conoce como sntesis insegura, cuya aplicacin necesita de una personal y cuidadosa atencin.

En la sntesis de roles aparece nuevas vistas: Vista de Sntesis, Vista de Colaboracin por Herencia, Tabla de Herencia y el Lenguaje OOram de Especificacin de Herencia. Se muestran, a la vez, las perspectivas de aplicacin del proceso de sntesis respecto de cada una de las vistas correspondientes al modelo de roles. PUENTE A LA IMPLEMENTACIN En esta seccin aparecen las especificidades aadidas a las vistas de colaboracin inter-roles en relacin a los aspectos de implementacin de los roles, adems de hacer corresponder los conceptos en OOram con los equivalentes de implementacin en C++ y Smalltalk, aplicables por tanto a otros lenguajes con facilidades de orientacin-a-objetos. Hay que tener en cuenta que el entorno de trabajo desarrollado por Taskon se ha basado grandemente en Smalltalk, de forma que los aspectos de uso de herencia mltiple y mixins en C++ se tratan con alguna ligereza. Lo que aqu se abordan son los aspectos iterativos de desarrollo en el proceso de implementacin y las cuitas de eleccin del lenguaje de programacin CREACIN DE COMPONENTES REUTILIZABLES Aqu se muestra la idea bsica de que para reutilizar es necesario utilizar antes, de manera que la llave del xito es la comunicacin efectiva entre el proveedor y los consumidores. OOram distingue entre reutilizacin por herencia (mediante patrones y frameworks) y reutilizacin por encapsulacin. El reso por herencia se basa en patrones (que respecto de OOram son paquetes de formato fijo contenedores de un modelo de roles junto con documentacin que describe cmo y cundo debe ste ser usado) y en frameworks (entornosmarco), que representan un modelo de roles junto con un conjunto de clases base que definen direcciones y restricciones de extensibilidad. El reso por encapsulacin se refiere en OOram a tres tcnicas denominadas OOCS (Sistema de Composicin de OOram), Configuracin en Tiempo de Ejecucin y Duplicacin de la Estructura de Objetos. El Sistema de Composicin OOCS se basa en que dado un objeto-semilla, el esquema OOCS especifica los tipos de objetos que pueden ser asimilados al mismo. El OOCS es, en esencia, una cadena de valor con cuatro capas: Usuario final, Creador del Esquema OOCS, Implementador de Tipo OOCS y Creador de Infraestructura.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 196

LEA, LECTOR: LEA Como el lector puede apreciar en base a lo hasta ahora expuesto, no se trata aqu de un simple mtodo que postula elegantes y frecuentemente hueras descripciones tereas de sistemas, sino ms bien un verdadero marco referencial muy denso en conceptos, notaciones y esquemas formales, pero donde el factor organizativo y humano juega un papel primordial. La extrema densidad de lo que en el texto se expone troca casi en imposible su sola enumeracin comprehensiva aqu, as que emplazo de nuevo al lector a que lea. OOram es, segn sus creadores, un mtodo adecuado de tratar con lo que se denomina programming-in-the-large. Pues bien, aparte de lo expuesto, en el mismo texto podrn encontrar cuatro casos bien desarrollados como ejemplos: el desarrollo de un sistema de informacin negocial, el anlisis y diseo de un sistema de tiempo-real, la creacin de un entorno-marco (framework) y los servicios inteligentes de red organizados como cadena de valor. REFERENCIAS DIRECTAS Ciertamente no hay demasiado escrito, as que rompiendo mi propia norma de referenciar exclusivamente lo por m ledo, a continuacin detallo las referencias que a este respecto me pas Carl Petter Swensson, a la postre uno de los revisores del texto sobre Ooram, y que incluyen libros, artculos, tesis doctorales y escarceos con lenguajes de programacin, conceptos e ideas similares en otros mbitos: Ivar Jacobson, Object Oriented Software Engineering (Libro). Richardson and P. Schwarz, Aspects: Extending objects to support multiple, independent roles, Proceedings of the 1991 ACM SIGMOD International Conference on the Management of Data, pp. 298-307, 1991. P. Gilbert and L. Bic, An object-oriented data model for Semantic Relativism, ECOOP 1989. Lynn Andrea Stein and Stanley B. Zdonik, Clovers: the dynamic behavior of types ans instances, Brown University, Technical Report CS-89-42, noviembre, 1989. Trygve Reenskaug et al., OORASS: seamless support for the creation and maintenance of object oriented systems, Journal of Object-Oriented Programming, 5 (6), octubre, 1992, pp. 27-41. Los conceptos del protocolo de meta-objetos dentro de la comunidad LISP. Egil P. Anderson and Trygve Reenskaug, System Design by Composing Structures of Interacting Objects, Proc. of ECOOP 92, Springer-Verlag LNCS 615, junio/julio 1992, pp. 133-152. Barbara Pernici, Object with Roles, Proc. of the Conference on Office Information Systems (COIS), Cambridge, Massachusetts, 1990.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 197

Constantin Arapis, Specifying Object Lifecycles, D. Tsichritzis (ed.), Object Management, Universite de Geneve, 1990. Constantin Arapis, Specifying Object Interaction, D. Tsichritzis (ed.), Object Composition, Universite de Geneve, 1991. Constantin Arapis, Object Behaviour Composition, D. Tsichritzis (ed.), Object Frameworks, Universite de Geneve, 1992. P. Papazoglou, Roles: A Methodology for Representing MMultifaceted Objects, Proc. of Conf. Database and Expert Systems Applications - DEXA 91, 1991, pp. 7-12. Lynn Andrea Stein, Compound Type Expressions: Flexible Typing in Object Oriented Programming, Proc. of Conf. on Object-Oriented Systems, Languages and Applications (OOPSLA), 1988, pp. 360-361, Position Paper. Constantin Arapis, Type Conversion and Enhancement in Object-Oriented Systems, D. Tsichritzis (ed.), Object Oriented Development, Universite de Geneve, 1989, pp. 191-205. David McAllester and Ramin Zabih, Boolean Classes, Proc. of Conf. on ObjectOriented Systems, Languages and Applications (OOPSLA), 1986, pp. 417423. Hendler, Enhancement for Multiple-Inheritance, SIGPLAN, V. 21, N. 10, October, 1986. Edward Sciore, Object Specialization, ACM Transaction on Information Systems, V. 7, N. 2, April, 103-122, 1989. Mohamed E. El-Sharkawi and Yahiko Kambayashi, Object Migration Mechanisms to Support Updates in Object Oriented Databases, N. Rishe, S. Navathe and D. Tal (eds.), Databases: Theory, Design and Application, A postconference proceedings based upon the proceedings of PARBASE-90 Florida March 6-9, 1990, IEEE Computer Society Press, 1991, pp. 73-109. Jianwen Su, Dynamic Constraints and Object Migration, Proceedings of the Sixteenth International Conference on Very Large Databases, Barcelona, Spain, VLDB 91, 1991, pp. 233-242. El lenguaje denominado LOOM, desarrollado en ISI, California. Para ms informacin, contactar a David Brill (brill@isi.edu) o copiar el Manual de Usuario mediante ftp de isi.edu:/pub/loom. Craig Chambers, Predicate Classes, ECOOP 93 proceedings. Robert Strom et al., Hermes A Language for Distributed Processing, Prentice Hall, 1991. La caracterstica CHANGE-CLASS del lenguaje CLOS, que permite convertir un objeto de una clase a otra. Papel sobre roles implementados en Smalltalk: roles.ps via ftp annimo de 140.78.58.1 La tesis doctoral sobre Redes Semnticas escrita por Nicholas Roussopoulos en 1977 en alguna universidad canadiense. El modelo de datos funcional permite que los tipos sean asociados dinmicamente con objetos surrogados, y esto significa que la identidad de un objeto

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 198

permanece invariante durante sus transformaciones de tipo. IRIS OPEN-DB, de HP. Berard Software Enggineering, Inc., A Complete Object-Oriented Design Example. J. Wieringa, Algebraic Foundations for Dynamic Conceptual Models, Department of Mathematics, Vrije Universiteit, Amsterdam, May, 1990, Ph.D. Thesis. Wirfs-Brock, Johnson, Surveying Current Research in Object-Oriented Design, Communications of the ACM, 33 (9), September, 1990, pp. 113-116. Este artculo incluye una seccin sobre modelado de roles. T. Hawryszkiewycz, Database Analysis and Design (Libro).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 199

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 200

12
BIBLIOGRAFA COMENTADA
Lo que sigue es un conjunto de cortas reflexiones y personales consejos sobre textos imprescindibles en C++ y Orientacin-a-Objetos, sin dejar pasar los dedicados a Java, Smalltalk, Bases de Objetos y metodologas en general. El lector enterado constatar que algunos de los textos que se citan aqu (abrumadoramente en ingls) han sido traducidos ya al castellano, pero sea dicho que yo, en la mayora de los casos ya lo saba, y he preferido un idioma extranjero a una traduccin peligrosa, malvada o, simplemente, ridcula. El lector tiene, empero, una garanta: todos estos libros forman parte de mi biblioteca personal y han sido seleccionados para su inclusin en esta relacin por poseer una caracterstica bsica: merecen ser reledos37. LIBROS BSICOS SOBRE C++ Seguidamente se detallan las obras de introduccin al lenguaje, as como aqullas de referencia bsica, sin las cuales no se debiera seguir avanzando en el mismo. Naturalmente he debido, pues ste es el segmento editorial ms poblado, tomar alguna decisin de exclusin que a alguno puede extraar. No he incluido, por ejemplo, la otrora famosa obra introductoria de Dewhurst & Stark, pues no ofrece caractersticas diferenciales con respecto a la de Lippman, mientras que sta me parece de mayor claridad pedaggica. Tampoco he incluido ningn libro del respetable Mr. Schildt, que obtiene su nicho de mercado de un grupo psicolgico bien determinado de lectores. He procurado, en fin, presentar estos textos en orden de dificultad creciente, pero sin esforzarme demasiado en prevalencias. Helos aqu: The C++ Workbook, por Richard S. Wiener & Lewis J. Pinson, 1990, Addison-Wesley, 0-201-50930-X, 349 pg. He de confesar que le profeso cierto cario a este texto, sin duda el ms elemental de todos los aqu comentados. Se trata de una introduccin a AT&T C++ 2.0,
37

El libro que no merece ser reledo no merece ser ledo, confirmo yo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 201

con multitud de ejemplos, letra grande y legible, y abundantes resultados de programas. El libro se caracteriza por frecuentes inserciones de apartados "Qu pasara si ...?", que intentan resolverle al lector las dudas ms habituales en el primer acercamiento al nuevo lenguaje. Teniendo en cuenta la proliferacin actual de desenfocadas introducciones al lenguaje C++, repletas de dudosas intenciones y de tontera, esta obra es un respiro que se puede completar en escasas horas. Ni de lejos sustituye, por supuesto, a textos de introduccin como el de Lippman o el de Dewhurst & Stark, pero muy bien podra constituirse en el perfecto puente hacia stos, pese a que la evolucin del lenguaje convierte cualquier libro de menos de 400 pginas de letra pequea en un mero divertimento. A C++ Toolkit, por Jonathan S. Shapiro, 1990, Prentice Hall Uno de las primeras necesidades de un desarrollador de C++ es la lectura y el estudio de cdigo "prctico": tras una etapa de aprendizaje generalmente no todo lo corta que uno hubiera esperado, el principiante llega a estar ciertamente hastiado de estudiar cdigo general, pedaggicamente aceptable pero de nula o ligersima aplicacin en el mundo real. Este libro trata, precisamente, de los componentes reutilizables que con la frase "no reinventen la rueda" se suelen obviar en los textos introductorios de C++. La obra, resultando agradablemente breve, ofrece, tras una corta aproximacin a los conceptos muy bsicos de Orientacin-a-Objetos y OOD, cdigo de herramientas tan utilizadas como listas enlazadas, rboles binarios, arrays dinmicos, etc. El texto se acerca, desde la ptica del OOD, a la codificacin de cada uno de estos componentes, para ofrecer los listados completos en la ltima parte del libro. Se proporcionan, tambin, algunas lneas para mejorar distintos aspectos de los programas C++, aunque, por estar basado en AT&T C++ 2.0, no incorpora, como sera sobremanera deseable, plantillas (templates), suplindolas mediante macros genricas del preprocesador. El autor expresamente autoriza el uso comercial de los elementos software que aparecen en el libro, respetando el aviso de copyright, y de su calidad comercial dan fe distintas aplicaciones bien conocidas en las que aparece tal aviso. Con todo, y en contra de lo que el lector pudiera esperar, el texto no acompaa diskette, por lo que al posible usuario le esperan largas veladas de tedioso teclear. Naturalmente ste no es un libro introductorio al lenguaje -pues se supone que el lector ya conoce C++- sino, quizs, uno de los mejores candidatos para despegar de la etapa inicial de aproximacin a C++. El texto adolece, con todo, de cierta lineal terquedad, producto hoy de un regusto demasiado monocorde. Vamos, que se trata de un texto ya antiguo (pero recapacite el lector que hasta de la Biblia se desprende algn mensaje, por lo visto). Ciertamente las actuales bibliotecas de clases, con todo su cdigo accesible y miles de pginas de documentacin, dejan bien chiquita a la intencionalidad de este texto: su nica descarga es que ... resulta ms barato. Vamos, que es como ir al cine a ver Viernes 13th parte 1 (quizs la mejor de la serie).

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 202

On to C++, por Patrick Henry Winston, 1994, Addison-Wesley, 0-201-58043-8. Reconozco que que este libro lo adquir coercionado por un tanto de morbo hacia su autor: Winston, del MIT, padre de la Inteligencia Artificial moderna y guru tecnolgico que ... bueno, bueno, veamos qu cuenta ste me dije. El libro, al fin, es ciertamente curioso, pues expone en secciones breves enseanzas de muy pocas lneas calificadas por epgrafes numerados (hasta 795), insertas en captulos que empiezan, sin variacin, por Cmo hacer ... (How to). As tenemos: Cmo escribir programas que hallan funciones-miembro en tiempo de ejecucin, Cmo construir constructores que llaman a otros constructores, Cmo disear clases y jerarquas de clases, etc., etc. En fin, la brevedad no da cancha a la tontera, aunque en este caso tampoco a la profundidad (pero infiero que no era tal su intencin). Los amantes de aforismos encontrarn aqu su sustento, pero no los buscadores de epigramas. Tan rido como la IA, pero ms prctico. C++ Primer, 2nd Edition, por Stanley B. Lippman, 1991, Addison-Wesley, 0201-54848-8, 614 pg. Nos encontramos ante lo que podra ser calificado como el texto estndar (por oficial) de introduccin a C++. En l se detalla la especificacin AT&T C++ 3.0 (y, por tanto, plantillas y clases anidadas) de una forma extremadamente rigurosa y pulida: los escassimos errores o carencias del texto se han debido, como es posible apreciar en comp.lang.c++, a circunstancias ajenas al autor. No se le supone al lector conocimiento previo alguno de C++ (ni siquiera una media experiencia en C), y la exposicin gradual de las caractersticas del lenguaje est perfectamente modulada. O sea, se trata del libro ideal para iniciarse, sin la ayuda externa de un profesor (aunque sta es, en general, de valiossima consideracin), en los tpicos y recovecos del lenguaje. Lippman empieza muy pronto en la obra con la codificacin de la clase "Array", y el lector puede asistir al proceso de su refinamiento, mediante la aparicin en el texto y acertado comentario de nuevas caractersticas que se le van aadiendo, involucrndose y comprometindose poco a poco en el proceso. El libro est repleto de instructivos ejercicios, de factible resolucin, a la vez que de ejemplos "vivos": el lector ve, sorprendido, cmo stos van incorporando con extrema facilidad nuevos detalles conforme avanza el relato. Todas las secciones del libro muestran en la prctica, pues, los conceptos tericos que se desprenden del lenguaje. Se exponen, por otro lado, una buena cantidad de interesantes y bien probados trucos de programacin, que el lector podr apreciar "en su salsa". Lippman dedica tambin un captulo a OOD (Diseo Orientado-a-Objetos), substanciado, como es habitual en el resto del libro, en un ejemplo apropiado. La tcnica de OOD empleada es simplsima: se trata de identificar las clases necesarias a nuestra aplicacin para dotarlas seguidamente de los interfaces apropiados, y establecer las relaciones entre ellas. Se trata, pues, ms que de una exposicin de OOD, una indicacin de la importancia que se le debe conceder al uso, expreso o no, de los conceptos de OOD a la codificacin en C++. En definitiva: este libro es fundamental para el principiante, mientras que

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 203

para el experto se convierte en paradigma de cmo debe escribirse un buen texto de introduccin. Mastering Object-Oriented Design in C++, por Cay S. Horstmann, 1995, John Wiley & Sons, 0-471-59484-9. El ttulo es ciertamente engaoso, porque el Master significa aqu Iniciacin. Oh, dios mo! Otro libro de introduccin al lenguaje! exclamar el cansado lector. Pues s. Pero el autor, columnista habitual de C++ Report e imparcial revisor de ideas y herramientas C++, merece, al menos, el beneficio de la duda. La intencin de Horstmann queda, con todo, meridianamente clara en el prefacio de la obra, en el que expone que hubo de montar este texto para satisfacer las necesidades de un curso de C++ en la San Jose State University, porque otros libros no servan: as el de Lippmann cubre cada aspecto de C++ en relacin a su complejidad, no a su importancia, mientras que las comparaciones de lenguajes del de Budd distraeran a los estudiantes de su aprendizaje de C++, a la vez que los textos de anlisis y diseo (como los de Booch y Rumbaugh), pese a su bondad conceptual, no resultan prcticos para estudiantes sin experiencia en el desarrollo de grandes proyectos. Con estos supuestos el autor plantea un libro que no intenta ser completo respecto de C++, sino mostrar el subconjunto de mayor uso prctico del lenguaje junto con guas para su adecuado uso. A la vez, y otra vez pese al ttulo, el libro no trata de anlisis o diseo orientados-a-objetos, pues en las pocas ocasiones que el autor aborda tales temas lo hace desde la perspectiva de las fichas CRC o, en todo caso, usando de la notacin Booch-Lite. El resultado es un libro enormemente prctico que presenta una eclecsis razonable de tpicos sobre el lenguaje y que, adems, lo hace de forma prudente y agradable. No s si una universidad espaola recomendara este libro tan prctico, pero los lectores que todava estn pisando la tierra agradecern tan sincero enfoque, alejado de alquimias intergalcticas sobre estructuras de datos y, sobre todo, situado en la misma dimensin de los problemas que el lenguaje intenta solucionar. Object-Oriented Design for C++, por Tsvi Bar-David, 1993, Prentice-Hall, 0-13630260-2. El autor pretende aplicar los conceptos de la orientacin-a-objetos al lenguaje C++ a la vez que intenta construir un puente entre tales conceptos y el mundo de los mtodos formales y las especificaciones formales. Claro que el lector, yo mismo y los periodistas cientficos saben que tal no se consigui, pues todava se suscitan debates sobre si mtodos formales s o no, y acaso cmo, en ingeniera de software38. El texto tiene, con todo, un agradable aunque liviano regusto formal y abunda sobremanera en la importancia evidente de precondiciones y postcondiciones e intenta imponer stas en un estilo de codificacin en C++ loable

38

Oigo exclamaciones airadas? Reclamaciones a IEEE y ACM.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 204

pero en buena medida poco prctico, y es que el lenguaje C++ no aporta ninguna facilidad embebida para el tratamiento de estas cuitas (como s lo hace, por ejemplo, Eiffel). Se pontifica tambin en este texto sobre la extrema importancia de las jerarquas de subtipado como extensin e interrelacin de las abstracciones de datos, ideas que parten del artculo Data Abstraction and Hierarchy de Barbara Liskov (que aparece reproducido en su integridad en este libro) y que influy de forma decisiva en el autor. En cualquier caso el libro es una sorprendente introduccin formalista a C++ y est tan empedrado de buenas intenciones como el infierno (que dira don Ramn, as que no vendr mal a ms de un cabeza-hueca que piense que manuales, referencias y normas de estilo slo han de ser ledos por programadores incompetentes. Una cosa hay que decir: en el ambiente universitario el adjetivo formal posee poderosas connotaciones atractivas que suelen crear adiccin y cierta psicosis denominada de mtodo cientfico, de forma que a nadie le habr de extraar que esta obra se use como texto en un primer curso de C++. The C++ Programming Language, 2nd Edition, por Bjarne Stroustrup, 1991, Addison-Wesley, 0-201-53992-6, 669 pg. Esta es la segunda edicin del texto que el Dr. Stroustrup public en 1.986 detallando el lenguaje C++, en su calidad de creador del mismo. Se trata de un tutorial del lenguaje en el que, a diferencia del texto de Lippman, se enfatizan los aspectos claves de uso del mismo. Se asume que el lector tiene experiencia previa en programacin en C, y se detalla la especificacin AT&T C++ 3.0 partiendo "de cero". El estilo del texto es enormemente sinttico, de manera que la cantidad de tpicos revisados es netamente superior a la del texto de Lippman. Comparada con la primera edicin, la obra ha crecido tambin considerablemente en nmero de pginas. Precisamente ahora, cuando se empieza a generalizar el uso de plantillas (templates) y se empieza a asentar la posibilidad prctica de uso del tratamiento de excepciones, las pginas de este libro sobre tales materias se constituyen en una insustituible gua referencial a la vez que conceptual, pues el conocimiento de la mera sintaxis es claramente insuficiente. Si en la primera edicin se revisaba la biblioteca que entonces se denominaba "stream", implementada por el propio Stroustrup, aqu se repasa la biblioteca "iostream", sobre las bases desarrolladas por Jerry Schwarz. Se muestran y discuten algunos interesantes trucos y tcnicas del lenguaje y el texto termina con un manual de referencia. Una seccin importante del libro la constituye (120 pginas) la dedicada a OOD (Diseo Orientado-a-Objetos), en la que, usando de una extensin de la tcnica de las fichas CRC (de la que el lector encontrar una sucinta descripcin ms adelante, en el texto de Wirfs-Brock), se introduce con acierto al lector en esta disciplina. Bien, se trata de un libro muy difcil de resumir por su buscada tersedad conceptual y de estilo, pero es indiscutible que, quiz con el soporte previo de una obra introductoria como la de Lippman, su posesin es indispensable para cualquier programador de C++. Estdienlo, sin ms condiciones.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 205

The Annotated C++ Reference Manual, por Margaret A. Ellis & Bjarne Stroustrup, 1990, Addison-Wesley, 0-201-51459-1, 447 pg. Esta es la biblia del C++: el texto de referencia indispensable para cualquier estudioso, interesado o programador del lenguaje. Y biblia es aqu un trmino usado con intencionada literalidad: acaloradas discusiones entre miembros de la comunidad C++ suelen zanjarse con citas del tipo "la seccin 13.2 de ARM (el apelativo carioso del texto) dice: ...", que surten el efecto del mgico ensalmo que slo puede emanar de la autoridad por todos reconocida. El texto de este libro fue tomado, en su momento, como documento base por el comit ANSI C++ para la estandarizacin del lenguaje, y la carencia, en estos momentos, de tal estndar ha redundado en confirmar como inamovible tabla de salvacin, en el complicado mar sintctico y conceptual de C++, a esta obra. Nos encontramos ante un texto eminentemente referencial, que no pretende ensear al lector a usar los mecanismos del lenguaje, sino ms bien a describirlos en una forma tersa y rigurosa, pero que, fundamentalmente en las notas, explicita cuestiones sobre la naturaleza de C++ que pueden llevar al lector a comprender mejor la esencia del lenguaje: por qu tal o cual caracterstica no ha sido contemplada, o por qu tal otra ha sido implementada de esta determinada manera, o cmo podran suplirse comportamientos no previstos en el nudo lenguaje, etc. Ntese que la primera lnea del prefacio dice as: "Este libro provee una completa referencia del lenguaje para el usuario experto de C++". No se pretende que el lector estudie de golpe, del principio al final, el texto, pues tal tarea sera como la de intentar abarcar por orden alfabtico una vasta enciclopedia (y esto trae reminiscencias, no obstante, de aquel "autodidacto" de la nausea sartriana): queda, pues, como una insustituible obra de consulta. De cualquier manera, y dado que desde mayo de 1.995 el borrador del estndar est disponible (en Internet) para el pblico en general, esta obra, eminentemente referencial, ha perdido parte de su valor prctico, conservando empero todo su valor histrico. The Design and Evolution of C++, por Bjarne Stroustrup, 1994, AddisonWesley, 0-201-54330-3. Este libro no versa sobre C++ sino sobre las decisiones de diseo que han conducido al lenguaje, en lo esencial, a su actual configuracin. Stroustrup posee un tono exacto y pragmtico que convierte su texto en un alegato contra la tontera, ms all de consideraciones beligerantes entre lenguajes. Yo dira que su antecedente ms cercano es el inteligente libro de Bertrand Meyer Object Oriented Software Construction, 1988, donde se explicitaban tambin las decisiones de diseo del lenguaje Eiffel. As que ... alto! Oigo las quejas de algn lector? Humm, las comparaciones no son odiosas: la estupidez y la banalidad, en contrapartida, s son odiosas. Considero que aunque C++ se pervirtiera y slo se usara en el BOE, el libro seguira siendo absolutamente recomendable. Si uno compara las decisiones de diseo que se notan en este libro con las de otros lenguajes como Java, el resultado es escandaloso. Al fin: racionalidad seria para un texto

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 206

inteligente y sentido. No se lo pierdan. Algorithms in C++, por Robert Sedgewick, 1992, Addison-Wesley, 0-20151059-6. Un libro de algoritmos? Humm, la verdad es que me veo un tanto forzado a incluir algo as en esta sucinta resea bibliogrfica. Lo que me hizo recapacitar sobre esta necesidad fue una ancdota curiosa acontecida en la Universidad de Alicante: portaba yo, para preparar una ponencia, varios libros sobre C++, a cual ms interesante, y mi sorpresa fue constatar el repentino inters de todo el personal del departamento por lo que yo pensaba un anodino libro sobre C++, cual es ste del Sr. Sedgewick, a la postre conocido por su trabajo desde la Universidad de Princeton sobre algoritmos en todos los lenguajes conocidos. Ciertamente la presente obra no es ms que el transporte, a veces prudente y usualmente atropellado, del anterior texto del autor Algorithms in C al dominio (si se puede mentar este vocablo) del C++. Claro que el texto en C pareca resultar tecnolgicamente inadecuado para las avanzadas mentes universitantes (por su estructurada antigedad), as que C++ pareca una adecuada buzzword para unir a Algoritmos. Oh, el texto no est mal. De hecho yo aconsejara que nadie se comprara ninguno de los otros lesivos textos sobre algoritmos en C++ que pueblan el mercado (Alan Ladd y compaa, mayormente), pero el hecho es que la implementacin adolece de muchas cosas, y principalmente es anterior al descubrimiento de la STL. As que ya saben: si quieren algoritmos, vayan a la fuente de Donald Knuth; si quieren C++ vayan a los textos clsicos; y si lo que quieren es exprimir el tiempo, acudan a este texto, sin duda el mejor de los que pudieran encontrar de este estilo. LIBROS DE ESTILO EN C++ Tras superar la etapa introductoria y asimilar los recursos del lenguaje, lo siguiente es aprender a codificar en C++ con efectividad y limpieza. Los textos que se detallan a continuacin pretenden cubrir la etapa intermedia de formacin del programador de C++, recalando ms que en la sintaxis en los esquemas conceptuales que subyacen bajo sta. Effective C++: 50 Specific Ways to Improve Your Programs and Designs, por Scott Meyers, 1992, Addison-Wesley, 0-201-56364-9. Este libro es, en esencia, una coleccin de 50 consejos sobre programacin en C++, debidamente comentados y justificados. Pero no se trata de un recetario al uso, sino ms bien de un compendio de lneas maestras, interrelacionadas entre s (como el lector pronto descubre) y tendentes a procurar al lector este tipo de conocimiento que subyace tras la seca sintaxis del lenguaje. As, aunque el lenguaje permite usar con libertad la derivacin pblica, la aproximacin de ste al espritu de OOD exige que tal derivacin se use solamente cuando se da una re-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 207

lacin de subtipo (o sea, de "ES-UN") entre las clases a relacionar. El lenguaje permite, tambin, por ejemplo, la redefinicin en clases derivadas de funciones miembros no-virtuales de las clases base: esta prctica vulnera, sin embargo, como bien indica Meyers, la cualidad de coherencia de los programas: el comportamiento de un objeto variar dependiendo del puntero desde el que sea accedido. Como vemos, los casos estudiados son de enorme utilidad prctica. Junto a stos se exponen tcnicas que suelen pasar desapercibidas a los principiantes en C++, como, por ejemplo, el chequeo de auto-asignacin en la implementacin del operador de asignacin de una clase. As, nos encontramos en el ndice con secciones como las siguientes: "Nunca redefinas el valor heredado de un parmetro por defecto", "Cualifica los destructores como virtuales en las clases base", "Chequea el valor de retorno de new", "Evita los datos miembros en el interfaz pblico", para terminar con "Lee el ARM". El libro, totalmente recomendable, proporciona al lector la inteligencia de cmo usar los recursos sintcticos de C++ asimilados de los textos introductorios clsicos. Adems, su lectura es tan amena como la de una novela policial. Y para los que gusten de segundas partes he de decir que Meyers amenaz con ms consejos en su nuevo libro. C++ Programming Style, por Tom Cargill, 1992, Prentice Hall, 0-201-56365-7 Junto con el libro de Meyers, configura una de las mejores inversiones en papel impreso que puedan realizar los ya iniciados en el lenguaje C++. El enfoque adoptado por Cargill es, no obstante, distinto al de aqul: en vez que acopiar reglas parciales y supuestamente independientes (como una shopping list), el libro rene porciones de cdigo extradas de otros textos de C++ y de productos comerciales, para luego examinarlos con el ojo crtico del estilo. Es sorprendente la cantidad de elementos perturbadores, y aun de graves errores, que Cargill hace aparecer ante nuestros ojos, demasiado acostumbrados a las revisiones rutinarias y a los esquemas del mnimo esfuerzo. Se tratan, as, temas como "Herencia innecesaria", "Consistencia de clases", etc. analizando codificaciones de clases como "String", "Stack", "Mquinas de Estados Finitos", etc. Cargill pretende imbuir al lector de determinadas reglas de buen estilo en C++, tales como las siguientes: "Identifica el delete para cada new", "No uses un constructor para inicializar datos miembros estticos", "Considera los argumentos por defecto como una alternativa a la sobrecarga de funciones", etc. Como se puede fcilmente apreciar, el texto no tiene desperdicio. El tipo de conocimiento que procura es, por otro lado, de una madurez matizadamente ms clara que en el anterior texto, pues el lector adquiere una visin global de la cohesin del estilo a imprimir al cdigo. El mismo Scott Meyers reconoce su proximidad a este texto, indispensable a todo programador de C++. C++ Programming Guidelines, por Thomas Plum & Dan Saks, 1991, Plum Hall, 0-911537-10-4, 274 pg. Los que experimenten cierta aversin por las colecciones de reglas y los manua-

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 208

les de estilo, encontrarn en este libro el arquetipo de sus pesadillas. Al menos en el formato. Se trata, en efecto, de secciones codificadas que observan el siguiente esquema: TPICO (por ejemplo, 6.06 virtual_fct - funciones virtuales), REGLA (descripcin de las lneas maestras de estilo correspondientes al tema del ttulo), EJEMPLO (demostracin prctica de la problemtica contextual en que se desarrolla la regla), JUSTIFICACIN (argumentacin de apoyo, tanto mediante razonamiento directo como a travs de informes y textos externos, de la regla expuesta), ALTERNATIVAS (opciones de la regla consideradas menores, o aun impracticables), NOTAS LOCALES (media pgina al menos, y normalmente pgina y media, en blanco para el supuesto apunte de notas por el lector). Bien, decamos que una tal rgida esquematizacin pudiera resultar demasiado restrictiva. El presente texto es, sin embargo, enormemente provechoso. Muy en la lnea de un anterior libro de los mismos autores ("C Programming Guidelines"), sus distintas secciones tienden a reforzar una idea que los principiantes en C++ rpidamente relegan al olvido: C++ no es C. C++ no es, tampoco, Smalltalk o Eiffel. Se trata de sistematizar las soluciones a los cuellos de botella en la gestin de proyectos en C++, fundamentalmente cuando intervienen equipos de ms de dos personas: a este fin se explicitan convenciones para nominar identificadores, facilidades para comentar cdigo, gestin de sobrecargas, etc. El libro es, en definitiva, un compaero a tener muy en cuenta ante el diseo efectivo de clases realmente cohesivas y portables. Taligents Guide To Designing Programs: Well-Mannered Object-Oriented Design in C++, por Taligent Inc., 1994, Addison-Wesley, 0-201-40888-0. Conocido el resultado fallido del ambicioso proyecto Taligent (al menos como joint-venture de multinacionales de marca), pudieran parecer fuera de lugar los productos derivados de tal heroica (en ms de un sentido) gesta, libros incluidos. Pero no, claro. Cualquiera que haya de desenvolverse con C++ en un equipo de ms de tres personas debera leer este libro, pues en l se detalla un extracto de una suerte de manual corporativo de estilo en C++ al uso en el entente Taligent. Naturalmente la naturaleza del producto a conseguir (bsicamente el conjunto de frameworks CommonPoint) matiza y personaliza las decisiones de uso y diseo del lenguaje, pero yo dira que casi todo lo aqu expuesto es, ms que razonable, deseable. C++ es un lenguaje difcil y, enfrentados a l, las corporaciones necesitan determinar primero qu subconjunto del mismo utilizar, para despus establecer las normas de uso de tal subconjunto. Este libro es una suerte de manual en el que se detalla una interesante normativa de codificacin de identificadores, a la vez que detallan consejos del tipo: Implemente protocolos completos en clases derivadas, Exprese todos los interfaces mediante objetos, Use objetos estticos en lugar de temporales, etc. Naturalmente todo esto sobra para codificar una pila o un rbol rojo-negro, pero resulta imprescindible para sacar a flote cualquier proyecto no trivial en C++.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 209

LIBROS DE PROGRAMACIN MEDIA Y AVANZADA EN C++ Este es un apartado singularmente despoblado en el actual panorama editorial sobre C++. No hay que dejarse engaar, por supuesto, por ttulos como "Inteligencia Artificial con Borland C++ 4.5" o "Fabrique su propia red neuronal con Visual C++ 2.0". Los tpicos avanzados del lenguaje constituyen, en la mayora de los casos, un universo impensable por el lector de introducciones. En este caso, pues, la seleccin ha resultado evidentemente fcil. He preferido, con todo, reunir los textos bajo el epgrafe comn "medios y avanzados" para evitar tener que calificar como avanzada nicamente a dos obras (que dejo como adivinanza). En fin: lo mejor ser que el lector juzgue y establezca su propia ordenacin. C++ IOStreams Handbook, por Steve Teale, 1993, Addison-Wesley, 0-20159641-5. No se le atragant siempre al lector ese inexorablemente corto captulo dedicado a los streams? Oh, streams por aqu, iostreams por all. No se le dio demasiado bombo a algo que no parece tener demasiadas posibilidades? Bueno, yo les dira que dos de las preguntas que planteo en mis evaluaciones de conocimiento de C++ a equipos de desarrollo son: Ha personalizado la biblioteca de Streams? y Cuntos manipuladores ha creado?. La evaluacin no es ciertamente inequvoca, pero las respuestas han resultado siempre escandalosamente sintomticas. Hasta ahora un aprovechamiento efectivo de la bien diseada biblioteca de Streams nicamente poda provenir de la lectura trabajada del cdigo fuente y, si acaso, de los papeles de ANSI X3J16 C++. El presente libro viene a cubrir tal hueco, aprovechado sin piedad por articulistas malsanos que han malenseado con saa a abusar de esta elegante biblioteca (y no citar revistas como PC World, PC Magazine, Slo Programadores, etc., reas de garrote vil streamico). Oh, la satisfaccin de leer un libro tcnico bien fundado en C++ es inexpresable, pues proporciona indicios de vida inteligente en algn mbito editorial. Bueno, yo no dira que este es un texto indispensable para todos los programadores de C++: slo lo es para aquellos programadores de C++ que restaan cdigo cuando teclean. Cuestin de calificacin, claro (y aqu debo notar que, tras la euforia, el nivel tcnico en este libro alcanzado no es estratosfrico: ms bien se trata de un pequeo puerto sobre el nivel del mar: cuestin de cultura C++). Advanced C++ Programming Styles and Idioms, por James O. Coplien, 1992, Addison-Wesley, 0-201-54855-0. Este es uno de esos escasos libros que redimen, con sobriedad textual y derroche de inteligencia, el aluvin de tonteras y libros triviales sobre C++ y OOP que nos estn inundando de forma inmisericorde. Al Stevens ha llegado a decir que este texto representa para C++ lo mismo que el de Kernighan & Ritchie represent para C: bien, quiz este comentario se limite a exteriorizar una pasin (fcil de comprender, por otra parte), porque sera ms lgico aplicar tal comparacin al

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 210

texto de Stroustrup, pero ciertamente indica un cierto estado de nimo que permanece al terminar el texto. Siendo este libro uno de mis preferidos, mi nica recomendacin es: cmprenlo!. Pero, de que trata esta obra? De tcnicas ms o menos elaboradas de codificacin en C++? Bien, no exactamente. Tras una breve, rigurosa y modlica introduccin a los ms interesantes tpicos del lenguaje, el autor nos anuncia de la existencia, dentro del lenguaje C++, de "idiomas" autnomos: esto es, de abstracciones por encima del nivel sintctico elemental del lenguaje y que configuran, a partir de distintos supuestos, unas formas de codificar y un sustrato conceptual esencialmente distinto entre cada una de ellas. Recordemos, por ejemplo, que Stroustrup nos indica que los constructores en C++ no pueden ser virtuales, pero, a la vez, expresa que con facilidad se puede suplir tal caracterstica. Coplien (Cope para sus amigos) habla, sin embargo, de un "idioma de constructores virtuales". Tomemos como ejemplo este idioma para que el lector pueda entender mejor qu se esconde tras tal denominacin. Un mensaje virtual permite posponer al tiempo de ejecucin la ligadura entre prototipo e implementacin de la funcin asociada; o sea, el mensaje se enviar a un objeto, desconocido en tiempo de compilacin, y ste responder de la forma ms apropiada. Un constructor virtual supone lo siguiente: a un objeto, cuyo tipo exacto desconocemos, se le enva el mensaje "constryete", y ste eligir el mtodo de construccin apropiado pues, quin habra de saber ms de construirse que el objeto en s?. Mediante la estructuracin de una codificacin que permita simular este comportamiento nos podramos encontrar, por ejemplo, con que ninguno de los tipos de los objetos de nuestra aplicacin sera chequeado en tiempo de compilacin, pues el tipo exacto de un determinado objeto no nos hara falta ni siquiera para construirlo. Piense el lector que, de un plumazo, nos hemos "cargado" una de las cacareadas caractersticas de C++: el fuerte chequeo de tipos. Piense ahora el lector cmo sera codificar en C++ sin el chequeo de tipos: muchas de nuestras ideas predeterminadas habran de cambiar! muchsimo de nuestro cdigo ya no tendra sentido! Es como si, de repente, estuviramos trabajando con un dialecto de C++: con un "idioma". Coplien describe algunos idiomas adicionales en su libro: "idioma de ejemplares", "idioma de estructuracin en bloques", "idioma de lenguajes simblicos", "idioma de herencia dinmica mltiple", etc. Ningn programador de C++ que aspire a algo ms que a la codificacin de una lista enlazada debera dejar de leer este texto. Hay que recabar, no obstante, que al lector se le supone un conocimiento adecuado de AT&T C++ 3.0, versin en que la obra est basada. Una ltima nota: los apndices son realmente interesantes, y convienen en procurar al lector un agradable sensacin de efectividad. The Power of Frameworks for Windows and OS/2 Developers, por Taligent Inc., 1995, Addison-Wesley, 0-201-48348-3. Teniendo en cuenta la disolucin del tri Appel-HP-IBM, la inclusin de este texto pudiera parecer vana. Lo cierto es que aun habiendo desaparecido el entente conjunto, IBM finalmente se qued con la tecnologa, y sta se repartir en sus productos de forma inexorable (como ya est ocurriendo). El texto es francamente

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 211

comercial, como un buen catlogo tcnico, e intenta susurrarnos a cada pgina Viste que buena idea? Observaste que inteligente implementacin? Notaste que elegante jerarqua?. Lo mejor de todo es que las ideas, implementaciones y jerarquas son endiabladamente buenas, as que un repaso amable de estos frameworks seguro que aclara a ms de uno las ideas sobre qu pedirle a una biblioteca-entorno de clases. De hecho este libro suple una carencia habitual en la documentacin de las bibliotecas comerciales de clases: ndica algunas decisiones de diseo. Por lo dems es una buena lectura de verano y un agradable repaso de un ambicioso proyecto que quizs debiera haberse planteado en otro lenguaje de programacin (y sta es una opinin de Andy Novobilsky). Data Abstraction and Object-Oriented Programming in C++, por Keith E. Gorlen, Sanford M. Orlow & Perry S. Plexico, 1990, John Wiley & Sons, 0-47192346-X, 403 pg. Este texto est basado en el estudio realizado por los autores para proveer de optimizaciones software a los sistemas UNIX de los Institutos Nacionales de Salud (NIH) en USA. Se trata, en esencia, de una biblioteca de clases envolvente (conocida como biblioteca NIH) modelada a imagen y semejanza del entorno Smalltalk-80 y prescindiendo de las capacidades grficas de ste. El libro exige un solvente conocimiento previo de C++ y se apoya en AT&T C++ 2.0. Usando la terminologa de Coplien, podramos decir que aqu se genera un "idioma tipo Smalltalk", y lo cierto es que lo que en el texto se expone ha tenido una extraordinaria y reconocida influencia en el desarrollo de un gran conjunto de entornos de aplicacin y bibliotecass de clases genricas. El provecho que los programadores de C++ pueden extraer de la obra es evidente, pues sta est montada como un tutorial, explicando detalles y decisiones de diseo de las clases (algunas de ellas inapreciables para la adecuada construccin de componentes reutilizables, una de las expectativas ms cacareadas y, a la vez, ms difciles de C++) y, tras esto, directamente utiliza el entorno creado como herramienta de desarrollo, explicando la posible extensin del sistema. La biblioteca NIH incluye clases como Iterador, Bolsa, Diccionario, Tiempo, Vector, Fecha, Coleccin, Pila, Objeto (la raz de la biblioteca "csmica", pues tal es el nombre por el que se conocen las bibliotecas con una nica clase base inicial). Como el lector puede fcilmente intuir, este tipo de bibliotecas propende al usuario a practicar la derivacin mltiple, y dadas las dificultades no siempre evidentes que esto entraa, el libro dedica un largo captulo a este respecto. Se detalla, incluso, un ejemplo de aplicacin de base de datos usando la biblioteca. Mi sugerencia? Bien, el fuerte entroncamiento de los conceptos de OOD con el acertado uso de C++ procuran un excelente texto de uso referencial, de valiossima lectura para cualquier programador de C++ y aun de los estudiosos de OOP; las ventajas y defectos del enfoque tipo Smalltalk adoptado, por otro lado, disgustarn o deleitarn al lector, dependiendo en buena medida de su estilo y costumbres, pero esto aguzar, alternativamente, el ojo crtico o el gozo del lector. Lanlo!

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 212

C++ Strategies and Tactics, por Robert B. Murray, 1993, Addison-Wesley, 0201-56382-7, 273 pg. Como el mismo ttulo indica, Bob Murray, editor durante muchos aos de C++ Report, ha querido mostrar, como en ajedrez, las estrategias y componendas que trascienden los meros movimientos de las piezas del juego. No es exactamente, en general, un libro "avanzado" sobre el lenguaje, sino que ms bien ocupa ese estadio intermedio entre los libros de estilo y la practicidad del cdigo realmente efectivo. En este sentido los dos captulos dedicados a las plantillas ("templates") justificaran, por s solos, la lectura del libro, pues dada la novedad comercial de esta adicin al lenguaje, pocos textos se han ocupado hasta la fecha de revisar, de forma seria, algunos aspectos no triviales de la misma. Junto con las plantillas, el buen diseo de jerarquas de herencia en C++ y la reusabilidad del cdigo ocupan el grueso de la obra, que, adems, procura un captulo sobre el manejo de excepciones. Nos encontramos, pues, ante una obra moderna y de potente claridad, pensada para el lector no-experto y que contiene ejercicios, resmenes y una buena cantidad de ideas y sugerencias de buen diseo en C++. En definitiva, una adicin indispensable para la biblioteca de C++. Designing and Coding Reusable C++, por Martin D. Carroll y Margaret A. Ellis, 1995, Addison-Wesley, 0-201-51284-X. Reso? No es la caracterstica esencial y automtica de toda codificacin en C++? No es una de las bases de la Orientacin a Objetos? No est ciertamente de ms un libro sobre algo que resulta evidente a todo programador en C++ imbuido en los fabulosos esquemas de la Programacin Orientada-a-Objetos? Bueno: s, no, s y no, respectivamente. A la Dra. Ellis la reconocer el lector como co-autora del ARM y co-columnista junto con Carroll (de AT&T Bell) en la revista C++ Report. El libro es francamente bueno y muestra lo que da de s un lenguaje dctil como C++: si en la mayora de los textos al alcance del hirsuto lector se prima la eficiencia como alma mater del lenguaje, aqu se ensalza la capacidad de reutilizacin por encima de aqulla. La buena noticia es que los autores analizan, para cada posible tpico, los inconvenientes de la fijacin en el reso, y proporcionan estrategias, tcnicas y trucos que habrn de incorporar el acerbo de experiencia del programador prudente de C++. Las plantillas se utilizan profusamente en el texto (que expresamente se desdice de los contenedores de tipo Smalltalk) y el tono escptico respecto del reso de cdigo es realmente de agradecer. Con los pies bien plantados en tierra, la obra habla de diseo de clases, extensibilidad, eficiencia, errores, conflictos, compatibilidad, jerarquas de herencia, portabilidad, uso de bibliotecas de clases ajenas, documentacin y otros interesantes tpicos (el lector avisado notar que he descrito el ndice). Las ideas que aqu se dan sobre excepciones, herencia invasiva, el uso de const, clases endgenas, instanciacin de plantillas, etc. son de una practicidad tal que el lector no podr por menos que exclamar: Cmo nadie me recomend este libro antes? En fin, una obra indispensable.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 213

Taming C++: Pattern Classes and Persistence for Large Projects, por Jiri Soukup, 1994, Addison-Wesley, 0-201-52826-6. Teniendo el cuenta en panorama de obras sobre C++, el ttulo anterior puede hacer segregar jugos gstricos a ms de un jefe de departamento o responsable de proyectos no-triviales en C++. Bien: el texto, como aparece en su presentacin, versa sobre las cosas obvias y simples que llevan a buen puerto o hacen fracasar a los grandes proyectos. De hecho su eleccin suele ir ligada al texto de Taligent sobre estilo de codificacin en C++, y se fundamenta en el sentimiento de inseguridad que se genera al unir un equipo de personas mediante el pegamento C++. Aparte de los discutibles porciones dedicadas a la persistencia de datos (un tanto forzadas por la actividad empresarial del autor) el libro est plagado de revisiones, tcnicas y consejos que intentan reflejar el xito del autor en su propia aventura C++ post AT&T. As, por ejemplo, en el captulo Bibliotecas de Patrones se examinan estructuras, problemas de distintas bibliotecas actuales (Tools.h++, NIH, Componentes C++ de Booch, etc.) para concluir con una biblioteca ideal: la implementada por Code Farms (la empresa del Sr. Soukup). Pero en realidad esto es totalmente legtimo, pues nadie puede hablar de una experiencia que no ha obtenido, y no hablar de experiencia es mentar el aire, claro. Pues bien, el autor expone sus personales ideas sobre dependencias entre clases, tipos de datos abstractos, generacin de patrones y ... persistencia. Es cierto, tambin, que la palabra resonante patrones en el ttulo no encontr eco en la comunidad establecida de patrones, as como las ideas del Sr. Soukup, siendo radicales, son discutidas. Pero la verdad es, al fin, que este es uno de los pocos libros que hablan de C++ en su relacin con grandes desarrollos y, en este sentido, es imprescindible. LIBROS SOBRE SMALLTALK Smalltalk? Por qu Smalltalk? Bueno, querido lector, Smalltalk es uno de los lenguajes de ms rancio abolengo dentro del mundillo de la Tecnologa de Objetos, y su influencia ha resultado decisiva en los aspectos prcticos de desarrollo de las bibliotecas de C++. Adems la literatura Smalltalk posee un tanto a su favor: al ser ste un lenguaje que aparentemente no est en la cresta de la ola y que conserva un cierto rigor academicista (rigor mortis le llaman algunos) la tontera no ha penetrado de forma irremediable en su acervo bibliogrfico. No se dan as, al menos todava, libros del tipo Programe en 15 horas con Smalltalk, asombre a sus amigos y d un nuevo rumbo a su vida sexual. Esto aparentemente quiere decir que casi todos los libros actuales sobre Smalltalk son intelectualmente legibles y no causan daos neuronales irreparables. Y la verdad es que, aunque sin competencia respecto de C++, existe una buena cantidad de libros sobre Smalltalk, pero, puestos a elegir, he aqu mi seleccin, aproximada y pretendida, pero no necesariamente, en orden creciente de dificultad:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 214

Programacin Orientada a Objetos: Aplicaciones con Smalltalk, Angel Morales & Francisco J. Segovia, 1993, Paraninfo, 84-283-2019-5. Es ste el nico libro original en castellano que, de forma pedaggicamente reglada, procura una razonable introduccin al lenguaje, bien aderezada, adems, de ejemplos prcticos completos cuya utilidad, sin embargo, no sobrepasa el mbito de la didctica acadmica. Resulta curiosamente actual el tendencioso ejemplo en el que Empresarios, Funcionarios, Intermediarios, Matones y Periodistas son, por fuerza, Polticos (derivan de esta clase), y un objeto de tipo Empresario soborna a un objeto de tipo Funcionario conocido como John War (nada que ver con Monsieur Alphonse, a lo que parece). Los ejemplos son, en general y segn lo visto, muy amenos (no faltan las ubicuas Torres de Hanoi), a la vez que la primera parte terica es suficientemente exacta: se describe el dialecto Smalltalk-80 de forma que se consigue adentrar en los conceptos bsicos del lenguaje a lectores con conocimientos al menos bsicos de algn otro lenguaje de programacin, quizs Pascal o similar. Se echa quizs en falta un disquete con el cdigo de los ejemplos, siempre deseable en Smalltalk por las facilidades de experimentacin con el mismo. Smalltalk Programming for Windows, Dan Shafer con Scott Herndon y Laurence Rozier, 1993, Prisma Publishing, 1-55959-237-5. Este libro es una revampirizacin del texto Practical Smalltalk: Using Smalltalk/V de Dan Shafer y Dean Ritz, publicado en 1990 por Springer-Verlag. La obra describe ejemplos prcticos sobre Smalltalk/V versin 2.0 para Windows, y asume un conocimiento cuando menos elemental de Smalltalk y de la programacin Orientada-a-Objetos, abordando la enseanza mediante el desarrollo completo y gradual de siete proyectos bien engarzados y cuyo cdigo completo se acompaa en un disquete: un prioritizador (un secuenciador de tems en base a prioridades), un contador simple (con botones de incremento y decremento), un calendario con interfaz grfico, un agenda de citas (que se aadir al calendario), un paquete grfico elemental, un diseador de formularios y un reloj multiproceso. El texto est muy pegado a la tierra, y el nivel es bajo-medio. Resulta aconsejable su lectura tras el estudio de los manuales de Smalltalk/V, quiz demasiado etreos. Object Oriented Programming, Peter Coad & Jill Nicola, 1993, Prentice-Hall, 013-032616-X, con disquete del cdigo C++ y Smalltalk. El libro resulta sorprendentemente fresco, detallado y especfico comparado con los anteriores de Coad y Yourdon sobre OOA/OOD, y, la verdad, resulta muy divertido de leer: se puede acabar de un tirn. Mediante el anlisis, diseo e implementacin de distintos pequeos proyectos, en creciente grado de dificultad, pero siempre muy pedaggicos (un contador elemental, una maquina vendedora, un sistema de soporte de ventas y un sistema de control de trfico), se introduce al lector en un discurrir donde se alternan C++ y Smalltalk, convirtindose as en

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 215

una perfecta obra ambivalente de introduccin a ambos lenguajes. Los autores intentan, a la vez -y parece que consiguen-, imbuir al lector en lo que denominan object-thinking, una suerte de estructuracin mental en la que se ven objetos por doquier en cualquier rea39. En fin: un texto ameno y recomendable, de nivel medio. Discovering Smalltalk, Wilf LaLonde, 1994, Benjamin Cummings, 0 -80532720-7. Si slo ha de leer un libro sobre Smalltalk, lea ste. Independientemente de si conoce o no ya el lenguaje, de si sabe o no qu es un ordenador, de si proviene de COBOL o C++, ste es su libro. Y si bien puede resultar chocante que al principio por ejemplo se explique, aun de pasada, qu es un disco flexible, el lector pronto descubrir que casi inadvertidamente, en una forma que recuerda el nfasis conceptual adscrito a Alan Kay, se va introduciendo en un lenguaje que no necesita de ningn bagaje informtico anterior. La profusin de grficos es impresionante (a diferencia del resto de los libros, ste se puede leer perfectamente sin tener Smalltalk delante) y el estilo francamente atractivo: los conceptos se introducen con fuerza, amenidad y detalle. No tienen excusa: lean y disfruten de un lenguaje agradecido como pocos. Smalltalk-80: The Language, Adele Goldberg & David Robson, 1989, AddisonWesley, 0-201-13688-0. Este libro es un clsico y representa la segunda edicin, convenientemente modificada y remozada, del anterior texto Smalltalk-80: The Language and its Implementation, familiarmente conocido como libro azul, de los mismos autores, publicado por Addison-Wesley en 1983, que contena una interesante especificacin, desaparecida en la presente edicin, para la construccin de una mquina virtual Smalltalk-80 (una buena razn para disponer de las dos obras). Este texto se apoda libro prpura y est estructurado como un manual de acceso y descripcin del lenguaje: la introduccin sintctica es seguida por un repaso de los recursos del lenguaje-entorno para acabar con la exposicin de distintas aplicaciones de simulacin discreta orientada-a-eventos. El tono de la obra es exacto y su lectura resulta cmoda y estimulante. En definitiva, como dicen los americanos, un must-have.

39

Con esto pasa como con el tabaco y los vicios mayores: los ms convencidos de la objetivizacin mental son precisamente los estructuralistas arrepentidos. Y la pregunta es cundo se fundar Estructuralistas Annimos? Hay ciertos pecados que necesitan pblica confesin.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 216

Smalltalk-80: The Interactive Programming Environment, Adele Goldberg, 1984, Addison-Wesley, 0-201-11372-4. Originalmente concebido como documentacin de usuario del sistema Smalltalk80 de Xerox, debido a la extraordinaria integracin del entorno con el lenguaje en s, este texto (denominado, segn la costumbre, con el color de su portada: libro naranja40) describe, en forma de manual tutorado, la interfaz de usuario del entorno-lenguaje, las tcnicas de extraccin de informacin de los objetos del sistema, las operaciones CRUD sobre clases, la depuracin del cdigo y las relaciones del entorno respecto del exterior. El libro presenta suficientes ilustraciones grficas y el estilo es adecuadamente paternal. En fin, un manual clsico41. Inside Smalltalk I, Wilf LaLonde & John Pugh, 1990, Prentice-Hall, 0-13468414-1. Esta obra, junto con el segundo tomo, representa para los aos 90 lo que para los 80 los textos de Goldberg y Robson. El papel impreso qudase obsoleto con mucha rapidez, pero as y todo est obra es indispensable para todo aqul que quiera trabajar de forma seria en Smalltalk. En este tomo se describen los fundamentos del dialecto Smalltalk-80 versin 2 y de su entorno de programacin, junto con el detalle de las clases bsicas y la gestin de imgenes grficas. Inside Smalltalk II, Wilf LaLonde & John Pugh, 1990, Prentice-Hall, 0-13465964-3. Este tomo, inseparable compaero del anterior, se centra en la construccin de aplicaciones con IGUs VIMP 42. Centrndose en el paradigma MVC (ModeloVista-Controlador) con una profundidad difcil -si no imposible- de hallar en otros textos, los autores introducen al lector con detalle, rigor y precisin en las operaciones con ventanas, mens, ventanas emergentes, etc., para acabar con casi 200 pginas en las que se discute y expone el diseo e implementacin de un constructor de ventanas (una suerte de asistente que proporciona facilidades grficas para la creacin de interfaces de usuario), una aplicacin de tamao medio de gran inters. Se trata de una obra imprescindible.

40

El inquieto lector podra preguntarse si existen ms libros de colores. Pues, bien, s: al texto Smalltalk-80: Bits of History, Words of Advice, de Glenn Krasner, editor, Addison-Wesley, 1983, ISBN 0-201-11669-3, se le denomina libro verde. Nada malicioso, empero. 41 Mark Twain socarronamente afirmaba que un clsico es un libro que todo el mundo elogia y nadie lee. Ya sabe, lector: sea original y lea. 42 VIMP (Ventanas, Iconos, Men y Puntero) es la aventurada grafa castellana de WIMP.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 217

Smalltalk/V: Practice and Experience, Wilf LaLonde & John Pugh, 1994, Prentice-Hall, 0-13-814039-1, con disquete. LaLonde y Pugh son, entre otras cosas y desde hace tiempo, columnistas permanentes de la seccin Smalltalk del JOOP (Journal of Object-Oriented Programming), de SIGS Publications. Fruto del ingente material publicado en sus columnas es el presente texto, en el que se presentan convenientemente remozados algunos casos prcticos de programacin orientada-a-objetos en Smalltalk/V para Windows. El libro est pensado, como los mismos artculos, para lectores con conocimientos medios de Smalltalk, aunque como los casos son realmente interesantes (conjuntos borrosos, intercambio dinmico de datos, combinacin de componentes modales y no-modales para construir un visor grfico, etc.), la lectura de las 185 pginas del texto resultarn tan valiosas para los expertos como para los recin llegados al lenguaje. IBM Smalltalk: The Language, por David N. Smith, 1994, Addison-Wesley, 08053-0908-X. IBM ha entrado de forma sorprendentemente rpida en la arena Smalltalk y ha cambiado ciertos criterios que se estimaban inamovibles. De cualquier manera la tradicin Smalltalk puede mucho, as que todo es, mayormente, como cualquier Smalltalkista podra esperar. Este libro es bueno, con todo, en el sentido referencial ms prctico del lenguaje: nomenclatura, esquemas, modificaciones arquitectnicas leves, muchas tablas grficas, ejemplos, relaciones y cdigo, suficiente cdigo (aunque de ese que se califica como toy-code). La inclusin de este libro aqu se debe a que la integracin de manual referencial y manual de usuario que procura tiene una calidad superior a la media y, por tanto, ayudar de forma prctica a los que necesitan inmersiones guiadas en el lenguaje. Debo decir que yo mismo he utilizado este texto como soporte para grupos de programadores trabajando con herramientas sofisticadas en Smalltalk. Smalltalk Best Practice Patterns - Volume 1: Coding, por Kent Beck. Errr ... no es un error de tipografa. No he notado los detalles editoriales de este libro porque yo lo he ledo como borrador pre-publicacin. Pero lo incluyo aqu porque no quiero dejar de recomendar al lector con conocimientos de Smalltalk un texto que rene, en forma de patrones software de codificacin, un conjunto de tcnicas bien asentadas utilizadas desde los albores de lenguajes por los mejores programadores Smalltalk. Los patrones de este libro se segmentan en los correspondientes de Comportamiento, Estado, Colecciones, Clases, Estilo de Codificacin y se aderezan por un pequeo ejemplo de conversin de monedas que usa de muchos de tales patrones. Si alguien quiere saber por qu la codificacin en Smalltalk no se semeja a ninguna otra y por qu genera tanta adiccin, lea, lea este libro. Kent Beck, que el lector reconocer como creador de las fichas CRC y activo Smalltalkista y Patronista, lo hace muy bien, de forma que el choque

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 218

inicial respecto de la rara nomenclatura de patrones utilizada se torna pronto en un reconocimiento respetuoso a la experiencia de quien sabe de qu habla (y slo por esto el lector ya debera ir corriendo a adquirir este indispensable libro). LIBROS SOBRE JAVA Java? Java? Java? Pues s, parece que la unin de palabras resonantes (Internet, C++, Smalltalk, herencia, etc.) ha dado en generar un sndrome ansioso respecto de este lenguaje. A buen seguro que cuando el lector revise esta seccin habrn ya aparecido decenas de libros sobre Java, la mayora de ellos criminales o simplemente estpidos. La cuestin es, en lo que a este texto respecta, su comparacin respecto de C++. El lector podr encontrar en internet papeles, ndices, mtodos, referencias e incluso manuales completos, libros en pre-edicin y comentarios diversos a los distintos aspectos del lenguaje/entorno Java. Lo que ocurre es que la naturaleza voltil de internet sigue aconsejando fiar el conocimiento de la seguridad de las hojas impresas. He aqu algunas de ellas: Hooked on Java: Creating Hot Web Sites with Java Applets, por Arthur van Hoff, Sami Shaio y Orca Starbuck, 1995, Addison-Wesley, 0-201-48837-X, con CD-ROM. Los autores, miembros del equipo de desarrollo de Java en Sun Microsistems Inc., exponen en este texto la euforia de un proyecto con una liviandad que causa escalofros. Mi pronta reaccin a la primera lectura del libro fue la de decepcin clara: mucho web, muchos applets, mucha euforia, pero poco lenguaje y demasiadas decisiones de diseo tomadas muy a la ligera, como porque s. Van Hoff es el autor del compilador Java e impulsor de Hot Java, mientras que Shaio dise e implement el conjunto de herramientas de interfaz de usuario (a la vez que el mecanismo de seguridad de los applets) y Starbuck bsicamente se ocup de la documentacin. El libro a menudo refleja la vivacidad de Duke, la mascota Java, y semeja una versin descafeinada de Ecce Homo: Por qu soy tan inteligente?, Por qu escribo tan buenos libros?, Por qu soy un destino?43. Con todo el texto se deja leer y querer, como un buen pasatiempo, pues dedica su mayor parte a la descripcin de applets y de pginas web. El CD-ROM que lo acompaa incluye todos estos applets, cdigo y pginas web de ejemplo y el JDK para Windows 95/NT y Solaris 2.X. As resulta que el libro es totalmente recomendable, pues frente a la tontera de los muchos artculos que inmisericordes ya se han publicado, la ligereza exenta de errores y las opiniones de primera mano finalmente resultan un buen plato. Si no le interesa Internet (o, en el mejor de los casos, Intranet), lo mejor ser, por otro lado, que olvide Java.
43

Recapacite el lector que Nietzsche admir profundamente a Wagner antes de denostarlo por su decadencia insoportable, as que la comparacin musical con el C++ quizs no resulte desafortunada.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 219

Mecklermedias Official Internet World 60 Minute Guide to Java, por Ed Tittel y Mark Gaither, 1995, IDG Books, 1-56884-711-4. Este texto es exactamente lo que anuncia: una gua que se pretende tan supuestamente fcil como el lenguaje que describe. La verdad es que el enfoque sinttico favorece enormemente la comprensibilidad y el lector puede acceder a informacin prctica librndose de bastante basura literaria. As, en 253 pginas, los autores describen las caractersticas bsicas del entorno Java, del lenguaje en s y de los applets, para pasar a examinar con ms detalle estos ltimos en el contexto de internet/html, y despus exponer varias tcnicas de codificacin de aplicaciones Java (incluido el ejemplo de un manejador de protocolos) y hablar de su futuro. La descripcin de la gramtica de Java y del API que conforman lenguaje, bibliotecas y Hot Java terminan de redondear el texto. Naturalmente el libro no ensea a programar, sino que ms bien muestra ordenadamente lo que finalmente hay (muchos adverbios). En fin, que lo ms agradable del texto es su carencia de pretensiones. Java!, por Tim Ritchey, 1995, New Riders Publishing, 1-556205-533-X. Se trata aqu de una descripcin del lenguaje/entorno Java con un claro tono pedaggico para programadores y administradores de sistemas. As que tras la tpica introduccin, se establecen procedimientos de instalacin del software, de variables de entorno, etc., para despus pasar a una revisin de tipos, expresiones, estructuras de control, clases, interfaces, paquetes, hilos, excepciones, bibliotecas de clases, AWT, Internet (cmo no?), y dos interesantes secciones sobre el interfaz con C y la mquina virtual Java. Sin duda el libro complementa los dos anteriores. The Java Handbook: The Authoritative Guide to the Java Revolution, por Patrick Naughton, 1996, Osborne McGraw Hill, 0-07-882199-1. Pese al petulante ttulo, ste es quiz el ms completo de los ttulos aqu referidos. Naughton cofund FirstPerson Inc. y particip de forma clave en el proyecto Green que dio lugar finalmente a Java, as que la informacin que aqu se da no es producto de la publicidad del momento. En la primera parte se detalla el lenguaje; en la segunda las clases del mismo y en la tercera el diseo detallado de applets (quiz la literatura ms precisa que hasta ahora haya ledo sobre el tema). El tono es abiertamente anti-C++, pero la gracia es que se pretende justificar cada decisin de Java en razn de las supuestas insuficiencias de C++: as se dice que C++ no es totalmente orientado-a-objetos por execrables razones de compatibilidad y eficiencia (no como Java, claro), y sin embargo se da por sentado que la decisin de Java de no considerar las clases como objetos en favor de la eficiencia es absolutamente encomiable. El libro, con todo, est mucho menos inflado de aire que el de Hooked on Java y su lectura resulta divertida y estimulante, sobre todo en los ejemplos de applets (donde se delata, de paso, la insuficiencia

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 220

clara de la actual versin de la AWT): el applet Impresionista, DynaDraw y Poesa en Imanes. Si slo ha de comprar un libro sobre Java, adquiera ste. The Java Primer Plus: Supercharging Web Applications with the Java Programming Language, por Paul M. Tma, Gabriel Torok y Troy Downing, 1996, Wayte Group Press, 1-57169-062-X. Con un ttulo que podra venderse al peso y muy al estilo de la mayora de los textos de el Grupo Wayte, esta obra intenta un acercamiento general al lenguaje y a las bibliotecas de clases que comprende sin olvidar aspectos como la comparacin con C/C++, etc. El libro es muy completo y asequible, constituyendo una suerte de manual de referencia elemental del lenguaje y su entorno, con muchos dibujos bien cuidados y sin entrar en demasiadas profundidades. El CD que regala incorpora la versin 1 del JDK, ya desfasada en favor del Java Workshop, adems del cdigo fuente usado en el libro, applets incluidos. Nada nuevo, pero, eso s, explicado clarito y agradablemente. La parte III se titula Uso de las capacidades avanzadas de Java y resulta la ms interesante del libro, pues trata de asuntos de red, hilos (threads), estructuras de datos, interfaz con C, grficos y sonidos. LIBROS SOBRE SOFTWARE ORIENTADO-A-OBJETOS El lector podra preguntarse aqu: realmente necesito de textos sobre ideas generales de la orientacin-a-objetos? Qu ayuda me pueden prestar tales ideas en los procesos diarios de codificacin en C++? Bueno, recordemos que C++ es un lenguaje con facilidades para la Programacin Orientada-a-Objetos, y que tal es, en definitiva, la fase de implementacin, tras las fases de diseo y anlisis orientados-a-objetos, de los objetos y sus relaciones modelados en base a los conceptos de orientacin-a-objetos a travs de los que se matiza y visualiza nuestro problema en el mundo real. Las ideas generales de este nuevo paradigma nos pueden ayudar, normalmente de forma inestimable, a encauzar nuestras codificaciones hacia modelos conceptuales ms adecuados a la nueva orientacin, consiguiendo que nuestro software sea ms robusto y fiable. Object-Oriented Software Construction, por Bertrand Meyer, 1988, Prentice Hall, 0-13-629031-0,534 pg. El presente trabajo es, sin duda, la ms rigurosa, acertada e inteligente exposicin de los principios en los que se sustentan los sistemas orientados-a-objetos. A la vez, y esto puede desconcertar al lector inadvertido, es una primera descripcin del lenguaje de programacin Eiffel, del que el Dr. Meyer es directo arquitecto y creador. Pero empecemos con mtodo. La primera parte, "Ideas y Principios", es absolutamente impagable: lo que en ella se expone, substanciado en cinco criterios y seis principios, es frecuentemente usado por m mismo en buena

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 221

parte de los cursos de OOA & OOD que imparto. La exposicin es sorprendentemente concisa, de forma que la revisin de conceptos supuestamente conocidos por el lector se torna en extremo interesante. Tras este anlisis general de los sistemas orientados a objetos, el Dr. Meyer se cuestiona por un lenguaje con facilidades para su implementacin, y como quiera que, segn sus propias palabras, no encuentra ninguno, decide crear el suyo propio, sujeto con exactitud al paradigma de objetos. Aparece as Eiffel, lenguaje orientado a objetos puro donde los haya, de sintaxis tipo Pascal e interesantsimas caractersticas. Pero, interesa esto al programador de C++? As lo creo. El Dr. Meyer no se limita a describir el lenguaje, sino que, como artfice del mismo, explica las disyuntivas en las decisiones de diseo y justifica las medidas adoptadas en cada caso, trayendo a colacin interesantes problemas presentes en muchos de los diseos orientados-a-objetos. Como ejemplo sirva el tratamiento que en el lenguaje se dan a lo que se denominan "precondiciones" y "postcondiciones": su claridad conceptual ha redundado en que, en aras de la modularidad, limpieza y coherencia del cdigo, tal enfoque haya sido posteriormente adoptado por distintas bibliotecas de C++, como, verbigracia, "Tools.h++" de Rogue Wave. Una tercera parte del texto se ocupa de revisiones genricas de lenguajes clsicos de programacin, as como de sus extensiones a objetos, y aun de C++, Smalltalk, Ada, etc. Se revisan tambin cuestiones de herencia y, de forma leve, cuestiones como la persistencia de objetos, que en el momento de publicacin de esta edicin no estaban todava en el ojo del huracn, como ocurre ahora. En los apndices se retoma, por fin, el lenguaje Eiffel a modo de fragmentos referenciales. Se trata, en resumen, de un libro indispensable para cualquier con pretensiones mnimamente serias en el mbito de la OOP: reserven, pues, un hueco en su estante para l. A Book of Object-Oriented Knowledge, por Brian Henderson-Sellers, 1991, Prentice Hall, 0-13-059445-8, 297 pg. El presente libro podra ser considerado como una eficaz introduccin al panorama general de orientacin-a-objetos y, aunque, segn informa el propio autor, el texto pretende ser una gua en el proceso de formacin y aclimatacin de la mentalidad de los lectores al paradigma de objetos (para lo que incluye modelos de transparencias "ad hoc" que pueden ser copiadas y utilizadas como ilustracin de cursos sobre la materia), la obra se constituye, en el fondo, en una esclarecedora revisin, desde una adecuada distancia (y recurdese aqu la frase de Ortega sobre Cleopatra), de los distintos criterios que pueblan, a veces en descorazonador desorden, el universo de los objetos. Se revisan, as, metodologa de anlisis, diseo e implementacin, intentando procurar al lector una suerte de plataforma conceptual bsica desde la que pueda acceder con mayor comodidad a tcnicas concretas. El tiempo, empero, no pasa en balde: actualmente yo uso las transparencias de este texto como soporte en el que basar una crtica de los enfoques ms extendidos de acercamiento a la Orientacin-a-Objetos. O sea, que la historia, como siempre, nos sirve para aprender de ciertos errores justo antes de volver a repetirlos.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 222

Object-Oriented Methods, 2 nd Edition, por Ian M. Graham, 1994, Addison-Wesley, 0-201-59371-8, 473 pg. Es ste un libro caracterizado por la perspectiva globalizadora bajo la que se contemplan las ideas y conceptos de orientacin-a-objetos. La impronta pragmtica britnica se deja notar, y su lectura es realmente amena. El texto comienza con una bien entramada introduccin crono-sectorial a los tpicos de la OOT: conceptos bsicos, lenguajes de programacin orientados-a-objetos, WIMPs, bases de datos relacionales, bases de datos orientadas-a-objetos, etc.; hasta llegar a la parte ms significativa: anlisis y diseo orientados-a-objetos. Aqu Graham, tras una revisin crtica de bastantes mtodos (Coad/Yourdon, Desfray, OOSE, OMT, OOSA, etc.), expone su metodologa (las comillas son mas) SOMA 44, una variacin de Coad/Yourdon a la que se han aadido, simplificando, "triggers". La orientacin-a-objetos es filtrada a travs de la experiencia del autor en los campos de inteligencia artificial e ingeniera del conocimiento y, as, resulta curiosa y enormemente instructiva (a la par que descorazonadora y un tanto pretenciosa), por ejemplo, la facilidad con que Graham aborda la fase de identificacin de objetos y de sus relaciones. La prototipacin aparece descrita, seguidamente, de una forma esclarecedora, para terminar con un vistazo al futuro posible y un muy interesante apndice sobre "objetos borrosos". En fin, se trata de un texto muy aconsejable para aqullos que busquen una visin integradora de las nuevas tcnicas en el continuum de la evolucin informtica. Servir, tambin, para aquellos que deseen contemplar un panorama global de mtodos, herramientas CASE, tendencias y perspectivas en el rea de la OT. No est de ms, al fin, probar un poco de solidez europea frente a las montaas (magnficas, por otro lado) norteamericanas. Object-Oriented Programming, por Peter Coad y Jill Nicola, 1993, Prentice Hall-Yourdon Press, 0-13-032616-X, 582 pgs. y disquete incluido. Bueno, en la misma tnica que otros libros firmados en colaboracin por Peter Coad, es ste un texto divertido, ameno y claramente pedaggico. Tras el ndice, de increble longitud, el lector se encuentra con una obra estructurada en cuatro partes, substanciadas cada una de ellas en un ejemplo completo y en orden creciente de dificultad: "Contador", "Una maquina expendedora", "ventas, ventas, ventas" y "Sigue el flujo", seguido por apndices en que se detallan las caractersticas esenciales de los lenguajes en que se desarrollan tales ejemplos: C++ y Smalltalk. Para el anlisis y diseo de stos se sigue, cmo no, el mtodo y la notacin de Coad/Yourdon, y cada paso es suficientemente explicado. La comparacin de los ejemplos en C++ y Smalltalk sirve, de paso, como incruenta introduccin a ambos lenguajes. Lo cierto es que el libro imbuye fcilmente al lector en el object-thinking, acostumbrndolo a pensar "en objetos", y slo por esto valdra

44

Graham expone SOMA detalladamente en su siguiente texto Migrating to Object Technology.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 223

la pena leerlo. Aparecen, adems, situaciones y decisiones de gran valor pedaggico. La campaa de comercializacin del libro incluye "El Juego de los Objetos", con pelotita, silbatos y fichas de cartn, junto con un vdeo en el que se puede apreciar la vitalidad yanqui de Peter Coad (acompaado por seoritas ligeritas de ropa que sostienen cartones con clases y otras barbaridades). LIBROS DE ANLISIS Y DISEO ORIENTADO-A-OBJETOS (OOA & OOD) A pesar de la apariencia de complejidad que normalmente se suele aplicar a estas fases del proceso de desarrollo software, lo cierto es que, como resulta de mi propia experiencia impartiendo cursos diferenciados de OOP, OOA y OOD, aunque normalmente se empieza por el lenguaje, cuando se revisan los mtodos de anlisis y diseo Orientados-a-Objetos, se hace sentir entre los alumnos una fuerte sensacin de que, comprendidas las bases de estas disciplinas, se pueden aprovechar mejor los recursos de C++. No estoy propugnando que el lector escoja necesariamente una de las metodologas presentes en el mercado, sino que examine el sustrato en el que se apoyan y se apropie de alguna de las tcnicas que en ellas aparecen. Designing Object-Oriented Software, por Rebecca Wirfs-Brock, Brian Wilkerson & Lauren Wiener, 1990, Addison-Wesley, 0-13-629825-7, 368 pg. Este es un texto absolutamente recomendable, sin contrapartida alguna, a aqullos que buscan iniciarse en las procelosas aguas del Diseo Orientado-aObjetos. Esto no significa, empero, que se trate de un libro elemental: de hecho, la solidez conceptual en la que se apoya convierte al texto en una muy fructfera fuente y base referencial para profesionales y equipos con experiencia en Tecnologa de Objetos. Esta obra intenta, en sntesis, proporcionar un mtodo de OOD independiente de lenguajes y aun de notaciones especiales. Dado que el autor del presente libro es especialmente sensible a lo que se conoce como diagramana (esa costosa, compleja y contraproducente acumulacin de dibujos y conexiones, escasamente diferenciados entre s, y que suelen conducir a analista, diseador, cliente y, en general, a cualquiera que inocentemente los examine, a un estado de perplejidad cercano al catatnico), la exposicin que aqu se realiza, capitaneada por Wirfs-Brock, es como una burbuja de oxgeno en la luna. El grueso del libro trata de lo que otros, en esta misma materia, dan mayormente por supuesto o examinan muy brevemente: la identificacin y asignacin de objetos y de sus interrelaciones. Para el tratamiento de la informacin relacionada con el proceso de OOD se usan las denominadas fichas CRC (Clase-ResponsabilidadColaboracin): en cada una de ellas se significa el nombre de la clase, si es abstracta o no, las superclases y las subclases de la misma, una sucinta descripcin de su cometido, las responsabilidades que asume (esa suma de un cierto tipo de conocimiento que la clase posee y las acciones que puede efectuar), y las colaboraciones necesarias para cumplimentar cada una de sus responsabilidades

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 224

(esto es, la relacin de clases necesarias para llevar a cabo las tareas o responsabilidades asignadas y para las que la clase no es autosuficiente). Se trata en sntesis del siguiente proceso: en una primera etapa exploratoria se produce la identificacin de clases, identificacin de clases abstractas, identificacin y asignacin de responsabilidades e identificacin de colaboraciones; en la siguiente etapa, denominada de anlisis, se modela la construccin de jerarquas (clases en derivacin), se identifican los contratos (una serie cohesiva de responsabilidades normalmente requeridas por otras clases) y se asignan a las colaboraciones, se identifican los subsistemas (abstracciones que permiten un manejo ms adecuado del sistema global a modelar), se refinan las colaboraciones y se protocolizan las responsabilidades (esto es, cada una de las responsabilidades se transforma en el prototipo de una funcin). Se obtiene, al final, algo as como una estructura de clases y sus relaciones vaca de implementacin. Pero es que la implementacin no es lo importante: la identificacin de las responsabilidades (por servicios) pblicos de las clases permitir fragmentar la implementacin de clases de una manera adecuada para el trabajo en equipo (una clase o serie de clases pueden serle asignadas a una persona, por ejemplo, y sta nicamente sabr del resto de las clases que pueden ser accedidas a travs de un protocolo pblico ya bien definido, independientemente de su implementacin concreta). El seguimiento del clsico ejemplo del cajero automtico es particularmente revelador sobre el proceso de diseo expuesto, con abundantes comentarios y la explicacin detallada de las decisiones tomadas. Este ejemplo, y otros, estn expuestos en su totalidad en los apndices del libro. Expuesto lo anterior, reitero mi recomendacin de uso de este libro quizs como el primer libro de OOD que los principiantes debieran estudiar. Using CRC Cards: An Informal Approach to Object-Oriented Development, por Nancy M. Wilkinson, 1995, SIGS Books, 1-884842-07-0 (Prentice-Hall 0-13374679-8), 226 pgs. Frecuentemente he odo que el anterior libro est muy bien, pero que slo proporciona vagas ideas para emprender algo parecido a una transicin mental al universo de los objetos. Naturalmente esa es la idea, pero no hay que olvidar el mtodo que la respalda: las fichas CRC son enormemente tiles para afrontar un desarrollo orientado-a-objetos. S, s, pero cules son los pasos a seguir en un equipo real trabajando en un proyecto real? Bueno, este texto aporta varias buenas ideas hilvanadas por una narracin bien asida a la tierra. El ejemplo de gestin bibliotecaria, que discurre por toda la obra, resulta adecuado, en tanto que permite otear distintos escenarios y problemas, de forma que los dilogos de los componentes del equipo de desarrollo (pues el libro simula una especie de cuaderno de bitacora dialogado) devienen reconocibles y clarificadores. Las fichas CRC se muestran, pues, adems de como excelentes herramientas exploratorias, en calidad de paso previo a mtodos formales como Booch, Shlaer-Mellor, etc. Se muestran algunas herramientas de gestin de fichas CRC (como ObjectSystem/CRC de Rational), y un captulo entero se dedica a lo que muchos lectores

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 225

declararn inestimable: el mapeo de las fichas a construcciones C++. Oh, el libro no expone ninguna idea de pasmo, pero la descripcin del conjunto de prcticas de uso de fichas CRC constituye un manual perfecto para un primer proyecto de migracin a la Tecnologa de Objetos, as como el texto es excelente para un curso complementario del mtodo de Wirfs-Brock, o an para la enseanza primera de la Tecnologa. Object-Oriented Modeling and Design, por James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy & William Lorensen, 1991, Prentice Hall, 013-629841-9, 528 pg. En este libro se expone una metodologa de anlisis y diseo orientados a objetos, que abarca el ciclo completo de desarrollo de software, creada por el equipo de investigacin de General Electric liderado por James Rumbaugh. De todas las metodologas propietarias examinadas aqu, sta es una de las ms completas y, a la vez, la que menos reniega de las bien conocidas metodologas de anlisis y diseo estructurados en las que abiertamente se basa. Los autores plantean el traslado del dominio del problema en el mundo real al campo software a travs del modelado de los objetos que aparecen en aqul, junto con sus relaciones. Y aunque esto mismo podra decirse de cualquier otro tcnica de OOA&OOD, el mtodo aqu expuesto, denominado OMT (Object Modeling Technique: Tcnica de Modelado de Objetos), se descompone en tres submtodos: el modelado de objetos, el modelado dinmico y el modelado funcional. Examinemos, por su inters, aun de forma sucinta, estas tres subtcnicas: en el modelo de objetos se describen, con una notacin clara y precisa, los atributos y las relaciones estticas entre los clases a que pertenecen los objetos del problema y sus relaciones ya modeladas; en el modelo dinmico se exponen, mediante diagramas de transicin de estados, los aspectos del sistema relacionados con el control del esquema secuencial y temporal de las operaciones que afectan a los objetos modelados, usando, para mayor facilidad en la comprensin del diagrama, la abstraccin de Harel que permite el anidamiento de subsistemas de estados; en el modelo funcional se exponen, por ltimo, los aspectos del sistema relacionados con las transformaciones de la representacin interna de los objetos modelados, ya expresadas estticamente como operaciones en el modelo de objetos, a travs de los muy conocidos diagramas de flujo de datos. Quiz el modelado funcional resulte el de peor acoplamiento en las bases conceptuales de un esquema de objetos, pero, aun as, su interrelacin con las dems tcnicas es modlica. Estos tres modelos se engarzan a travs de lo que se pretende -o mejor, adivina- sea un esquema no secuencial de fases: anlisis, diseo del sistema y diseo de objetos. La exposicin final de ejemplos (un compilador de diagramas de objetos, animacin computerizada y un sistema de diseo de distribucin elctrica) es un excelente complemento de esta tcnica. Estamos, en definitiva, ante un excelente texto, aderezado con comentarios ms o menos acertados sobre bases de datos relacionales y con extensiones a objetos, lenguajes no orientados-a-objetos, etc.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 226

Se aprecia, por ltimo, una importante caracterstica de cohesividad a lo largo de la exposicin de la metodologa que le proporciona una solidez conceptual a que otras son ajenas. La OMT ha ido ganando, desde su publicacin, adeptos entre los usuarios de OOA&OOD, habindose posicionado, en estas fechas, como una de los mtodos de uso ms extendido. Se utilice o no esta tcnica, lo cierto es que el libro es, en todo caso, una valiossima contribucin a cualquier biblioteca de OT. General Electric ha desarrollado una herramienta denominada OMTool para distintas plataformas que computeriza estas tcnicas, pero lo cierto es que prcticamente cualquier herramienta actual multi-mtodo soporta OMT. Finalmente el mtodo se ha asociado de forma indisoluble con James Rumbaugh, que junto con Grady Booch e Ivar Jacobson en Rational estn pariendo un entente unificado que ya ha cambiado de nombre ms de una vez. Oh, divina eclecsis! Object-Oriented Analysis and Design with Applications, 2nd Edition, por Grady Booch, 1994, Benjamin/Cummings, 0-8053-5340-2, 589 pg. Este libro, muy en la lnea de extensa difusin del anterior, es uno de los ms considerados por la comunidad de OT. Constituye la perfecta continuacin (a pesar de su independencia y aun a pesar del sr. Booch), con un carcter marcadamente propio, del texto de Wirfs-Brock. Como la mayora de los textos en OOA y OOD, su primera seccin (Conceptos) empieza por una revisin de los conceptos bsicos de la orientacin a objetos, tales como clases, objetos, etc., exponiendo distintos mecanismos para la identificacin de estos dentro del dominio de un problema: esta parte es grandemente reflexiva y procura una bien fundada iniciacin a la Tecnologa de Objetos. La segunda seccin (El Mtodo) expone el mtodo de OOD de Booch, junto, cmo no, a su correspondiente notacin (donde aparecen las famosas nubes), a ms de convenientes consideraciones prcticas. La ltima seccin (Aplicaciones) detalla lo que Booch denomina ejemplos notriviales en que se aplica lo hasta entonces visto. Lo curioso es que, tras una primera y exitosa edicin en la que Booch ejemplificaba su mtodo mediante cdigo en CLOS, C++, Smalltalk, Ada y Object Pascal, esta segunda edicin dedique sus ejemplos con exclusividad al C++ (a la vez que ha aadido el vocablo Analysis a su ttulo, aunque sin demasiada representatividad real). Un apndice sobre lenguajes de programacin orientados y basados en objetos, adems de 58 pginas repletas de bibliografa completan el volumen. Nos encontramos, pues, ante uno de esos raros textos densos en contenido y, a la vez, de brillante practicidad y fuertes capacidades referenciales. Piense el lector que uno de los "reproches" que se le imputan a Booch es la "excesiva riqueza" de su notacin. Mi consejo? Este debe ser el segundo o, a lo sumo, tercer libro de diseo que adquieran. Y en cuanto a herramientas destaca la bien conocida Rational Rose, pero lo cierto es que este mtodo lo soportan casi todas las herramientas actuales.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 227

Migrating to Object Technology, por Ian M. Graham, 1994, Addison-Wesley, 0201-59389-0, 552 pg. El autor extiende su anterior libro Object Oriented Methods con esta obra, dividida en dos claras partes: en la primera se examinan distintas cuestiones relacionadas con el proceso de migracin hacia la Tecnologa de Objetos (necesidad, oportunidad, beneficios, problemas, interoperacin, reso, interfaces grficos, almacenamiento de objetos, sistemas distribuidos y sistemas expertos), y en todas ellas se analizan dificultades, beneficios, direcciones, oportunidades y realidades comerciales; en la segunda parte se detalla como abordar este proceso de migracin utilizando SOMA, con un muy interesante captulo dedicado al anlisis y captura de requerimientos y una siempre bienvenida exposicin dedicada a mtricas orientadas-a-objetos (Graham, por parte de la Corporacin Suiza de Banca, es uno de los promotores del Club de Mtricas Orientadas-a-Objetos). No faltan las referencias extensas a la re-ingeniera de procesos de negocio y los aspectos de diseo fsico e implementacin para completar un libro redondo que, no obstante, se complementa perfectamente con aqul primero del autor. El libro esconde, finalmente, un disquete con una versin truncada (sin capacidades de impresin) de una herramienta no-CASE denominada SOMATiK, que intenta automatizar el uso de SOMA. Object-Oriented Analysis, 2nd Edition, por Peter Coad & Edward Yourdon, 1991, Yourdon Press/Prentice Hall, 233 pg. Nos encontramos ante la segunda edicin de uno de los primeros textos aparecidos en el mercado sobre OOA. Esta premura editorial consigui que las ideas propuestas por Coad y Yourdon se extendieran con gran rapidez, siendo as que este mtodo ha permanecido durante mucho tiempo como uno de los ms ampliamente difundidos. El libro es uno de los ms breves de los comentados en este anexo y est escrito en un lenguaje coloquial de muy fcil lectura. Los conceptos bsicos del paradigma de objetos se exponen con la ayuda de definiciones de diccionarios y enciclopedias. La graficacin, una de las primeras y, por tanto, de las ms rudimentarias en este campo, bsicamente expone el resultado grfico de la herramienta comercializada por los autores (OOATool). Las secciones de introduccin y comparacin de distintas metodologas de anlisis anteriores al OOA (Yourdon-de Marco, Jackson, etc.) son agradablemente sucintas y claras. Lo nico que se puede reprochar es la falta de un formalismo metodolgico prctico que permita al lector hacer uso de lo aprendido. De hecho el lector se queda al final del texto con una cierta sensacin de borrachera de objetos, generada en buena medida por el nfasis y la excitacin con que los mismos autores tratan a la OT, pero sin direccionamiento prctico claro en el que sostener sus primeros pasos en este campo. El libro es, pues, perfectamente aconsejable como texto introductorio a OOA.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 228

Object-Oriented Design, por Peter Coad & Edward Yourdon, 1991, Prentice Hall, 0-13-630070-7. Estamos ante una clara continuacin del anterior libro de los autores sobre OOA, que usa de una extensin apropiada a OOD de la herramienta de anlisis OOATool de los autores. Tras una leve introduccin (pues el texto, como el anterior, es singularmente corto), se repasa la metodologa de Anlisis orientado-a-objetos de Peter Coad: un modelo multicapa (sujeto, clase-objeto, structura, atributos y servicios) y multicomponente (dominio del problema, interaccin humana, gestin de tareas y gestin de datos), con una notacin especfica de aplicacin. Los autores intentan, con cierto xito, integrar de forma incruenta las tcnicas de OOD con las del proceso de OOA, para pasar despus a exposiciones sobre sectores de parcial inters, como el de las herramientas CASE o los distintos lenguajes de programacin. El texto, con las mismas salvedades de la obra anterior, es totalmente recomendable como introduccin no reglada al campo del OOD. Object-Oriented Analysis: Modeling the World in Data, por Sally Shlaer & Stephen J. Mellor, 1988, Yourdon Press/Prentice Hall, 144 pg. Tenemos aqu a uno de los pocos textos serios focalizados en el rea de anlisis orientado-a-objetos. Con un corto nmero de pginas, la obra comienza con una simptica introduccin a los tpicos conceptos bsicos, pasando a poco a clasificar los objetos en: tangibles, roles, interacciones, incidentes y especificaciones (he de reconocer que esta fragmentacin conceptual yo siempre la he asumido como de identificacin de clases). Seguidamente expone un modelo de control textual de especificaciones de clases como soporte de la tcnica desarrollada por los autores y denominada modelado de informacin. No es ste un libro que proporcione un bagaje semejante al de Wirfs-Brock, ni la tcnica en l descrita es particularmente fcil de aplicar, pero, con todo, el texto ofrece detalles muy interesantes para el estudioso, as como ejemplos altamente intuitivos y de ilustraciones autoexplicativas. Object Lifecycles: Modeling the World in States, por Sally Shlaer & Stephen J. Mellor, 1991, Prentice Hall, 0-13-629940-7. Esta obra estudia, tras un breve repaso comprehensivo de la anterior obra de los autores, el comportamiento dinmico de los sistemas de objetos. stos se asimilan a mquinas de estados (as como las clases a modelos de estados), de tal forma que el ciclo de vida de un objeto puede modelarse como un conjunto de estados, de eventos, de reglas de transicin y de acciones. Seguidamente se muestra el desarrollo de las relaciones entre objetos afectadas por el tiempo, para pasar despus a la exposicin de los mtodos de modelado de secuenciaciones de eventos y terminar con una extensin de los diagramas de flujos de datos denominada ADFD y referida a los datos asociados a acciones de los objetos. Se exponen diversas posibles aplicaciones de la tcnica de la obra y se muestran

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 229

algunas lneas de migracin a esta metodologa desde el enfoque estructurado. En definitiva nos encontramos ante el perfecto compaero de la anterior obra. Object-Oriented Systems Analysis: A Model-Driven Approach, por David W. Embley, Barry D. Kurtz & Scott N. Woodfield, 1992, Prentice Hall, 0-13-6299733, 302 pg. He aqu, a mi entender, una de las aportaciones ms significativas realizadas en los ltimos tiempos al rea del anlisis orientado-a-objetos. Los autores proveen, a ms de una definicin formal de su mtodo de anlisis (OSA: Object-Oriented Systems Analysis) basado en lo que llaman ORM (Object-Relationship-Model), de la que carece el resto, una nueva y rica notacin que se aplica con exactitud al nuevo enfoque de aproximacin al OOA: relaciones, estados y modelos de interaccin de objetos. Si bien los modelos de relacin y de estados son fcilmente asimilables (salvadas ciertas distancias) desde otras metodologas (diagramas entidad-relacin, etc.), el modelo de interaccin reemplaza al clsico diagrama de flujo de datos. El tratamiento dado, de cualquier forma, a las relaciones es particularmente rico y revelador: stas aparecen ya como objetos reales, y la notacin cualificadora de los conjuntos de relaciones resulta increblemente clara, en perfecto desarrollo de aproximaciones ms tradicionales como la de Rumbaugh (OMT). La obra contiene una gran cantidad de ejemplos y cuestiones (existe un libro adicional con la respuesta a los ejercicios propuestos) sencillamente perfectos. El captulo introductorio es, por otro lado, suficientemente explicativo, y el ejemplo del trayecto en la ciudad es realmente bueno. Bien: su biblioteca quedara incompleta sin esta obra. As de simple. Object-Oriented Software Engineering: A Use Case Driven Approach, por Ivar Jacobson, Magnus Christerson, Patrik Jonsson y Gunnar vergaard, 1992, Addison-Wesley, 0-201-54435-0, 524 pgs. Pocos libros han influido tanto, tan rpido y tan extensamente en la comunidad de objetos como el presente, de forma que los Casos de Uso que en l se exponen (entre otras ideas) fueron inmediatamente adoptados, en mayor o menor medida, por la prctica totalidad de los otros mtodos. El texto entero supone una aproximacin fundada a lo que debiera ser la ingeniera de software orientada-a-objetos y su legibilidad es francamente excelente, de forma que maliciosamente se aconseja su lectura a gestores y responsables de proyectos. El texto empieza -cmo no?- con una parte introductoria (ms prctica, a mi gusto, que la de Booch), para en la segunda parte abordar una pila de conceptos esenciales (arquitectura, anlisis, componentes, validacin, etc.) y terminar con una tercera parte dedicada a la gestin prctica de proyectos, con dos captulos dedicados a sendos ejemplos, una cierta gua mnima de gestin de proyectos y un repaso de algunos otros mtodos de OOA/OOD. El libro es claro y preciso, pues se apoya en los muchos aos de experiencia de su autor principal, pero hay que advertir (y en el texto se

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 230

nota sin tapujos) que no es ms que un breviario del mtodo de Jacobson (Objectory), de forma que algunos de mis clientes no han comprendido el alcance del mismo hasta que han pagado la licencia del mtodo entero. Object Oriented Program Design with Examples in C++, por Mark Mullin, 1990, Addison-Wesley, 0-201-51722-1, 303 pg. Este texto ha llegado a ser muy popular entre un cierto sector de la comunidad C++, principalmente entre los desarrolladores provenientes de C y de esquemas de diseo estructurado, debido quizs a la inmediata practicidad de los conceptos que, sin esquematizacin rigurosa, se van proponiendo: es como si se diseara en C++. El autor asume un ejemplo (la creacin de una base de datos corporativa para Bancroft Trading Company) y en sucesivos captulos va refinando su diseo. La mayor ventaja para algunos de este libro (su proximidad a la vida real) es, sin embargo, tambin su principal defecto, pues aparte del diseo de bases de datos la importancia habra de traspasarse a la identificacin de clases y relaciones, algo que en el texto se relega a un segundo plano. Planteada esta observacin, por lo dems el libro es levemente recomendable como primer estadio de paso en la codificacin C++ basada en la conceptualizacin de objetos, sin demasiadas pretensiones adicionales. Yo dira que sin ninguna pretensin adicional. A Complete Object-Oriented Design Example, por Joseph E. Richardson, Ronald C. Schultz & Edward V. Berard, 1992, Berard Software Engineering Inc, 1-881974-01-4, 350 pg. Se suele echar de menos, al introducirse en el terreno del OOD, la disponibilidad de un ejemplo completo, en todas su fases, que rellene esas carencias, obviadas por una cuestin esencial de espacio en otros textos, y que colocan al novicio en disyuntivas normalmente difciles de superar. El presente texto intenta cubrir tan urgente necesidad. El lector fcilmente podr apreciar que en el libro se explicitan, con toda clase de detalles, las fases consideradas ms farragosas y de trabajo ms tedioso, normalmente substanciadas en listas selectivas: listas y ms listas. Se usan, despus, diagramas de transicin de estados, redes de Petri y diagramas de Booch para resolver el problema de diseo de una utilidad de concordancias, tpica de un procesador de textos. Finalmente se detalla la implementacin completa de la solucin encontrada, tanto en Smalltalk como en C++. En el apndice se detallan distintas especificaciones para terminar con una exposicin parcial de las diapositivas empleadas por la ya desaparecida firma de ingeniera de software, editora del libro, en sus cursos y trainings de OOD. El resultado? Una aproximacin pedaggica al mundo real con un ejemplo no del todo de juguete.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 231

Working With Objects: The OOram Software Engineering Method, por Trygve Reenskaug con Per Wold y Odd Arild Lehne, 1996, Manning Publications, 1884777-10-4 (Prentice Hall: 0-13-452930-8) Atencin, lector: a mi entender este es uno de los textos ms importantes publicados en los ltimos aos sobre construccin de sistemas software, de forma que arriesgarse a ignorarlo es comprometerse con la oscuridad. Sepa el lector, de cualquier forma, que no soy fantico: slo vehemente. Esto es, en el texto se explicitan muchas ideas que a m me parecen no slo naturales y adecuadas, sino tambin inteligentes, efectivas y, finalmente, humanas. Es curioso que sean los trabajos europeos, y sobre todo los del norte, los que enfaticen la primordial importancia del factor humano en la construccin de sistemas software. El libro contiene, adems, un importante componente pedaggico, pues evidencia los importantes logros conseguidos mediante el uso prudente de Smalltalk y de la ms general Tecnologa de Objetos en una empresa (Taskon) a lo largo de ms de 25 aos. El autor principal, Trygve Reenskaug, es, adems de un reputado experto en el campo de la Orientacin-a-Objetos, el creador del concepto Modelo-Vista-Controlador (MVC) que seguro todos conocen. El libro destila inteligencia y sentada experiencia en todas sus pginas, a la vez que pone de manifiesto un principio que no por evidente se aplica en otros mtodos: las mismas tcnicas empleadas en el anlisis y diseo de software debieran servir para el anlisis y diseo de organizaciones humanas. En fin, casi me aventuro a proclamar: si slo han de comprar un libro sobre objetos, adquieran ste. LIBROS SOBRE PATRONES DE DISEO Hay unos cuantos textos relacionados con los patrones de diseo software, buena parte de ellos de Alexander, naturalmente. Para evitar el pataleo de los lectores, resear brevemente las obras de arquitectura. He aqu mi seleccin: Notes on the Synthesis of Design, de Christopher Alexander, 1964, Harvard University Press. Este es el texto basado en la tesis doctoral de Alexander, y base, a la vez, del estudio de Alexander sobre el sistema BART, en el que el autor establece por vez primera que la funcionalidad del sistema no depende tan slo de un conjunto de requerimientos. Y si esta idea, sabindola no originaria de la escritura automtica, no despierta la curiosidad del lector, nada podr hacerlo. A Pattern Language: Towns/Building/Construction, de Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King y Shlomo Angel, 1977, Oxford University Press, 0-19-501919-9. 253 patrones, con el formato especfico propuesto por Alexander y repartidos en

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 232

1.171 pginas (muchas pero pequeas y con fotos e ilustraciones, no tema el lector), se dan cita en este texto (ya difcil de conseguir), en el que adems se propugna una integracin del mejor-vivir con el medio fsico circundante: gente-gentepatrones-gente. Cuando se habla del libro de Alexander (CA patterns book) o del libro AIS (las iniciales de los primeros autores) se refieren a esta obra. Para que el lector se forme una adecuada idea del tono del libro, sirvan estos ejemplos descafeinados y salvajemente simplificados: Cmo se sabe que un parque est adecuadamente insertado en el terreno urbano? !Cuando los mendigos duermen en l! Dnde deben construirse las paradas de autobuses: en zonas tranquilas o en zonas de bullicio vital urbanstico? Pues en ... humm, dejar que el lector lea el libro. Realmente estas ideas tienen impacto en los arquitectos noveles (como las ideas de Le Corbusier sobre las medidas humanas de las farolas, etc.), para bien o para mal. The Oregon Experiment, de Christopher Alexander, 1978, Oxford University Press. Aqu se explicitan los planteamientos participativos (usuarioconstructor/diseador) puestos en prctica en el plan maestro de Berkeley de 1970. El resultado, fiel a la trayectoria prctica alexanderiana, no fue el esperado. The Timeless Way of Building, de Christopher Alexander, 1979, Oxford University Press. Junto con el de A Pattern Language sta es una de las obras ms difundidas de Alexander. Si a estas alturas ya soportamos bien el estilo pseudo-filosficoreligioso del autor, el texto merece la lectura, pues en l se establecen las bases de una arquitectura post-industrial creada por la gente. The Production of Houses, de Christopher Alexander, 1985, Oxford University Press. Se relata aqu la desafortunada historia del fallido proyecto de construccin de una comunidad en Mexicali. Este texto es especialmente interesante por cuanto en l Alexander reflexiona sobre los problemas y carencias que llevaron al fracaso del proyecto. Algunas reflexiones resultan emocionalmente ingenuas (sobre todo las relacionadas con la escasa comprensin del gobierno mexicano), pero de ellas se desprende un tono de advertencia al que los nuevos apstoles de los DPs no debieran resultar ajenos. Advanced C++ Programming Styles and Idioms, por James O. Coplien, 1992, Addison-Wesley, 0-201-54855-0. Desde su publicacin he venido recomendando efusiva e insistentemente este inteligente libro a todo aqul que de verdad quiera conocer el lenguaje C++ y aun

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 233

usarlo. Resulta claro ahora, como el mismo autor expresamente reconoce, que los idiomas aqu descritos son en realidad patrones, presentados empero sin formato definido. El libro es, pues, doblemente (mi comentario ya se di en la seccin de C++ Avanzado) imprescindible. Design Patterns: Elements of Reusable Object-Oriented Software, de Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides, 1995, AddisonWesley, 0-201-63361-2. Este texto se conoce como GOF book o libro del GOF (Gang-of-Four: Clan-delos-Cuatro, en evidente referencia a los autores del texto), y es sencillamente indispensable para cualquiera interesado en los patrones de diseo. Tras una adecuada introduccin conceptual se introduce al lector en un caso prctico (un editor WYSIWYG) y ante los sorprendidos ojos de ste desfilan patrones donde no pareca haberlos. Seguidamente se detallan distintos patrones agrupados en tres subcatlogos: de creacin, estructurales y de comportamiento, con ejemplos en C++ y Smalltalk. Por su solidez este libro puede hacer cambiar de parecer a los que pudieran pensar que es demasiado pronto para redactar un catlogo de patrones. Puedo contarles que, habiendo impartido varias conferencias sobre patrones, los asistentes que finalmente leyeron el libro llegaron a confesarme que no haban valorado bien la practicidad de las ideas que en l se exponen hasta que lo vieron y leyeron con sorpresa y satisfaccin. En fin, imprescindible: tanto para los programadores de C++ como ... para cualquiera. Design Patterns for Object-Oriented Software Development, de Wolfgang Pree, 1995, Addison Wesley. Tras un breve examen de la historia, estado y clasificacin de los patrones (patrones orientados a objetos, patrones de codificacin, recetarios de marcos, contratos formales y catlogos de patrones de diseo), Pree nos adentra en los metapatrones, o piezas reusables que encierran el diseo de complejos marcosentornos. En realidad el libro trata sobre marcos (frameworks), y sobre cmo puede encontrarse en estos (bien establecidos y maduros) un conjunto mnimo de metapatrones transportable al desarrollo de otros marcos. Pree expone siete metapatrones y despus aboga por su integracin en el proceso de OOA/OOD mediante lo que l mismo denomina Hot-Spot-Driven Design (HSDD: diseo enfocado-a-zonas-sensibles, en insana traduccin). En esencia, una Zona-Sensible es, respecto de un escenario de diseo, un rea bien delimitada susceptible de cambio (esto es, un rea flexible). El texto es interesante, con varias referencias al libro GOF, pero quizs se centra demasiado en el acadmico (aunque tremendamente interesante) ET++ (un marco para desarrollo de GUIs) obviando otros marcos comercialmente bien establecidos; a la vez, las referencias a los patrones de codificacin en C++ resultan un tanto ingenuas. El libro resulta, con todo, recomendable para aqullos que pretender historizar su tesis doctoral haciendo

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 234

sayo en ella de la tecnologa entera. Humm ... Quise decir pretencioso? Pattern Languages of Program Design, editado por James O. Coplien y Douglas C. Schmidt, 1995, Addison-Wesley, 0-201-60734-4. Tras leer el libro GOF uno podra preguntarse si el crculo de patrones all expuesto podra fcilmente ampliarse. La primera conferencia sobre Pattern Languages of Program Design (PLoP) supuso la confirmacin prctica de las expectativas generadas. En el presente libro los editores han reunido, comentado y unificado el material de tal conferencia, que se caracteriz por una organizacin singularmente efectiva: los papeles no fueron expuestos por los autores, sino por distintos conjuntos de revisores que expusieron al pblico las bondades y flaquezas encontradas en cada uno de los patrones presentados. Los 30 patrones presentados en esta obra son eminentemente textuales (en el sentido clsico de patrn de Alexander), y se han dividido en Marcos, Sistemas y Procesos Distribuidos, Objetos de Negocio, Procesos y Organizacin, Patrones de Diseo y Catlogos, Arquitectura y Comunicacin, Uso de Objetos y Estilo, para terminar con Eventos y Manejadores de Eventos. El libro representa para el lector la oportunidad de desligar los patrones de tal o cual lenguaje de programacin y resulta, a la par que entretenido, grandemente revelador sobre las nfulas que debieran animar los procesos de construccin de software. LIBROS SOBRE BASES DE OBJETOS La literatura sobre la mixtura de Bases de Datos y Orientacin-a-Objetos y, en general, sobre sistemas persistentes est poblada de informes tcnicos, de implementaciones comerciales y de aventurados esquemas de investigacin. En la bibliografa que sigue me centrar en los ttulos que no requieren un bagaje tcnico excesivo, favoreciendo las visiones simplistas que, al final, generan una cierta cultura de Bases de Objetos. Object-Oriented Concepts, Databases, and Applications, editado por Won Kim & Frederick H. Lochovsky, 1989, Addison-Wesley, 0-201-14410-7. Este temprano texto contiene artculos muy citados (como el de Roger King, Mi Gato est orientado-a-objetos, que proporciona una leve visin sobre modelos semnticos), aunque los dedicados a las bases de objetos han quedado un tanto historizados, manteniendo empero unos aspectos intencionales de lectura aconsejable. Object-Orientation: Concepts, Languages, Databases, User Interfaces, Setrag Khoshafian & Razmik Abnous, 1990, John Wiley & Sons, 0-471-51801-8. Este libro es un tanto viejo y bastante elemental, aunque confieso que le dispenso

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 235

cierta simpata (que por definicin podra calificarse de afinidad con lo intil). Las ideas presentadas aqu son claras -por simples- y leves -por meramente intuitivas-: as, por ejemplo, la parte dedicada a Interfaces de Usuario Orientados-aObjetos rebosa candor desde nuestra perspectiva actual. El libro se constituye, pues, en una introduccin amable a esta rea tecnolgica. Las Selecciones del Readers Digest seran una buena comparanza. Object Data Management: Object-Oriented and Extended Relational Database systems, R.G.G. Catell, 1991, Addison-Wesley, 0-201-53092-9. Este es uno de los textos ms apreciados por gestores en relacin al soporte de decisiones sobre las Bases de Objetos. Cattell, un activista del sector, plantea un texto con afn de completitud que revisa todos los tpicos de la Tecnologa, incluyendo un repaso de sistemas tradicionales, una panormica de los nuevos conceptos de gestin de informacin, algunas ideas sobre implementacin, un detalle de objetivos y la revisin sumaria de bastantes productos, para acabar con unas agradables referencias bibliogrficas brevemente comentadas. Object-Oriented Databases, Setrag Khoshafian, 1993, John Wiley & Sons, 0471-57056-7. Yo dira que este es un texto para gestores (managers) en el que, tras la consabida y evitable introduccin genrica a la Tecnologa de Objetos, se muestran algunos aspectos bsicos y prcticos de las OODBMSs: modelado, diseo, persistencia, versionamiento, transacciones, concurrencia y ... arquitectura clienteservidor. Se puede leer de un tirn, lo que es bueno y malo, naturalmente. En fin: se trata de una introduccin no acadmica a un rea que adolece de demasiado formalismo huero, as que el lector puede aplicarse el auto-test y decidir. Sistemas de Bases de Datos Orientadas a Objetos: Conceptos y Arquitecturas, Elisa Bertino & Lorenzo Martino, 1993 (traduccin 1995), AddisonWesley Iberoamericana, 0-201-65356-7. Hay que decir que el Dr. Miguel Katrib ha realizado una traduccin magnfica de este texto, que se transforma as en el nico en castellano que aborda de forma seria algunos aspectos genricos tericos y prcticos sobre las Bases de Objetos: indexacin, consultas, evolucin dinmica de objetos y esquemas, modelos de datos y mecanismos de autorizacin se sopesan entre ejemplos aplicados, fundamentalmente, a GemStone, O2 e Iris. Siendo, empero, un texto acadmico recomendable, adolece de cierta vaguedad anmica si se considera como lectura de convencimiento para gestores de proyectos y programadores en general. En resumen: si su biblioteca ha de constar de ms de cincuenta libros, compre tambin ste.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 236

The Object Database Standard: ODMG-93, editado por R.G.G. Catell, 1994, Morgan Kaufmann Publishers, 1-55860-302-6. Con la intencin de normalizacin de facto subyaciendo en cada prrafo, este libro, instructivo y afortunadamente breve, es de lectura obligada no tanto por la realidad que refleja sino por la pretensin formalizadora que insufla. OMG est muerto? No sabra decirlo, pero su cadver (en todo caso) atrae muchas moscas. Object-Oriented Databases: Technology, Appllications and Products, Bindu R. Rao, 1994, McGraw-Hill, 0-07-051279-5. En este libro asistimos a una demostracin de conocimientos prcticos un tanto deslavazada, aunque til para determinados lectores: Rao nos lleva a galope por captulos triviales y relatos recopilatorios entre los que cruzan exposiciones de algunas Bases de Objetos comerciales: ObjectStore, Versant, Objectivity/DB; y en menor medida GemStone, IRIS, UniSQL y otras. El texto aparece adecuado para gestores que deseen asimilar de forma rpida las tcnicas y esquemas ms usados en los productos comerciales, aunque adolece de coherencia. Yo suelo, no obstante, recomendar la lectura directa de los manuales de las distintas OODBMSs, pues stos suelen incluir unas buenas introducciones genricas y usualmente estn pedaggicamente estructurados para su pronta asimilacin. Object Databases: The Essentials, Mary E. S. Loomis, 1995, Addison-Wesley, 0-201-56341-X. Debo reconocer mi debilidad por la Dra. Loomis: el libro, al igual que sus columnas peridicas en el JOOP, est escrito en un lenguaje sorprendentemente claro que hace gala de un pragmatismo agradable y natural. La exposicin est bien estructurada, es amena, encaja a la vez con un pblico tcnico y de gestin, y resulta, al fin, en un buen sabor post-lectura. La asuncin, por otra parte, de distintos puntos de vista (del administrador, del programador, etc.) confiere al texto una perspectiva nica que se convierte en perfecta gua respecto de las distintas opciones tericas: si la persistencia ha de ser ortogonal al tipo, si el enfoque pesimista de concurrencia es apropiado, etc. Un colega, experto desde hace muchsimos aos en el rea de la Tecnologa de Objetos, me comentaba hace poco entusiasmado: He ledo ya la mitad del libro y ... lo entiendo todo!. El texto es totalmente autnomo, aunque es opinin general (y por tanto discutible de pleno) que complementa el ms antiguo de Cattell. En verdad que si slo ha de comprar un libro sobre Bases de Objetos, elija ste. Y es que esta vez la pasin y la razn andan juntas. Modern Database Systems: The Object Model, Interoperability, and B eyond, editado por Won Kim, 1995, Addison-Wesley, 0-201-59098-0. Siguiendo un esquema similar al texto del 89, aparecen aqu muchos artculos de

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 237

distintos autores que se estructuran en dos captulos tecnolgicos: Bases de Datos de Prxima Generacin e Interoperabilidad con Bases de Datos Preexistentes. La adecuada disposicin de las contribuciones, mayormente originales para el texto, permite una lectura secuencial y muestra una precisa visin del estado actual de la Tecnologa. LIBROS SOBRE INGENIERA DE PROCESOS Reengineering the Corporation: A Manifesto for Business Revolution, por Michael Hammer & James Champy, New York: HarperCollins Publishers, 1993, 0-88730-640-3. 216 pginas (en la edicin inglesa, claro) de lectura fcil con muchos ejemplos y borrosas formas-de-hacer tratan de comunicar al lector una supuesta mayor efectividad (partiendo desde la nada) en el enfoque de las corporaciones del maana. Aqu se examinan (y esto es un eufemismo) distintos ejemplos de cmo la focalizacin en la importancia e los procesos ha llevado a algunas empresas a desarrollos brillantemente efectivos. Se trata, en definitiva, de una buena lectura de verano. Nada ms. Y nada menos. Claro que no es un manual, y ni siquiera contiene postulados o mtodos. Es ... un best-seller. Su inclusin aqu se debe a que sin este libro el lector no podra comprender los siguientes (y no el texto, sino la razn de su publicacin, claro). The Object Advantage: Business Process Reengineering with Object Technology, por Ivar Jacobson, Maria Ericsson y Agneta Jacobson, ACM Press, 1994. Los Casos-de-Uso de Jacobson encajan perfectamente en el nicho comercial de la Reingeniera de Procesos de Negocio Orientada-a-Objetos (OOBPR), as que en este libro se relata (ms que detalla) un enfoque de integracin orientada-aobjetos con entregables, ejemplos y una clarsima intencin de promocin comercial. Claro! Hay que vender re-ingeniera, y el cctel con procesos, negocios y objetos es publicitariamente explosivo. En fin, yo les aconsejara este libro para que puedan comprobar por s mismos como las necesidades comerciales convierten a un slido autor en un autor de fama corporativa. Business Engineering with Object Oriented Technology, por David A. Taylor, John Wiley & Sons, 1995. La primera parte de este libro, de forma curiosamente interesante, simila una prolongacin negocial del texto de Wirfs-Brock, pero cuando el lector empieza a desesperanzarse empieza a aparecer y conformarse lo que Taylor denomina Ingeniera Convergente (Convergent Engineering): un marco bsico orientado-aobjetos de slida practicidad que pretende constituirse en base del desarrollo de

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 238

software fiable. De una forma un tanto desmitificadora en estos tiempos de reinado del proceso Taylor prcticamente seala: Focalizacin en los procesos? No, gracias! No sustituya: Integre!. El libro es agradablemente corto y deja un buen regusto final. LIBROS SOBRE GESTIN DE PROYECTOS Succeeding with Objects: Decision Frameworks for Project Management, por Adele Goldberg & Kenneth S. Rubin, 1995, Addison-Wesley, 0-201-628783, 542 pgs. Goldberg y Rubin se han despachado con un libro imprescindible para cualquiera interesado en la gestin prctica de proyectos orientados-a-objetos. Los marcos de decisin a que se refiere el ttulo son secuencias organizadas de decisiones que deben tomarse en relacin directa con los objetos insertos en tales marcos y tambin con la arquitectura del proyecto a abordar, y cuyo objetivo ltimo es satisfacer con xito las metas impuestas por el proyecto mismo. En este inteligente y sentido libro los autores examinan el acercamiento inicial a la Tecnologa, la seleccin del adecuado modelo de proceso y la planificacin y el control del proyecto. El reso se discute seguidamente, pero inserto en esquemas organizativos que permitiran su efectiva aplicacin. La composicin de equipos es fundamental y en el marco correspondiente se exponen las decisiones a tomar para la constitucin de un equipo exitoso, para despues examinar el problema de qu herramientas usar, que planes de formacin asumir, cmo validar el trabajo realizado y unas ltimas palabras sobre el fracaso con objetos. El estilo es suelto y los apndices inestimables (verbigratia, el cuestionario sugerido para gestores de proyectos). Un responsable de informtica ignorar est libro a su riesgo y cuenta. Pitfalls of Object-Oriented Development, por Bruce F. Webster, 1995, M&T Books, 1-55851-397-3. He de confesar que este libro no colm las expectativas que el ttulo y su publicidad me haban sugerido. Claro que satisfacerme a m es azarosamente prolijo. Con todo el texto es buen material para los efectivos practicantes, novicios o no, de la Tecnologa de Objetos. Cada pitfall consta de una descripcin primera, seguida de un detalle de los sntomas, ms las posibles consecuencias de su aplicacin, tcnicas de deteccin, consejos para su eliminacin/extraccin y, para finalizar, algunas pistas encaminadas a su prevencin. Webster divide los problemas en: conceptuales, polticos, de gestin, de anlisis y diseo, de entornos, lenguajes y herramientas, de implementacin, de clases y objetos, de codificacin, de calidad y de reuso: un ambicioso conjunto que pretende abarcar el ciclo de vida completo del software y su redencin mediante la penitencia constructiva. Atiendan a algunas de las trampas: (5.4) Usar C++, (5.5) No usar C++, (3.5) Intentar demasiadas cosas, demasiado pronto, demasiado rpido, (1.1) Adoptar la

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 239

Orientacin-a-Objetos por razones equivocadas, (6.8) Ser seducido por el lado oscuro, etc. etc. En fin, con esta obra (que se supone complementaria del magnfico texto de Goldberg y Rubin, Succeeding with Objects) se pretende conseguir algo parecido a lo que con los patrones de diseo: comunicar la experiencia contrastada en diseo real de sistemas a los postulantes, aunque aqu por el lado morboso del castigo y el didactismo. Muy entretenido, al fin y a la postre. Object Lessons: Lessons Learned in Object-Oriented Development Projects, por Tom Love, 1993, SIGS Books, 0-9627477-3-4 (Prentice-Hall 0-13472432-1). El Dr. Love semeja los modos y estilos de Drucker en un libro amable que destila, a partes iguales, conocimiento y ligereza. Es curioso que el relato del texto se asuma intuitivamente como lanzado desde arriba, en un implcito reconocimiento de la experiencia con escasas fisuras del autor en el rea de gestin de proyectos. El libro empieza con el histrico ejemplo de la construccin del navo Vasa, cuyo desarrollo y ltimo fracaso prctico se ajustan condenadamente bien a los esquemas de fallo en proyectos software. Tras este ejemplo afortunado, Love se despacha con un nuevo smil sobre objetos (un objeto es una mquina electrnica, con entrada, salida y alimentacin elctrica), tras lo que intenta una introduccin liviana a la Tecnologa de Objetos que servir de base para un conjunto de captulos en los que se citan normas difusas (por extendidas en el texto), pero de gran ejemplicidad prctica. As, Love nota que los programadores del mundo real no reutilizan, o Escoja proyectos importantes, no aqullos sin importancia, tambin como La inmersin funciona mejor planteando la comparacin con el aprendizaje de un idioma extranjero. Se trata, como el ttulo indica, de la comunicacin de la valiosa experiencia personal en un rea que necesita de menos pasmo comercial y ms practicidad real. Yo dira que este libro es una buena introduccin (a modo de vistazo atemperado) de la Tecnologa de Objetos para jefes de proyecto o departamento de software, con el nico aviso: No contiene frmulas mgicas. LIBROS CONTRA LA TONTERA Los siguientes textos no se cien al mbito estricto de la Tecnologa de Objetos, sino que exponen de forma afortunadamente acertada un cmulo de criterios y principios, explcitos o no, subyacentes en el diseo de sistemas software de calidad. La seleccin, como siempre, es absolutamente personal y medida: por cada libro interesante que estudio he de leer otros cuatro lesivos, triviales o ridculos. Naturalmente yo intento leer nicamente los buenos, pero es difcil (y poco educado) juzgar en voz alta sin conocer, as que tras conocer y desechar, he aqu mi seleccin, mascada ya para que el lector trabaje menos:

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 240

201 Principles of Software Development, por Alan M. Davis, 1995, McGrawHill, 0-07-015840-1. Davis plantea en este texto una completa conjuncin de principios/mandamientos/patrones que, aplicados, debieran procurar sistemas software ms racionales, slidos y mantenibles: en resumen, de calidad. Los principios son cortos y no tienen desperdicio: (34) Todo documento software necesita un ndice, (82) Los grandes diseos vienen de grandes diseadores, (30) Sigue a los lemmings con cuidado, (22) Tcnica antes que herramientas, (170) S pesimista sobre la evolucin del software, ... y muchos otros. Cada principio se acompaa de una corta justificacin, sirviendo as el texto de guia referencial a ingenieros (sic) software, directivos y estudiantes. Conviene recordar que los seres humanos tienden a trivializar rpidamente lo que les parece obvio en un contexto dado, as que a ms de uno le resultar tremendamente instructivo repasar algunos conceptos que tena por asimilados pero que nunca realmente ha aplicado con claridad. Software Requirements & Specifications: A Lexicon of Practice, Principles and Prejudices, por Michael Jackson, 1995, Addison-Wesley, 0-201-87712-0. Este libro, aunque liviano, me ha encantado hasta la sonrisa: su estructura es la de un diccionario, de forma que las distintas secciones estn ordenadas por orden alfabtico, y aun as puede leerse de corrido. Jackson aporta aqu importantes dosis de sentido comn y claridad distribuidas en pequeas porciones repletas de inteligencia y solidez. La traslacin, por ejemplo, del problema de los puentes de Knigsberg al terreno de los escenarios en especificaciones es particularmente afortunada; el planteamiento, bajo el epgrafe Brillantez, de los analistas insustituibles que generan diseos que ni ellos mismos alcanzan a comprender es, por otro lado, grandemente instructivo (Oh Sancta Simplicitas). La incomprensin, por ejemplo, de los mens por parte de los comensales, en el apartado Restaurantes, resulta intelectualmente punzante. En fin, Jackson se despacha con sorpresas pgina tras pgina y desarrolla temas tan interesantes como El Marco JSP, Dekker (sobre el Problema de la Mutua Exclusin), Eventos e Intervalos, etc. En el sentido ms cercano al espritu de DAlembert, este diccionario es una buena herramienta contra la estupidez y el fanatismo.

Ricardo Devis Botella C++: STL, Plantillas, Excepciones, Roles y Objetos

Pgina 241

También podría gustarte