lunes, 9 de septiembre de 2013

Sobre la Programación Orientada a Objetos

Me crié (hablando de programación) con Basic, y con uno de los viejos, donde había que ponerle a todo números de lineas y no teníamos subs. Eso hizo que mi forma de pensar un código fuera fuertemente "estructurada". Más tarde, alguien me sugirió QBasic como una forma de hacer lo mismo que hacía en Basic (el mismo código) pero con un editor más bonito. Explorando qué más tenía QBasic encontré las subs (funciones o subrutinas) y eso me hizo un poco más modular. Cuando pasé a VisualBasic, mi forma de pensar no cambió. La poca y bizarra orientación a objetos de los primeros VB pasó totalmente desapercibida para mí, y sólo incorporé el concepto de evento.

Con ese background (que llevó varios años y estaba bien acentado), entré a la universidad y me dispararon directamente con la Programación Orientación a Objetos (POO) y bastante de C++. Además, era el primer año que la materia se daba en C++; los docentes eran muy buenos programadores con Pascal/Delphi, y tuvieron que aprender C++ solo para actualizar la materia. Todo esto y más hicieron que la orientación a objetos parezca algo forzada. Y si bien no la cuestioné de entrada, tampoco la entendí ni aproveché tanto en mis primeros proyectos. Solo para la parte visual parecía realmente tener sentido.

Más tarde, quiso el destino que sea yo uno de los que daba las prácticas de esa materia, y con el tiempo también comencé a dictar una de las teorías. Ahora estaba del otro lado, y tenía que venderles y explicarles el nuevo paradigma a chicos que entraban sin costumbres, o peor aún, con malas costumbres como las mías. Mi visión de la orientación a objetos había cambiado por el simple hecho de haber pasado unos años programando con C++. Le había encontrado el gusto desde el punto de vista sintáctico, desde la prolijidad, seguridad y reutilización del código, y otras consideraciones bastante pragmáticas. Pero recién al leer el libro de Bruce Eckel encontré una definición simple, directa, concisa, entendible, etc... en fin, a mi gusto maravillosa:

 "...la POO permite describir el problema en términos del problema, en lugar de usar términos de la computadora en la que se ejecutará la solución."

En la sección 1.1 explica muy bien la idea. Básicamente, todos los lenguajes de programación ofrecen abstracciones de algo. Los primeros lenguajes comenzaron a ofrecer abstracciones cada vez más potentes de las cosas que era capaz de hacer o manejar la computadora, y creo que esto fue un camino totalmente lógico y natural. Así subió el nivel de los lenguajes, y se pasó de hablar de instrucciones de máquina y registros, a hablar de variables, funciones, archivos, arreglos, etc. Pero el programador debía entonces llevar el problema real que quería resolver con su programa al espacio de cosas que manejaba una computadora y que podían representar esos lenguajes. Con la orientación a objetos surge entonces la posibilidad de plantear el las soluciones en los términos del problema mismo, y ya no en los términos de la máquina.

¿Como es esto? Según yo lo veo, con la orientación a objetos, el pasaje desde el problema real al mundo de las computadoras se da en dos partes. Por un lado está el modelado de cada clase, el diseño de sus tripas; y por otro el modelado del diagrama de clases (cuáles son y cómo se relacionan). Los objetos se corresponden con elementos del problema real que se resuelve (cliente, alquiler, venta, alumno, etc), y sus relaciones y mensajes también provienen de este mismo espacio. Entonces, en este nivel, la solución se plantea según los términos del problema, y no según los de la computadora. Pero hay que hacer esos objetos, hay que escribir los métodos, elegir los atributos privados, en fin, todo lo que en el nivel anterior no se ve. Y ahí es donde se hace el real pasaje a los términos de la computadora. Al hacerlo ahí, el problema de este pasaje es más simple y acotado, ya que cada objeto es una unidad en sí mismo, autocontenido, que se encarga de gestionar y proteger lo suyo. Y de esto se trata programar, ya lo dijo Kerningham hace mil años, de manejar la complejidad, de saber reducirla. Estamos particionando el problema del cambio de espacio en muchos problemas menores, problemas locales a uno o unos pocos objetos, de forma que una vez resueltos esos problemas, las grandes reglas del sistema que se quiere modelar se pueden plantear en los términos del verdadero sistema, liberándonos (en cierto sentido) de las restricciones de la máquina que las va a ejecutar (es decir, con los objetos y sus mensajes, sin pensar tanto en cómo funcionan por dentro).

Pero ojo que con el párrafo anterior puedo llegar a dar una idea a mi gusto errónea y que siempre miro de forma despectiva: que el diseño del diagrama de clases está separado de la implementación de dichas clases. Esto es por la forma en que muchos encaran la ingeniería de software, como una actividad previa a (y separada de) la codificación, donde el ingeniero de software dibuja diagramitas según sus reglas de libro sin importarle cómo van a implementarse en realidad. No se trata de disociar ambos mundos, sino que para ser bueno en uno creo que es obligatorio tener experiencia y haber sufrido un poco en el otro. Es siempre un tire y afloje entre el diseño ideal y la implementación más eficiente, y se necesita un compromiso de ambos para llegar un sistema razonable en los dos aspectos. Bien pensada, la orientación a objetos nos permite atacar mejor esa complejidad y producir código más prolijo, más fácil de mantener, más flexible, y no es una condición necesaria sacrificar tiempo de desarrollo, performance, u otras cuestiones esenciales en la codificación. En general, las aplicaciones de Java, no se porqué, tienden a ser excelentes contraejemplos, con capas y capas de abstracciones a veces (a mi gusto) innecesarias y exageradas, aunque a nivel teórico el lenguaje sea muy muy interesante y tenga aspectos muy bien pensados y resueltos.

En fin, este post no era para banagloriar la orientación a objetos, sino para compartir una valiosa mirada sobre la misma, que por simple y obvia que le pueda parecer a varios, dada la forma en que se enseña POO en muchísimos casos, puede llevarnos años descubrir. Esta distorsión pienso que puede ser la que llevó a uno de los padres de la POO a criticar C++. Y para cerrar y no dejar una idea fanatista, dejo una cita de alguien que hizo el camino de C a C++ cuando ya era un gigante de la programación, y cuya experiencia no creo que nadie se atreva a cuestionar:

“Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function.” (John Carmack)

1 comentario:

  1. Hola... Soy muuuuy novato en programación. Apenas si hago algunos scripts muy pobres en Python. ¿Como puedo mejorar? Que debería hacer para ser un mejor programador?. Como encuentro problemas interesantes que resolver?...
    Descubrí tu blog a través de Pseint, esta bárbaro. Me gustó mucho desde la primera vez que lo probé. Como llegas a lograr algo así?. Que buen manual de c++ me recomendarías para empezar enserio?... Muchas gracias!...

    ResponderEliminar