Desarrollo de juegos como base para la compresión de temas fundamentales de la programación orientada a objetos Ponencia Aprendizaje y currículo HÉCTOR FABIO CADAVID RENGIFO ESCUELA COLOMBIANA DE INGENIERÍA “JULIO GARAVITO” hcadavid@escuelaing.edu.co Fax: (571)6762340 Introducción En la Facultad de Ingeniería de Sistemas de la Escuela Colombiana de Ingeniería desde hace varios años se ha venido trabajando el paradigma de la programación orientada a objetos dentro de dos de las asignaturas obligatorias dentro del plan de estudios, después de haber cursado tres asignaturas de programación con el paradigma procedimental/estructurado. No se parte de la programación orientada a objetos porque se busca que los estudiantes logren un conocimiento adecuado de todos los paradigmas de programación, evitando limiten su forma de pensar a uno solo. Cuando se hizo más popular este paradigma, muchos años después de su concepción, se empezaron a hacer sentir muchos de sus detractores, profesionales en el área con vasta experiencia en el desarrollo de aplicaciones orientadas al procesamiento de datos con bases de datos relacionales. Las críticas se centraron fundamentalmente en una comparación entre los modelos de objetos y los modelos entidad relación, mencionando desventajas para el procesamiento de datos. Incluso los profesionales egresados más recientemente recomiendan omitir ciertos elementos de este paradigma al catalogarlos como inútiles, lo que evidencia un profundo desconocimiento de sus aplicaciones. Este artículo recoge los resultados de una experiencia de la enseñanza del paradigma orientado a objetos, a través de juegos .En ella se da a los estudiantes una visión de cómo darle a una aplicación características de extensibilidad y adaptabilidad haciendo uso de las características de este paradigma, independientemente de su propósito. Primera aproximación a los conceptos Orientados a Objetos En los primeros cursos de programación de computadores, se introducen los conceptos de abstracción y encapsulamiento como elementos fundamentales para el ejercicio del diseño de software modular, escalable y basado en componentes reutilizables. Como base teórica de la enseñanza de esta tipo de programación se retoma el concepto matemático de TAD (Tipo Abstracto de Dato), que se define como un “modelo matemático compuesto por una colección de operaciones definidas sobre un conjunto de datos de un modelo”. Los estudiantes, mediante el uso de un lenguaje estructurado/modular tradicional realizan los ejercicios propuestos en clase siempre pensando en elementos reutilizables, para los cuales garantizan la abstracción y el encapsulamiento, haciendo sólo visible para el integrador de dichos módulos los nombres de los tipos y sus operaciones relacionadas. Sobre la base de esta formación se dicta el primer curso de programación orientada a objetos. Gracias a esto, a pesar de usar lenguajes estructurados/modulares en los primeros cursos de programación, la transición de paradigma se logra sin mayores problemas, pues en su etapa inicial el cambio de paradigma se presenta sólo como un cambio de metáfora para los mismos principios: abstracción y encapsulamiento. Metáfora para la abstracción y el encapsulamiento con lenguajes tradicionales La información de estado de las entidades que se abstraen en un sistema es almacenada en registros de memoria. Para garantizar encapsulamiento, el estado interno de dichos registros sólo puede ser alterado o consultado por las operaciones del módulo del TAD. A su vez, con las especificaciones dadas en la documentación de de dichas operaciones, se da un nivel de abstracción al hacer que éstas realmente tengan semántica. Módulo del TAD consultarEstado{ } a b cambiarEstado{ } … Figura 1: Los datos ‘a’ y ‘b’ son información encapsulada de un TAD Cuando se revisa este tema para introducir los conceptos de la programación orientada a objetos, se da como metáfora un automóvil. Si un automóvil funcionara en la realidad tal como en un sistema de software con este esquema de abstracción y encapsulamiento, para poder encender el automóvil, acelerarlo, girar, o realizar cualquier acción con la que éste modifique su estado (velocidad, aceleración, ángulo de giro, etc.), sería necesario llevarlo hasta el concesionario, pues éste tendría el único timón, acelerador, freno, y demás controles para todos los carros producidos. Teniendo como motivación la búsqueda de una manera de programar más natural, más parecida a la realidad, se les presenta la misma metáfora, pero bajo el paradigma orientada a objetos. En un sistema de software orientado a objetos, la representación de cada automóvil dentro del sistema, se comportaría igual que en la realidad, pues cada uno de éstos tendría sus controles para cambiar su estado: dirección, pedal de aceleración, etc., y mecanismos para consultar su estado: tablero para medir el combustible, odómetro, tacómetro, etc. cambiarEstado a consultarEstado b cambiarEstado consultarEstado Figura 2: ‘a’ y ‘b’ siguen representando entidades del sistema encapsulando sus detalles, pero son autosuficientes, pues cada uno cuenta además de su estado, con sus operaciones. Tanto ‘a’ como ‘b’ pueden ahora considerarse objetos. Hasta este punto, quienes aprenden el nuevo paradigma ven una manera más simple y natural de modelar la información de un sistema usando componentes que representen las entidades involucradas en el mismo, pero saben que se puede hacer exactamente lo mismo con un lenguaje tradicional. La verdadera motivación para aprender el nuevo paradigma Con las bases que provee el manejo de tipos abstractos de datos, el cambio de paradigma estructurado/modular a orientado a objetos se ha vuelto menos complejo; los estudiantes logran manejar ambos paradigmas sin mezclarlos. El siguiente tema por desarrollarse en un curso de programación orientada a objetos es el de la herencia de clases. Este tema agrega nuevos elementos al modelaje del sistema, y permite hacer relaciones de generalización/especialización entre conceptos (clases). El ejemplo clásico es el de las extensiones al concepto de persona para definir personas que tienen características adicionales según su perfil dentro del contexto del sistema: Persona nombre edad cedula Profesor categoria Estudiante semestre Figura 3: Ejemplo clásico usado para explicar el concepto de herencia Este tipo de ejemplos es el que usan como referencia los detractores de este paradigma de programación, los cuales argumentan que es más natural y práctico un modelaje basado en composiciones que en jerarquías. Esto es debido a la idea errónea de que modelar un sistema orientado a objetos significa simplemente definir forzosamente jerarquías de conceptos. Buscar generalizaciones/especializaciones dentro de un modelo tiene muchas aplicaciones más allá de la simple reutilización de clases, aplicaciones que han permitido la incursión de nuevas ideas dentro de la ingeniería de software, como los patrones de diseño, marcos de trabajo (frameworks) y las arquitecturas de software basadas en componentes intercambiables. El verdadero objetivo de un curso de programación orientada a objetos debe ser el dejar claros los conceptos de este paradigma que dieron lugar a estas nuevas ideas, con el fin de que puedan ser asimiladas más adelante en los cursos formales de ingeniería de software. Polimorfismo y encadenamiento dinámico La verdadera potencia de un lenguaje orientado a objetos está en la capacidad de interpretar de forma consistente con la realidad las jerarquías de conceptos. En la realidad, usamos comúnmente las jerarquías de conceptos en las taxonomías: Ser vivo Mamífero Vaca Reptil Humano Serpiente Figura 4: Taxonomía parcial Los lenguajes orientados a objetos permiten definir estas mismas jerarquías, y adicionalmente, con la característica de polimorfismo, a nivel funcional garantizan la consistencia de tipos con dicha jerarquía. Ya no existe un chequeo de tipos excluyente (por ejemplo, en ejecución, los parámetros dados una función siempre deben tener los mismos tipos que los usados en su declaración). En vez de esto se trabaja con los conjuntos derivados de la taxonomía. Para el caso de la taxonomía de la figura 4, si se hace una función para mamíferos, es válido darle como parámetro cualquier cosa que según la taxonomía sea un mamífero (mamíferos, vacas y humanos en este caso). SerVivo respirar() Mamifero respirar() Vaca respirar() Humano respirar() Reptil respirar() Serpiente respirar() Figura 5: Modelo de clases correspondiente a la taxonomía Esto significa que en ciertas ocasiones los objetos pueden ser tratados como si fueran algo más general de lo que en realidad son. Un objeto Humano por ejemplo puede ser tratado como un mamífero o como un ser vivo, según se necesite. Cuando se da especialización entre las clases, es decir, cuando una clase redefine la manera de comportarse heredada de su clase padre (en este ejemplo cada ser vivo redefine la manera de respirar), el lenguaje debe garantizar, por consistencia, que cuando se les dé forma diferentes a los objetos, éstos se comporten como realmente son. Esta es la característica del encadenamiento dinámico. Gracias a las características de polimorfismo, y a la garantía que da el encadenamiento dinámico, se han vuelto muy populares los patrones de diseño, que son modelos orientados a objetos de soluciones parciales a problemas de diseño presentados comúnmente. También se ha vuelto muy popular el desarrollo de frameworks, aplicaciones con una lógica implementada parcialmente, que pueden usarse como base para desarrollar diferentes tipos de aplicaciones de propósitos diferentes pero con elementos comunes. Estos temas en particular han sido los más difíciles de asimilar por parte de los estudiantes, e incluso en el medio, pues es común encontrar literatura técnica que trata a estos conceptos de forma errónea o con definiciones incomprensibles. La forma tradicional de hacer evidente en la práctica estas dos características es el desarrollo de laboratorio donde ellas se vean reflejadas en resultados numéricos. Los inconvenientes que se han encontrado en este tipo de ejercicios son: - El aprendizaje no es efectivo para algunos estudiantes pues un resultado numérico no es significativo para ellos, y no los conduce a ninguna reflexión. El desarrollo de este tipo de laboratorios es poco motivante para algunos estudiantes, pues a pesar de estar usando una nueva tecnología y un nuevo paradigma, el resultado de su trabajo es igual a los resultados obtenidos en los proyectos de sus primeros cursos de programación (entran datos por consola y se da una salida textual una vez se haga el procesamiento). Enfoque de los juegos Desde hace mucho se ha visto el efecto motivante de los juegos en el aprendizaje de la programación. Se pueden citar ejemplos como logo, karel el robot, y más recientemente para el contexto de la programación orientada a objetos un juego desarrollado por la IBM llamado Robocode, en el cual se cuenta con una plataforma para simular batallas de robots programados en lenguaje Java. Muchas personas tienen la idea de que dentro del contexto del desarrollo de software, la creación de juegos es una práctica trivial y poco seria, que no aporta nada a las competencias requeridas para el ejercicio profesional de la ingeniería de sistemas. Sin embargo, a pesar de que en Colombia la producción comercial de juegos es prácticamente inexistente, como ejercicio académico éste ha permitido una muy buena asimilación de los conceptos básicos del paradigma orientado a objetos requeridos para la construcción de sistemas de software de cualquier índole con buenas bases arquitectónicas. Los juegos, por requerir la abstracción de modelos mucho más complejos y dinámicos que los manejados por una aplicación de negocio regular, requerir la integración de elementos de la formación en ingeniería poco aplicados como la geometría y el álgebra lineal, y por la motivación que ejerce sobre los estudiantes por su componente lúdico, es el ejercicio ideal de desarrollo de software como prueba de la asimilación de los conceptos de programación vistos en la teoría. Para el caso de los dos conceptos básicos en la enseñanza de la programación orientada a objetos mencionados anteriormente, al dar como reto la construcción de un juego al que se le puedan incorporar más personajes con diferentes comportamientos, y más situaciones sin tener que cambiar ninguna línea de código del juego base, fuerzan el uso, y hacen evidente visualmente, el funcionamiento de dichos conceptos. Ejercicios en el laboratorio La primera aproximación a los juegos dada en el curso es en un ejercicio en el laboratorio, cuyo propósito específico es hacer que los estudiantes reflexionen sobre el comportamiento de una serie de objetos que representan elementos en un contexto específico. En esta caso se hace que los estudiantes desarrollen un modelo de clases que represente una pista de baile, compuesta de bailarines, donde cada bailarín al realizar una serie consecutiva de pasos desarrolla su “estilo” de baile, haciendo uso de una serie de métodos básicos definidos en la clase Bailarín como subir y bajar tanto los brazos como las piernas. PistaBaile Bailarin moverATodos() BailarinRap siguientePaso() * siguientePaso() BailarinCumbia siguientePaso() BailarinRock siguientePaso() Figura 6: Modelo de clases del taller de laboratorio Para este ejercicio se pide la implementación de la operación que mueve a todos los bailarines en la pista de baile, pero de tal manera que quede abierto a nuevos bailarines que definan posteriormente, lo que obliga a hacer uso del polimorfismo. Cuando los estudiantes desarrollan la interfaz gráfica que representa el estado de todos los bailarines de la pista en cada segmento de tiempo, el resultado es una animación que les capta mucho la atención, y los hace reflexionar sobre por qué cada bailarín se mueve de forma diferente, dado que la operación que mueve a todos los bailarines al tiempo, no hace distinción entre los diferentes tipos de bailarines existentes. Figura 7: Salida de la herramienta desarrollada por los estudiantes, que muestra el estado del modelo (pista de baile) en tiempo de ejecución. Caso de uso: juego de invasores Este fue un proyecto final del primer curso de programación orientada a objetos. El propósito era implementar un marco de trabajo (framework), que tuviera implementada toda la lógica de un juego donde una nave controlada por el jugador se enfrenta a una diversidad de elementos, como los asteroides que no se mueven, y los elementos autónomos que se desplazan con determinados patrones, y atacan al jugador en caso de detectarlo. En un primer plazo, se debía entregar todo el marco de trabajo funcionando a través de una interfaz gráfica, con algunos elementos básicos. En la sustentación del proyecto, el requisito para aprobar la evaluación de éste era desarrollar un nuevo personaje con “personalidad” propia, e incorporarlo al juego, sin modificar en absoluto la lógica del mismo (si lo requería el juego estaba mal diseñado). Posteriormente, el estudiante explicaba por qué razón, sin haber modificado la lógica del juego, el nuevo elemento funcionaba correctamente, lo que demostraba su apropiación en la práctica de los conceptos dados en clase. Figura 8: Parte del modelo de clases con el que debían aprovechar el polimorfismo y el encadenamiento dinámico para cumplir con los requerimientos del proyecto de curso. Figura 9: Imagen del juego desarrollado por uno de los estudiantes. Cada elemento en la pantalla tiene “vida propia” y debe ser eliminado por el jugador. En la mayoría de proyectos entregados se identificó un especial esmero en la parte visual y en general, en dar valor agregado al producto, cosa por la cual nunca se ofreció nota adicional. Esto hizo evidente un alto grado de motivación y de apropiación del desarrollo, lo que se le podría atribuir a que los estudiantes vieron que el producto que desarrollaron podría iría más allá del uso académico como medio de evaluación de conocimientos y ser un producto con clientes específicos (parientes, amigos, etc.), a quienes finalmente les podrían mostrar los frutos de su formación de una forma más impactante. Conclusión Es importante que en la formación de los futuros ingenieros de sistemas no se sesgue la visión de las labores que pueden realizar como profesionales. Muchos egresados sólo tienen la visión de desarrollar aplicaciones para manejar información y procesos en las organizaciones, porque muchas veces fue lo único a lo que se enfrentaron en su formación. En este momento donde Colombia tiene uno de los índices más bajos de exportación de tecnología en Latinoamérica es importante darle a los futuros profesionales las bases para que con su ingenio y creatividad puedan, eventualmente, crear soluciones que revolucionen, y no limitarse exclusivamente a aplicar tecnologías existentes a problemas de manejo de información. La mayoría de los detractores de paradigmas como la programación orientada a objetos, lo son porque consideran que ser informático o ingeniero de sistemas equivale a ser alguien que desarrolle aplicaciones que manejan bases de datos, ya que no tienen una visión del verdadero potencial de la tecnología en contextos que no necesariamente están relacionados con el manejo de la información en una organización, como es el caso de la inteligencia artificial, tecnologías para la educación como los simuladores, o incluso el campo de la tecnología para el entretenimiento.