Inheritanche considered harmful Inheritanche considered harmful La herencia es la clase base de todos los males J. Daniel Garcia Grupo ARCOS Universidad Carlos III de Madrid 27 de noviembre de 2015 cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 1/53 Inheritanche considered harmful Aviso c Esta obra está bajo una Licencia Creative Commons b e d cb e d – Atribución-NoComercial-SinDerivar 4.0 Internacional. Debes dar crédito en la obra en la forma especificada por el autor o licenciante. El licenciante permite copiar, distribuir y comunicar públicamente la obra. A cambio, esta obra no puede ser utilizada con fines comerciales — a menos que se obtenga el permiso expreso del licenciante. El licenciante permite copiar, distribuir, transmitir y comunicar públicamente solamente copias inalteradas de la obra – no obras derivadas basadas en ella. J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 2/53 Inheritanche considered harmful ARCOS@uc3m UC3M: Una universidad joven, internacional y orientada a la investigación. ARCOS: Un grupo de investigación aplicada. Líneas: Computación de altas prestaciones, Big data, Sistemas Ciberfísicos, y Modelos de programación para la mejora de las aplicaciones Mejorando las aplicaciones: REPARA: Reengineering and Enabling Performance and poweR of Applications. Financiado por Comisión Europea (FP7). RePhrase: REfactoring Parallel Heterogeneous Resource Aware Applications. Financiado por Comisión Europea (H2020). Normalización: ISO/IEC JTC/SC22/WG21. Comité ISO C++. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 3/53 Inheritanche considered harmful Actividad C++ Jornadas C++. Web: http://usingstdcpp.org Meetups: http://www.meetup.com/Madrid-C-Cpp/ Próximo meetup viernes 4 de diciembre. ¿Te interesa C++? @usingstdcpp cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 4/53 Inheritanche considered harmful Cartera de servicios Formación: Adopción de C++11/14/17/. . . Formación ad-hoc en C++. Programación paralela: multi-core, GPGPU, . . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 5/53 Inheritanche considered harmful Cartera de servicios Formación: Adopción de C++11/14/17/. . . Formación ad-hoc en C++. Programación paralela: multi-core, GPGPU, . . . Consultoría: Definición de coding standards. Apoyo tecnológico en proyectos de desarrolllo. Migración de código, mejoras de portabilidad. Mejora de rendimiento y eficiencia energética. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 5/53 Inheritanche considered harmful Cartera de servicios Formación: Adopción de C++11/14/17/. . . Formación ad-hoc en C++. Programación paralela: multi-core, GPGPU, . . . Consultoría: Definición de coding standards. Apoyo tecnológico en proyectos de desarrolllo. Migración de código, mejoras de portabilidad. Mejora de rendimiento y eficiencia energética. I+D+i: Refactorización de código. Herramientas de análisis de código (estático y dinámico). Convocatorias regionales, nacionales, e internacionales. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 5/53 Inheritanche considered harmful Introducción 1 Introducción 2 Observaciones 3 Caso práctico cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 6/53 Inheritanche considered harmful Introducción Lenguajes de programación There are only two kinds of languages: the ones people complain about and the ones nobody uses. Bjarne Stroustrup cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 7/53 Inheritanche considered harmful Introducción Lenguajes de programación There are only two kinds of languages: the ones people complain about and the ones nobody uses. Bjarne Stroustrup Anybody who comes to you and says he has a perfect language is either naïve or a salesman. Bjarne Stroustrup cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 7/53 Inheritanche considered harmful Introducción Herramientas y problemas Un martillo es fantástico para clavar un clavo. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 8/53 Inheritanche considered harmful Introducción Herramientas y problemas Un martillo es fantástico para clavar un clavo. ¿Y para apretar tuercas? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 8/53 Inheritanche considered harmful Introducción Herramientas y problemas Un martillo es fantástico para clavar un clavo. ¿Y para apretar tuercas? ¿Y para atornillar? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 8/53 Inheritanche considered harmful Introducción Herramientas y problemas Un martillo es fantástico para clavar un clavo. ¿Y para apretar tuercas? ¿Y para atornillar? ¿Para depurar un programa? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 8/53 Inheritanche considered harmful Introducción Herramientas y problemas Un martillo es fantástico para clavar un clavo. ¿Y para apretar tuercas? ¿Y para atornillar? ¿Para depurar un programa? ¿Será la OO un martillo para programadores? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 8/53 Inheritanche considered harmful Introducción Los orígenes La subrutina: David Wheeler y Maurice Wilkes. 1951. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 9/53 Inheritanche considered harmful Introducción Los orígenes La subrutina: David Wheeler y Maurice Wilkes. 1951. Programación funcional: Lisp, Johh McCarthy. 1958. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 9/53 Inheritanche considered harmful Introducción Los orígenes La subrutina: David Wheeler y Maurice Wilkes. 1951. Programación funcional: Lisp, Johh McCarthy. 1958. Programación orientada a objetos: Simula, Simula-67. Ole-Johan Dahl y Kristen Nygaard. 1960-1970. Smalltalk, Smalltalk-80. Alan C. Kay. 1970-1980. ... cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 9/53 Inheritanche considered harmful Introducción Los orígenes La subrutina: David Wheeler y Maurice Wilkes. 1951. Programación funcional: Lisp, Johh McCarthy. 1958. Programación orientada a objetos: Simula, Simula-67. Ole-Johan Dahl y Kristen Nygaard. 1960-1970. Smalltalk, Smalltalk-80. Alan C. Kay. 1970-1980. ... Programación genérica: CLU. Barbara Liskov. 1974. Ada. Jean Ichbiah. 1983. C++. Bjarne Stroustrup. 1983. Alexander Stepanov. 1998. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 9/53 Inheritanche considered harmful Introducción Pero ¿Cuándo tiene éxito? 1979-1983: C++. 1986: Object Pascal. 1986: Eiffel. 1995: Java. 1995: Ada95. 2000: C#. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 10/53 Inheritanche considered harmful Introducción ¿Qué más ocurrió en los 90? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 11/53 Inheritanche considered harmful Observaciones 1 Introducción 2 Observaciones 3 Caso práctico cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 12/53 Inheritanche considered harmful Observaciones OO: Lenguajes vs Sistema ¿Se puede hacer desarrollo OO sin un lenguaje OO? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 13/53 Inheritanche considered harmful Observaciones OO: Lenguajes vs Sistema ¿Se puede hacer desarrollo OO sin un lenguaje OO? En teoría: SI. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 13/53 Inheritanche considered harmful Observaciones OO: Lenguajes vs Sistema ¿Se puede hacer desarrollo OO sin un lenguaje OO? En teoría: SI. Y en la práctica también: X-Windows System, OSF/Motif. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 13/53 Inheritanche considered harmful Observaciones OO: Lenguajes vs Sistema ¿Se puede hacer desarrollo OO sin un lenguaje OO? En teoría: SI. Y en la práctica también: X-Windows System, OSF/Motif. Sin embargo: demasiado complicado y conducente a errores. Fácil cometer errores. ¿Por qué dejar al programador tareas que puede hacer un compilador? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 13/53 Inheritanche considered harmful Observaciones Cosas que a veces olvidamos Principios de diseño de X-Windows ( Bob Scheifler y Jim Gettys, 1984). Do not add new functionality unless an implementor cannot complete a real application without it. It is as important to decide what a system is not as to decide what it is. Do not serve all the world’s needs. The only thing worse than generalizing from one example is generalizing from no examples at all. If a problem is not completely understood, it is probably best to provide no solution at all. If you can get 90 percent of the desired effect for 10 percent of the work, use the simpler solution. Isolate complexity as much as possible. Provide mechanism rather than policy. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 14/53 Inheritanche considered harmful Observaciones Todo tiene que ser un método ¿Por qué tenemos clases? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 15/53 Inheritanche considered harmful Observaciones Todo tiene que ser un método ¿Por qué tenemos clases? Principio de la ocultación de la información. David Parnas (1972) Incrementar la flexibilidad y comprensión. Reducir tiempo de desarrollo. Reducir acoplamiento global. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 15/53 Inheritanche considered harmful Observaciones Todo tiene que ser un método ¿Por qué tenemos clases? Principio de la ocultación de la información. David Parnas (1972) Incrementar la flexibilidad y comprensión. Reducir tiempo de desarrollo. Reducir acoplamiento global. Pero ... Hemos asumido que el módulo o componente es equivalente a la clase. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 15/53 Inheritanche considered harmful Observaciones Todo tiene que ser un método ¿Por qué tenemos clases? Principio de la ocultación de la información. David Parnas (1972) Incrementar la flexibilidad y comprensión. Reducir tiempo de desarrollo. Reducir acoplamiento global. Pero ... Hemos asumido que el módulo o componente es equivalente a la clase. Y nos empeñamos en ocultar, incluso cuando no hay nada que ocultar. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 15/53 Inheritanche considered harmful Observaciones Métodos de clase Un método de la metaclase → Compartido por todas la instancias. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/53 Inheritanche considered harmful Observaciones Métodos de clase Un método de la metaclase → Compartido por todas la instancias. Java public final class Math { public static double abs(double a) {/∗...∗/} } // Invocación x = Math.abs(y); cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/53 Inheritanche considered harmful Observaciones Métodos de clase Un método de la metaclase → Compartido por todas la instancias. C++ Java public final class Math { public static double abs(double a) {/∗...∗/} } // Invocación x = Math.abs(y); cb e d – namespace std { double abs(double arg); } // Invocación x = abs(y); J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/53 Inheritanche considered harmful Observaciones Métodos de clase Un método de la metaclase → Compartido por todas la instancias. C++ Java public final class Math { public static double abs(double a) {/∗...∗/} } namespace std { double abs(double arg); } // Invocación // Invocación x = Math.abs(y); x = abs(y); Tendemos a inventar clases: Porque en alguna clase tengo que meter esto. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/53 Inheritanche considered harmful Observaciones Métodos de clase Un método de la metaclase → Compartido por todas la instancias. C++ Java public final class Math { public static double abs(double a) {/∗...∗/} } namespace std { double abs(double arg); } // Invocación // Invocación x = Math.abs(y); x = abs(y); Tendemos a inventar clases: Porque en alguna clase tengo que meter esto. O a tener animales como la clase Integer. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/53 Inheritanche considered harmful Observaciones Métodos de clase Un método de la metaclase → Compartido por todas la instancias. C++ Java public final class Math { public static double abs(double a) {/∗...∗/} } namespace std { double abs(double arg); } // Invocación // Invocación x = Math.abs(y); x = abs(y); Tendemos a inventar clases: Porque en alguna clase tengo que meter esto. O a tener animales como la clase Integer. O a hacer que main sea un método. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/53 Inheritanche considered harmful Observaciones Ocultación paranóica de la información Los atributos de una clase siempre tiene que ser privados. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 17/53 Inheritanche considered harmful Observaciones Ocultación paranóica de la información Los atributos de una clase siempre tiene que ser privados. Y luego lo llenamos todo de getter y setters. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 17/53 Inheritanche considered harmful Observaciones Ocultación paranóica de la información Los atributos de una clase siempre tiene que ser privados. Y luego lo llenamos todo de getter y setters. ¿Dónde está la ocultación de la información? cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 17/53 Inheritanche considered harmful Observaciones Ocultación paranóica de la información Los atributos de una clase siempre tiene que ser privados. Y luego lo llenamos todo de getter y setters. ¿Dónde está la ocultación de la información? Un par de valores class pair { public: pair ( int k, const string & v); void set_key(int k) { key=k; } int get_key() const { return key; } void set_value(const string & v) { value=v; } string get_value() const { return value; } private: int key; string value; }; cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 17/53 Inheritanche considered harmful Observaciones Ocultación paranóica de la información Los atributos de una clase siempre tiene que ser privados. Y luego lo llenamos todo de getter y setters. ¿Dónde está la ocultación de la información? Un par de valores class pair { public: pair ( int k, const string & v); void set_key(int k) { key=k; } int get_key() const { return key; } void set_value(const string & v) { value=v; } string get_value() const { return value; } private: int key; string value; }; cb e d – O un par de valores struct pair { pair ( int k, const string & v); int key; string value; }; J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 17/53 Inheritanche considered harmful Observaciones Y entonces llegaron los patrones Design Patterns: Elements of Reusable Object-Oriented Software. Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. 1994. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 18/53 Inheritanche considered harmful Observaciones Y entonces llegaron los patrones Design Patterns: Elements of Reusable Object-Oriented Software. Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. 1994. Debería ser de obligada lectura. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 18/53 Inheritanche considered harmful Observaciones Y entonces llegaron los patrones Design Patterns: Elements of Reusable Object-Oriented Software. Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. 1994. Debería ser de obligada lectura. Desgraciadamente usado malamente como un recetario. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 18/53 Inheritanche considered harmful Observaciones Y entonces llegaron los patrones Design Patterns: Elements of Reusable Object-Oriented Software. Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. 1994. Debería ser de obligada lectura. Desgraciadamente usado malamente como un recetario. Sin embargo, hay patrones problemáticos: Singleton: Mecanismo complicado de emulación de variables globales. Visitor: Mecanimso complicado de emulación de polimorfismo dinámico múltiple. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 18/53 Inheritanche considered harmful Observaciones Herencia Herencia: Mecanismo de reutilización de código. Herencia de interfaz (Subtyping): Establece una relación es-un. Herencia de implementación: Mecanimso de reutilización de implementación. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 19/53 Inheritanche considered harmful Observaciones Herencia Herencia: Mecanismo de reutilización de código. Herencia de interfaz (Subtyping): Establece una relación es-un. Herencia de implementación: Mecanimso de reutilización de implementación. Aproximaciones: Todo deben ser clases organizadas en una única jerarquía unversal. Un Vector extiende un AbstractList que extiende un AbstractCollection que extiend un Object. Utilizar herencia de forma limitada cuando sea necesario. Un std::vector no hereda nada de nadie. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 19/53 Inheritanche considered harmful Observaciones Polimorfismo Polimorfismo: Capacidad de ofrecer el mismo interfaz variando la implementación. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 20/53 Inheritanche considered harmful Observaciones Polimorfismo Polimorfismo: Capacidad de ofrecer el mismo interfaz variando la implementación. Normalmente usado como sinónimo de polimorfismo dinámico. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 20/53 Inheritanche considered harmful Observaciones Polimorfismo Polimorfismo: Capacidad de ofrecer el mismo interfaz variando la implementación. Normalmente usado como sinónimo de polimorfismo dinámico. Polimorfismo dinámico: Se toma la decisión sobre la selección de la implementación en tiempo de ejecución. Pequeño sobrecoste por invocación a función. Aceptable si el uso es limitado. Conduce a diseños más flexible de lo realmente necesario. Y si un día . . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 20/53 Inheritanche considered harmful Observaciones Hay otro polimorfismo Polimorfismo estático: Se toma la decisión sobre la selección en tiempo de compilación. No siempre es posible. Flexibilidad suficiente. No hay sobrecoste en tiempo de ejecución. Ordenación genérica template <typename C> void sort(C & c) { sort (c.begin() , c.end()) ; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 21/53 Inheritanche considered harmful Observaciones Hacia un nuevo paradigma A new scientific truth does not triumph by convincing its opponents and making them see the light, but rather because its opponents eventually die The structure of scientific revolutions Thomas Kuhn, 1962. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 22/53 Inheritanche considered harmful Observaciones Hacia un nuevo paradigma A new scientific truth does not triumph by convincing its opponents and making them see the light, but rather because its opponents eventually die The structure of scientific revolutions Thomas Kuhn, 1962. FUNGENOOP. Functional. Generic. Object Oriented. Procedural. (Tony DaSilva) cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 22/53 Inheritanche considered harmful Observaciones Hacia un nuevo paradigma A new scientific truth does not triumph by convincing its opponents and making them see the light, but rather because its opponents eventually die The structure of scientific revolutions Thomas Kuhn, 1962. FUNGENOOP. Functional. Generic. Object Oriented. Procedural. (Tony DaSilva) cb e d – Ejemplo void dibuja(Container & c) requires same<element_type<Container>,Figura∗> { for_each(begin(c), end(c), []( Figura ∗ s) { s−>draw();}); } J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 22/53 Inheritanche considered harmful Observaciones Un problema adicional Gestión de los recursos. Muchos lenguajes OO han optado por hacerle la vida fácil al programador con la recolección de basura. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 23/53 Inheritanche considered harmful Observaciones Un problema adicional Gestión de los recursos. Muchos lenguajes OO han optado por hacerle la vida fácil al programador con la recolección de basura. Pero seguimos con memory leaks por todas partes. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 23/53 Inheritanche considered harmful Observaciones Un problema adicional Gestión de los recursos. Muchos lenguajes OO han optado por hacerle la vida fácil al programador con la recolección de basura. Pero seguimos con memory leaks por todas partes. La recolección de basura: Generalmente tiene impacto en el rendimiento. Incremento del imapcto debido a la revolución multi-core. La mejor estrategia de gestión de la basura es no generar basura. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 23/53 Inheritanche considered harmful Caso práctico 1 Introducción 2 Observaciones 3 Caso práctico cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 24/53 Inheritanche considered harmful Caso práctico El problema 3 Caso práctico El problema Una solución sencilla Solución orientada a objetos Solución genérica Polimorfismo de implementación Comparación cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 25/53 Inheritanche considered harmful Caso práctico El problema Un caso sencillo Un documento tiene una lista de elementos. Queremos volcar un elemento a la salida estándar. Usaremos una función dump(). Comenzaremos usando números enteros como valores de elementos. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 26/53 Inheritanche considered harmful Caso práctico El problema Un caso sencillo Un documento tiene una lista de elementos. Queremos volcar un elemento a la salida estándar. Usaremos una función dump(). Comenzaremos usando números enteros como valores de elementos. NOTA: Las soluciones que se presentan se derivan de adaptaciones de las presentadas por Sean Parent en su charla “value semantics”. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 26/53 Inheritanche considered harmful Caso práctico Una solución sencilla 3 Caso práctico El problema Una solución sencilla Solución orientada a objetos Solución genérica Polimorfismo de implementación Comparación cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 27/53 Inheritanche considered harmful Caso práctico Una solución sencilla Código cliente main.cpp #include "doclib.h" #include <iostream> int main() { document doc; doc.add_element(1); doc.add_element(2); doc.add_element(3); doc.dump(std::cout); return 0; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 28/53 Inheritanche considered harmful Caso práctico Una solución sencilla Biblioteca de documentos doclib.h #ifndef DOCLIB_H #define DOCLIB_H #include <vector> #include <iostream> class document { public: void add_element(int e) { elems.emplace_back(e); } void dump(std::ostream & out) const; private: std :: vector<int> elems; }; #endif cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 29/53 Inheritanche considered harmful Caso práctico Una solución sencilla Biblioteca de documentos doclib.cpp #include "doclib.h" void document::dump(std::ostream & out) const { using namespace std; out << "START" << endl; for (const auto & e : elems) { out << e << endl; } out << "END" << endl; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 30/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos 3 Caso práctico El problema Una solución sencilla Solución orientada a objetos Solución genérica Polimorfismo de implementación Comparación cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 31/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Generalizando la biblioteca Deseamos tener una solución más general. Soportar documentos con elementos de distintos tipos (enteros, cadenas, . . . ). Soportar documentos que permitan elementos con múltiples tipos en el mismo documento. Probemos la solución orientada a objetos clásica. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 32/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Biblioteca de documentos doclib.h #ifndef DOCLIB_H #define DOCLIB_H #include <iostream> #include <vector> #include <memory> class element { public: virtual ~element() {} virtual void dump(std::ostream &) const = 0; }; //. . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 33/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Biblioteca de documentos doclib.h class document { public: void add_element(std::shared_ptr<element> && e) { elems.emplace_back(e); } void dump(std::ostream & out) const; private: std :: vector<std :: shared_ptr<element>> elems; }; #endif cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 34/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Código cliente main.cpp #include "doclib.h" class my_int_value : public element { public: my_int_value(int v) : value{v} {} void dump(std::ostream & out) const { out << value << std :: endl; } private: int value; }; //. . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 35/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Código cliente main.cpp int main() { using namespace std; document doc; doc.add_element(make_shared<my_int_value>(1)); doc.add_element(make_shared<my_int_value>(2)); doc.add_element(make_shared<my_int_value>(3)); doc.dump(cout); return 0; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 36/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. Indirección + memoria dinámica + virtualización → rendimiento pobre. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. Indirección + memoria dinámica + virtualización → rendimiento pobre. Gestión del tiempo de vida → recolección de basura o cuenta de referencias. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. Indirección + memoria dinámica + virtualización → rendimiento pobre. Gestión del tiempo de vida → recolección de basura o cuenta de referencias. Propiedad compartida de objetos → estructuras de datos accidentales. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. Indirección + memoria dinámica + virtualización → rendimiento pobre. Gestión del tiempo de vida → recolección de basura o cuenta de referencias. Propiedad compartida de objetos → estructuras de datos accidentales. Adicionalmente: Problemas de sincronización. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. Indirección + memoria dinámica + virtualización → rendimiento pobre. Gestión del tiempo de vida → recolección de basura o cuenta de referencias. Propiedad compartida de objetos → estructuras de datos accidentales. Adicionalmente: Problemas de sincronización. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución orientada a objetos Polimorfismo dinámico Al usar la herencia como mecanismo para el polifmorfismo se traslada la complejidad al código cliente, incrementando el acoplamiento. La herencia implica tamaños variables → Memoria dinámica. Indirección + memoria dinámica + virtualización → rendimiento pobre. Gestión del tiempo de vida → recolección de basura o cuenta de referencias. Propiedad compartida de objetos → estructuras de datos accidentales. Adicionalmente: Problemas de sincronización. La herencia es la clase base de todos los males. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/53 Inheritanche considered harmful Caso práctico Solución genérica 3 Caso práctico El problema Una solución sencilla Solución orientada a objetos Solución genérica Polimorfismo de implementación Comparación cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 38/53 Inheritanche considered harmful Caso práctico Solución genérica Programación genérica Probemos el polimorfismo en tiempo de compilación. Un tipo genérico document<T> usable para cualquier tipo T. Se apoya en una función genérica para volcar valores dump_value(). cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 39/53 Inheritanche considered harmful Caso práctico Solución genérica Programación genérica Probemos el polimorfismo en tiempo de compilación. Un tipo genérico document<T> usable para cualquier tipo T. Se apoya en una función genérica para volcar valores dump_value(). Permite tener documentos homogéneos. No se pueden tener enteros y cadenas en el mismo docuemnto. Todas las llamadas resueltas en tiempo de compilación. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 39/53 Inheritanche considered harmful Caso práctico Solución genérica Biblioteca de documentos doclib.h #ifndef DOCLIB_H #define DOCLIB_H #include <iostream> #include <vector> template <typename T> void dump_value(const T & x, std::ostream & out) { out << x << std :: endl; } //. . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 40/53 Inheritanche considered harmful Caso práctico Solución genérica Biblioteca de documentos doclib.h template <typename T> class document { public: void add_element(T && e) { elems.emplace_back(e); } void dump(std::ostream & out) const; private: std :: vector<T> elems; }; template <typename T> void document<T>::dump(std::ostream & out) const { using namespace std; out << "START" << endl; for (const auto & e : elems) { dump_value(e,out); } out << "END" << endl; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 41/53 Inheritanche considered harmful Caso práctico Solución genérica Código cliente doclib.h #include "doclib.h" #include <string> int main() { document<int> doc1; doc1.add_element(1); doc1.add_element(2); doc1.dump(std::cout); document<std::string> doc2; doc2.add_element("C++"); doc2.add_element("is"); doc2.add_element("cool"); doc2.dump(std::cout); return 0; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 42/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación 3 Caso práctico El problema Una solución sencilla Solución orientada a objetos Solución genérica Polimorfismo de implementación Comparación cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 43/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Ocultando el polimorfismo El polimorfismo dinámico debe ser un mecanismo de implementación. No debe ser visible al código del cliente. El cliente debe usar interfaces simplificadas. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 44/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Ocultando el polimorfismo El polimorfismo dinámico debe ser un mecanismo de implementación. No debe ser visible al código del cliente. El cliente debe usar interfaces simplificadas. Usaremos un document que acepta elements. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 44/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Ocultando el polimorfismo El polimorfismo dinámico debe ser un mecanismo de implementación. No debe ser visible al código del cliente. El cliente debe usar interfaces simplificadas. Usaremos un document que acepta elements. Internamente un element puede usar polimorfismo dinámico como detalle de implementación. Borrado de tipos (Type Erasure). cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 44/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Biblioteca de documentos doclib.h #ifndef DOCLIB_H #define DOCLIB_H #include <iostream> #include <vector> #include <memory> template <typename T> void dump_value(const T & x, std::ostream & out) { out << x << std :: endl; } // . . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 45/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Elemento: Internamente puntero a valor doclib.h class element { public: template <typename T> element(T x); element(const element & o) = delete; element & operator=(const element & o) =delete; element(element &&) noexcept = default; element & operator=(element &&) noexcept = default; void dump(std::ostream & out) const { self−>dump(out); } // . . . private: std :: unique_ptr<base_value> self; }; cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 46/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Detalle de implementación: Jerarquía de valores doclib.h (detalles de element) private: struct base_value { virtual ~base_value() = default; virtual void dump(std::ostream & out) const = 0; }; template <typename T> struct value : base_value { value(T x) : data{std :: move(x)} {} virtual void dump(std::ostream & out) const { dump_value(data,out); } T data; }; // . . . cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 47/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Biblioteca de documentos doclib.h // . . . template <typename T> element::element(T x) : self {std :: make_unique<value<T>>(std::move(x))} { } class document { public: void add_element(element && e) { elems.emplace_back(std::move(e)); } void dump(std::ostream & out) const; private: std :: vector<element> elems; }; #endif cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 48/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Volcado de documento doclib.cpp #include "doclib.h" void document::dump(std::ostream & out) const { using namespace std; out << "START" << endl; for (const auto & e : elems) { e.dump(out); } out << "END" << endl; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 49/53 Inheritanche considered harmful Caso práctico Polimorfismo de implementación Un documento heterogéneo main.cpp #include "doclib.h" int main() { document doc; doc.add_element(1); doc.add_element(2); doc.add_element("C++"); doc.add_element("is cool"); doc.dump(std::cout); return 0; } cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 50/53 Inheritanche considered harmful Caso práctico Comparación 3 Caso práctico El problema Una solución sencilla Solución orientada a objetos Solución genérica Polimorfismo de implementación Comparación cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 51/53 Inheritanche considered harmful Caso práctico Comparación Uso de memoria Solución mínima. 3 asignaciones. 28 bytes. Solución OO clásica. 6 asignaciones. 208 bytes. Solución genérica. 3 asignaciones. 28 bytes. Polimorfismo de implementación. 6 asignaciones. 104 bytes. cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 52/53 Inheritanche considered harmful Caso práctico Comparación Inheritanche considered harmful La herencia es la clase base de todos los males J. Daniel Garcia Grupo ARCOS Universidad Carlos III de Madrid 27 de noviembre de 2015 cb e d – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 53/53