domingo, 29 de julio de 2012

1.1. El progreso de abstracción.

1.1. El progreso de abstracción

Es bueno saber que los lenguajes de programación nos simplifican mucho el trabajo. De no ser por ellos, deberíamos tratar con el ordenador usando comandos sumamente extraños y un tanto extensos incluso para pequeñas instrucciones.

En un primer momento, surgió el mencionado lenguaje ensamblador, el cual viene a ser una abstracción de la máquina subyacente.

Como sabemos, el “lenguaje máquina” se corresponde con el “lenguaje binario”. Lo que quiere decir que, las instrucciones directas al ordenador deberían expresarse en 1s y 0s.

Lo que el lenguaje ensamblador hizo es implementar una representación simbólica de dichos códigos de máquina binarios.

Muchos lenguajes llamados “imperativos” le siguieron (tales como Fortran, BASIC y C). Éstos representaban abstracciones del lenguaje ensamblador, lo que suponía grandes mejores. Sin embargo, aún se requería idear la solución en términos más del ordenador que en términos del problema. Esto es lo que se conoce como un lenguaje de “bajo nivel”.


El esfuerzo requerido para usar esta correspondencia era un factor determinante en la programación. Este detalle era el que hacía costosos los procesos de escritura y mantenimiento de los programas.

Con el paso del tiempo las abstracciones han sido de mayor grado, a tal punto que se crearon lenguajes de programación para programar basados únicamente en símbolos gráficos. Pero esto es demasiado restrictivo. Es como tener acceso a un programa para programar sólo dando clicks a botoncitos, eligiendo opciones pre-establecidas.

Como para citar un ejemplo…
Hubo un tiempo en que estaba tratando de aprender LUA y XML (hace muchos años en realidad), pero esto se quedó sólo en querer. Era porque estaba administrando un juego online, y las modificaciones que le hacía era en base a muchas guías que leía en esos tiempos (sin contar con conocimiento alguno de programación). Sentía entonces esas necesidad de aprender, para poder crear “scripts” y “spells” para el juego. Fue muy curioso, pues encontré un programa que me permitía crear esos “spells” con sólo dar clicks. Allí se me preguntaba el daño promedio, mínimo y máximo del hechizo. Pedía que especifique la animación que deseaba para dicho conjuro y si era un ataque a distancia (en el que debía delimitar un rango de alcance) o uno de campo (donde debía especificar el área que acapararía). El problema fue que, cuando surgió un pequeño desperfecto con uno de los spells ya existentes, éste no podía editarlo desde ese “Editor de spells”, puesto que no traía consigo todos los “efectos posibles”. En un foro se me explicó que sólo había que cambiar un “true” por un “false”, y yo, lamentablemente (en aquel entonces) no supe tan siquiera corrgir ese minúsculo error.

Puede argumentarse que dichos métodos de programación son demasiado restrictivos. Es decir, son muy útiles, pero sólo pueden crearse para un tópico en específico.

Lo bueno es que los lenguajes POO van mucho más allá. Éstos nos proporcionan herramientas para programar en términos del problema, sin ser restrictivo. La idea de esta nueva forma de programación es crear objetos como solución. Así, cuando alguien más (o incluso nosotros mismos) lea el código, podrá ver reflejada en este una descripción del problema. Esto es porque la solución estará dada en términos del problema (en vez de instrucciones de bajo nivel que más se asemejan a términos del ordenador).

Cada objeto se asemeja a una pequeña computadora: tiene un estado y operaciones que se le puede pedir que haga. Y esto no es un detalle negativo, es un aspecto positivo, pues se corresponde con el mundo real (que es donde existen los problemas que vamos a resolver): cada objeto tiene características y comportamientos.
 
Smalltalk fue el primer lenguaje de programación orientado a objetos con éxito, y uno de los lenguajes en que está basado C++. Alan Kay resume 5 características básicas de este lenguaje:
  1. Todo es un objeto. Podemos comparar un objeto con una variable elaborada: almacena datos, y podemos “hacer peticiones” a este objeto, solicitando que realice operaciones en sí mismo. Podemos tomar cualquier componente conceptual del problema que estamos intentando resolver (perros, edificios, servicios, etc) y representarlos como un objeto (en nuestro programa).
  2. Un programa es un grupo de objetos, los que se encuentran enviando mensajes a otros para decirles qué hacer. Los mensajes que se envían como petición a los objetos son concretamente invocaciones de funciones (las que pertenecen a algún objeto en particular).
  3. Cada objeto tiene su propia memoria constituida por otros objetos. Es decir, pueden crearse nuevos tipos de objetos en base a otros ya existentes, haciendo “paquetes” de estos. Esto es lo que permite reducir la complejidad de los programas (pues se ocultan objetos dentro de otros).
  4. Cada objeto tiene un tipo. Más concretamente, cada objeto es una instancia de una clase.
  5. Objetos de un mismo tipo pueden recibir los mismos mensajes (mismas peticiones, mismos llamados de funciones). Así, las peticiones que podemos realizar a un objeto de tipo “figura” las podemos realizar también con objetos de tipo “círculo”, siempre que se haya definido la relación “un círculo es una figura”. Esta sustituibilidad es uno de los conceptos más poderosos en la POO.