Download Capítulo II. Tipos Abstractos de Datos. Estructuras de Datos, su

Document related concepts

Programación funcional wikipedia , lookup

Polimorfismo (informática) wikipedia , lookup

Common Lisp wikipedia , lookup

Lisp wikipedia , lookup

Scheme wikipedia , lookup

Transcript
Capítulo II. Tipos Abstractos de Datos. Estructuras de Datos, su
implementación y enseñanza en la carrera de Informática.
1.1 Introducción. Los índices están mal sería II.1 , todo está así
El estudio de las estructuras de datos es casi tan antiguo como el nacimiento de la
programación, y se convirtió en un tema capital en este ámbito desde finales de la década
de los 60. (Badía 2004)
Con la aparición de los lenguajes de programación estructurados, surge el concepto de tipo
de datos, definido como un conjunto de valores que sirve de dominio de ciertas
operaciones. En estos lenguajes (C, Pascal y similares), los tipos de datos se usan sobre
todo para clasificar los objetos de los programas - variables, parámetros y constantes - y
determinar qué valores pueden tomar y qué operaciones se les pueden aplicar.
Esta noción, no obstante, se reveló insuficiente en el desarrollo de software a gran escala,
dado que el uso de los datos dentro de los programas no conocía más restricciones que las
impuestas por el compilador, a los nuevos tipos de datos definidos por el usuario no se
restringía de ninguna manera su ámbito de manipulación. No entiendo esto
Para solucionar esta carencia, diversos investigadores introdujeron a mediados de la
década de los 70 el concepto de Tipo Abstracto de Datos, abreviadamente, TAD que
considera un tipo de datos no sólo como el conjunto de valores que lo caracteriza sino
también como las operaciones que sobre él se pueden aplicar, juntamente con las diversas
propiedades que determinan inequívocamente su comportamiento. Todos estos autores
coincidieron en la necesidad de emplear una notación formal para describir el
comportamiento de las operaciones, no sólo para impedir cualquier interpretación ambigua
sino para identificar claramente el modelo matemático denotado por el TAD. (Knuth 1973;
Lipschutz 1977; Goguen, Thatcher et al. 1978)
La abstracción es un mecanismo fundamental para la comprensión de fenómenos o
situaciones que implican gran cantidad de detalles. La idea de abstracción es uno de los
conceptos más potentes en el proceso de resolución de problemas. Se entiende por
abstracción la capacidad de manejar un objeto como un concepto general, sin considerar la
enorme cantidad de detalles que pueden estar asociados con dicho objeto. Sin abstracción
no sería posible manejar, ni siquiera entender, la gran complejidad de ciertos problemas.
(Guttag and Liskov 1986; Blackwell 1998)
El proceso de abstracción presenta dos aspectos complementarios:

descartar los aspectos relevantes del objeto COMO QUE DESCARTAR LO
RELEVANTE

ignorar aspectos irrelevantes del mismo (la irrelevancia depende del nivel de
abstracción, ya que si se pasa a niveles más concretos, es posible que ciertos
aspectos pasen a ser relevantes).
Uno de los puntos más cruciales asociados con el diseño de un nuevo sistema involucra la
gestión de la complejidad del proceso de diseño.
Habitualmente los buenos diseñadores emplean alguna forma de abstracción como
herramienta para tratar esta complejidad. En este momento puede ser utilizado un tipo
especial de abstracción conocido como abstracción de datos. Esto implica una
descripción abstracta o lógica, tanto de los datos requeridos por el sistema informático
como de las operaciones que pueden ser ejecutadas con esos datos.
El uso de la abstracción de datos durante el desarrollo del software permite al diseñador
concentrase en cómo son usados los datos en el sistema para resolver el problema que le
ocupa, sin tener que preocuparse por la representación y tratamiento de los datos en la
memoria del computador, de ahí que se plantee que la verdadera utilidad de los Tipos
Abstractos de Datos aparece en el diseño de nuevos tipos de datos. (Heileman 2003)
La extrapolación de esta técnica a sistemas de gran tamaño conduce al llamado diseño
modular de las aplicaciones y se caracteriza por el hecho de dividir el problema original en
varios subproblemas más pequeños, cada uno de ellos con una misión bien determinada
dentro del marco general del proyecto, que interaccionan de manera clara y mínima, de tal
forma que todos ellos juntos solucionan el problema inicial; si algunos subproblemas siguen
siendo demasiado complicados, se les aplica el mismo proceso, y así sucesivamente hasta
llegar al estado en que todos los subproblemas son lo bastante sencillos como para
detener el proceso. El resultado es una estructura jerárquica que refleja las
descomposiciones efectuadas; cada descomposición es el resultado de abstraer las
características más relevantes del problema que se está tratando de los detalles
irrelevantes en el nivel de razonamiento actual, los cuales adquieren importancia en
descomposiciones sucesivas. Desde el punto de vista de su gestión, cada subproblema es
un Tipo Abstracto de Datos que se encapsula en lo que se denomina un módulo;
1
precisamente, la mejora respecto al diseño descendente proviene de la ocultación de la
representación de los datos y de la limitación de su manipulación al ámbito del módulo que
define el tipo. A primera vista, puede parecer costoso, e incluso absurdo, dividir una
aplicación en módulos y escribir procedimientos y funciones para controlar el acceso a la
estructura que implementa un Tipo Abstracto de Datos, sin embargo esta metodología
abunda en diversas propiedades interesantes:

Abstracción. Los usuarios de un Tipo Abstracto de Datos no necesitan conocer
detalles de implementación (tanto en lo que se refiere a la representación del tipo
como a los algoritmos y a las técnicas de codificación de las operaciones), por lo que
pueden trabajar en un grado muy alto de abstracción. Como resultado, la
complejidad de un programa queda diluida entre sus diversos componentes.

Corrección. Un TAD puede servir como unidad indivisible en las pruebas de
programas, de manera que en una aplicación que conste de diversos tipos
abstractos no tengan que probarse todos a la vez, sino que es factible y
recomendable probarlos por separado e integrarlos más adelante. Evidentemente,
es mucho más fácil detectar los errores de esta segunda manera, porque las
entidades a probar son más pequeñas y las pruebas pueden ser más exhaustivas.

Eficiencia. La separación clara entre un programa y los TAD que usa favorece la
eficiencia, ya que la implementación de un tipo se retrasa hasta conocer las
restricciones de eficiencia sobre sus operaciones, y así se pueden elegir los
algoritmos óptimos.
La implementación de un Tipo Abstracto de Datos supone una traducción de su
especificación en la sintaxis de un lenguaje de programación particular. Esta traducción se
compone de las declaraciones de variables apropiadas, que sean necesarias para definir
los datos y un procedimiento o rutina de acceso que implemente cada una de las
operaciones requeridas por el TAD. El término Estructura de Datos se refiere a una
colección de variables que están relacionadas de alguna forma específica.
1.2 Tipos Abstractos de Datos, Estructuras de Datos y tipos de datos.
Se puede decir que la abstracción permite estudiar los fenómenos complejos siguiendo un
método jerárquico, es decir, por sucesivos niveles de detalle. Generalmente, se sigue un
sentido descendente, desde los niveles más generales a los niveles más concretos.
2
Los programas son objetos complejos que pueden contener varios miles de instrucciones,
cada una de las cuales puede dar lugar a un error del programa y que, por lo tanto,
necesitan mecanismos de definición que eviten en la medida de lo posible que el
programador cometa errores.
En el proceso de programación se puede extender el concepto de abstracción tanto a las
acciones, mediante la llamada abstracción procedural (uso de procedimientos), como a los
datos, mediante los llamados tipos abstractos de datos.
La aplicación a los datos de las ideas de abstracción y de ocultación de información ha
tardado más tiempo en producirse. El concepto de tipo abstracto de datos, propuesto
hacia 1974 por John Guttag, vino a desarrollar este aspecto. Análogamente a los
procedimientos, los llamados tipos abstractos de datos constituyen un mecanismo que
permite generalizar y encapsular los aspectos relevantes sobre la información (datos) que
maneja el programa. (Liskov and Guttag 2001)
No se deben confundir los conceptos de tipo de datos, estructura de datos y tipo abstracto
de datos. Todos ellos constituyen diferentes niveles en el proceso de abstracción referida a
los datos.
Los datos son las propiedades o atributos (cualidades o cantidades) sobre hechos u
objetos que procesa el ordenador. El tipo de datos, en un lenguaje de programación, define
el conjunto de valores que una determinada variable puede tomar, así como las
operaciones básicas sobre dicho conjunto. Los tipos de datos pueden variar de un lenguaje
a otro, tanto los tipos simples como los mecanismos para crear tipos compuestos. Para el
usuario, el proceso de representación es invisible. El programador no manipula
directamente las cadenas de bits que constituyen los datos, sino que hace uso de las
operaciones previstas para cada tipo de datos.
Entre el nivel de los tipos de datos y el nivel de los tipos abstractos nos encontramos con
las llamadas estructuras de datos. Las estructuras de datos son conjuntos de variables,
quizás de tipos distintos, relacionadas (conectadas) entre sí de diversas formas y las
operaciones definidas sobre esa agrupación. Ejemplos de estructuras de datos las
podemos encontrar en muchos ámbitos, desde las matemáticas (estructuras algebraicas:
grupo, anillo) hasta el mundo de los negocios (estructura de una empresa). Los elementos
de una estructura de datos dependen del lenguaje de programación a través de los tipos de
datos que los definen. Sin embargo, la estructura en sí, que está definida por el tipo de
relación entre los elementos, no depende del lenguaje de programación empleado. Las
estructuras de datos se caracterizan por el tipo de los elementos de la estructura, las
3
relaciones definidas sobre los elementos y las operaciones permitidas sobre la estructura.
Operaciones típicas sobre estructuras de datos suelen ser: acceder a los elementos (por la
posición que ocupan o por la información que contienen), buscar elementos, insertar o
borrar elementos, modificar las relaciones entre los elementos. Al nivel de las estructuras
de datos, ya no tienen relevancia las operaciones que se puedan realizar sobre los
componentes individuales de la misma, solamente la tienen las operaciones que implican a
la estructura globalmente.
En el nivel más alto de abstracción estarían los tipos abstractos de datos, estos se pueden
ver como modelos matemáticos sobre los que se definen una serie de operaciones. El tipo
abstracto de datos es una colección de valores y operaciones que se definen mediante una
especificación que es independiente de cualquier representación. Para representar el
modelo matemático básico de un TAD se emplean estructuras de datos y las operaciones
definidas en el modelo se representan mediante procedimientos.
Por ejemplo, se podría definir el TAD número complejo como un objeto con dos
componentes que son números reales y sobre el que se definen las operaciones suma y
producto de números complejos. En una definición de este tipo no importa si en un
programa concreto se utiliza una estructura tipo registro con dos campos para representar
los datos o bien una estructura tipo arreglo con dos elementos. Desde el punto de vista
formal ese tipo de información es irrelevante. Así mismo, no es necesario conocer cómo se
realizan las operaciones definidas formalmente, sólo importa qué hacen para poder usarlas
correctamente.
1.3 Diferentes paradigmas de programación para implementar las
Estructuras de Datos.
El modelo general de las computadoras, desde que fue esbozado por von Neumann, no ha
cambiado mucho, mientras que la invención humana para proponerse nuevos problemas a
resolver, usando la computadora, parece no tener límites. (Aspray 2000)
En consecuencia, los lenguajes de programación tienen que adaptarse a éstas crecientes
necesidades y aumentar la expresividad para poder resolver problemas muy diversos y
cada vez más complejos.
Además, tienen que ofrecer cierta eficiencia en la ejecución. Es un logro difícil de alcanzar
y un reto la selección adecuada, tanto de las Estructuras de Datos como de los Lenguajes
de programación para implementarlas.
4
1.3.1 Lenguajes funcionales.
Tradicionalmente los matemáticos han resuelto problemas usando el concepto de función,
la cual convierte ciertos datos en resultados. Si se conoce cómo evaluar una función
usando la computadora, se pueden resolver automáticamente muchos problemas. Este
análisis fue realizado por algunos matemáticos que consideraron la computadora una
herramienta importante para su trabajo, creando los lenguajes de programación
funcionales, los que aprovechan la posibilidad que tienen las funciones para manipular
datos simbólicos, y no solamente numéricos, y la propiedad que les permite componer,
creando de esta manera, la oportunidad para resolver problemas complejos a partir de las
soluciones a otros más sencillos. También se incluyó la posibilidad de definir funciones
recursivamente. (Steele and Sussman 1979)
Un lenguaje funcional ofrece conceptos que son muy entendibles y relativamente fáciles de
manejar. El lenguaje funcional más antiguo, y seguramente el más popular hasta la fecha,
es LISP, diseñado por McCarthy
en la segunda mitad de los años 50. Su área de
aplicación es principalmente la Inteligencia Artificial. En la década de los 80 hubo una
nueva ola de interés por los lenguajes funcionales, añadiendo la tipificación y algunos
conceptos modernos de modularización y polimorfismo. (Mcarthy 1965)
Programar en un lenguaje funcional significa construir funciones a partir de las ya
existentes. Por lo tanto es importante conocer y comprender bien las funciones que
conforman la base del lenguaje, así como las que ya fueron definidas previamente. De esta
manera se pueden ir construyendo aplicaciones cada vez más complejas.
El uso del LISP en la implementación de Listas, como Estructura de Datos, hace sencilla y
elegante la programación de las operaciones básicas y las aplicaciones a problemas
concretos, como el cálculo de la derivada de funciones, trabajo con polinomios, etc.
1.3.2 Lenguajes Lógicos.
Otra forma de razonar para resolver problemas en matemáticas se fundamenta en la lógica
de primer orden. El conocimiento básico de las matemáticas se puede representar en la
lógica en forma de axiomas, a los cuales se añaden reglas formales para deducir aspectos
verdaderos (teoremas) a partir de los axiomas. Gracias al trabajo de algunos matemáticos,
de finales de siglo pasado y principios de éste, se encontró la manera de automatizar
computacionalmente el razonamiento lógico -particularmente para un subconjunto
5
significativo de la lógica de primer orden- que permitió que la lógica matemática diera
origen a otro tipo de lenguajes de programación, conocidos como lenguajes lógicos.
(Colmeraure and Roussel 1993; Lezcano, Lobato et al. 2000)
En la programación lógica el proceso de descripción de un dominio de aplicación se lleva a
cabo mediante la conceptualización de los objetos y las relaciones que hipotéticamente
existen, lo cual se expresa a través de un lenguaje formal apropiado.
La noción de un objeto puede ser amplia. Pueden ser objetos concretos (un circuito
específico, una persona especifica) o abstractos (el número dos, el conjunto de todos los
enteros, el concepto de justicia). Por otra parte, pueden ser primitivos o compuestos, como
es el caso de un circuito que consta de muchos componentes. (Lezcano 1998; Lezcano,
Lobato et al. 2000)
Una relación, es una cualidad o atributo de un grupo de objetos con respecto a otros. Por
supuesto, una relación en particular puede mantenerse para más de un grupo de objetos.
La característica esencial de la programación lógica es su semántica declarativa, de ahí la
forma simple de determinar la veracidad o falsedad de cada una de las sentencias.
La mayoría de los sistemas de programación lógica usan una forma clausal (variante del
cálculo de predicados). Esta forma es extremadamente expresiva por la existencia de
operadores lógicos y variables, lo que hace posible codificar información parcial acerca de
un dominio determinado. En lenguajes más restringidos como los marcos, se deben
escribir procedimientos para codificar información parcial. El tipo más simple de expresión,
en la forma clausal, es el átomo. Un átomo expresa una relación específica, válida para
un grupo determinado de objetos.
Dentro de los lenguajes orientados a la lógica tiene significativa importancia el Prolog, que
ofrece la ventaja de que él mismo constituye un motor de inferencia para sistemas
expertos, con lógica de primer orden en cuyo caso el programa es realmente la base de
conocimiento más un conjunto de datos de partida. Es el primer lenguaje lógico y el más
conocido y utilizado. Sus orígenes se remontan a los inicios de la década de los 70 con los
trabajos del grupo de A. Colmerauer en Marsella, Francia. (Colmeraure and Roussel 1993)
También en este caso, las aplicaciones a la Inteligencia Artificial mantienen el lenguaje vivo
y útil.
6
En el caso de la programación lógica, el trabajo del programador se restringe a la buena
descripción del problema en forma de hechos y reglas. A partir de ésta se pueden
encontrar muchas soluciones dependiendo de como se formulen las preguntas (metas),
que tienen sentido para el problema. Si el programa está bien definido, el sistema
encuentra automáticamente las respuestas a las preguntas formuladas. En este caso ya no
es necesario definir el algoritmo de solución, como en la programación imperativa, en
cambio, lo fundamental aquí es expresar bien el conocimiento sobre el problema mismo.
En programación lógica, al igual que en programación funcional, el programa, en este caso
los hechos y las reglas, están muy alejados del modelo von Neumann que posee la
máquina en la que tienen que ser interpretados; por lo tanto, la eficiencia de la ejecución no
puede ser comparable con la de un programa equivalente escrito en un lenguaje
imperativo. Sin embargo, para cierto tipo de problemas, la formulación del programa mismo
puede ser mucho más sencilla y natural.
Una de las limitaciones claves de la mayoría de los sistemas de programación lógica, es
que sus métodos deductivos son inadecuados. La resolución es completa, desde el punto
de vista que ella puede probar cualquier conclusión lógicamente implicada por su base de
conocimiento. Sin embargo, un buen sistema debería ser capaz de arribar a conclusiones a
partir de datos inciertos, razonar analógicamente y generalizar su conocimiento
apropiadamente si se quiere ser realmente efectivo.
En un inicio se construyeron muchos sistemas inteligentes que utilizaban como base el
cálculo de predicado de primer orden, dado su fuerte y general poder expresivo y su
semántica bien definida. Sin embargo, debido a que las construcciones del lenguaje son
muy refinadas y no brindan facilidades para describir estructuras más complejas, los
expertos del dominio presentaban dificultades en el uso del cálculo de predicados y la
comprensión del conocimiento expresado en éste. Además, la generalidad del cálculo de
predicados ha puesto un límite significativo para el desarrollo de facilidades de deducción
efectiva usando el conocimiento expresado en él.
Estas dificultades motivaron el desarrollo de redes semánticas y lenguajes de
representación orientados a objetos basados en marcos. (Lezcano, Lobato et al. 2000)
7
1.3.3 Paradigma de la Programación Orientada a Objeto.
A mediados de los años 60 se empezó a vislumbrar el uso de las computadoras en la
simulación de problemas del mundo real. Pero el mundo real está lleno de objetos, en la
mayoría de los casos complejos, los cuales difícilmente son representados por los tipos de
datos primitivos de los lenguajes imperativos. Así es que a dos noruegos, Dahl y Nygaard,
se les ocurrió el concepto de objeto y sus colecciones, llamadas clases de objetos, que
permitieron introducir abstracciones de datos a los lenguajes de programación. La
posibilidad de reutilización del código y sus indispensables modificaciones, se reflejaron en
la idea de las jerarquías de herencia de clases. Ellos introducen el concepto de
polimorfismo. Todos estos conceptos fueron presentados en el lenguaje Simula 67. Aunque
diseñado como lenguaje de propósito general, Simula tuvo su mayor éxito en las
aplicaciones de simulación discreta, gracias a la clase SIMULATION que facilitaba
considerablemente la programación. (Dahl, Myhrhaug et al. 1970)
La Programación Orientada a Objetos (POO), que por todo lo anterior varios han dado en
llamar la Programación Estructurada de los 90's, encuentra en este contexto un terreno
fértil. Lo relevante de la Programación Orientada a Objetos está dado porque en lugar de
tratar de modelar un problema en algo familiar a la computadora se trata ahora de acercar
la computadora al problema. Es decir, modelar la realidad del problema a través de
entidades independientes pero que interactúan entre sí y cuyas fronteras no estén
determinadas por su instrumentación computacional sino por la naturaleza del problema.
Estas entidades serán denominadas objetos por analogía con el concepto de objeto en el
mundo real. (Heileman 2003)
Programar en un lenguaje de programación orientado a objetos es definir clases (nuevos
tipos de datos) que expresan una determinada funcionalidad la cual es común a todos los
individuos de una clase. A través de esta funcionalidad los objetos o instancias concretas
de una clase dan respuesta a las solicitudes (mensajes) que les envían otros objetos. Las
clases deben ser lo suficientemente cerradas como para que cada objeto pueda ocultar la
información (datos) que lo caracteriza como individuo. Es un problema interno del objeto
cómo llevar a cabo la funcionalidad descrita en la clase. Esto es, tal vez, lo más elegante
de la POO, la sencillez de sus conceptos.
8
Visto en la óptica de las arquitecturas convencionales de computadoras, en la POO los
datos no circulan abiertamente por todo el sistema como en la programación tradicional.
Los programas no se dividen en declaraciones pasivas de estructuras de datos y funciones
(que tal vez actúen sobre algunas de las estructuras de datos). Los datos están ahora
encerrados dentro de cada objeto y éste es quien decide internamente cómo trabajar con
ellos para dar respuesta a una solicitud de otro objeto.
Por otra parte estas clases deben ser lo suficientemente abiertas para permitir la
reutilización, adaptación y extensión de las mismas a nuevas funcionalidades, sin correr el
riesgo de afectar el funcionamiento de lo que ya está correcto. Esta aparente contradicción,
de lo que se conoce como principio abierto-cerrado, es la piedra angular de la POO.
En ausencia de una definición formal de qué es la POO, algunos prefieren identificarla por
sus objetivos. (Sedgewick 1992; Horstmann 1995; Heileman 2003)
Tres objetivos fundamentales persigue la POO para facilitar la experimentación:
o La robustez de las partes, que garantiza su integridad y funcionamiento propio
(lo cual a su vez facilita disminuir las fallas). Esto es posible a través de
recursos como el encapsulamiento y el manejo de excepciones.
o La reusabilidad y la extensibilidad. Que se puedan derivar, más que definir,
nuevas clases de objetos a partir de las ya existentes, facilitándole con ello al
programador el desarrollo de prototipos y una rápida exploración en las
nuevas ideas. Esto se facilita en los Lenguajes Orientados a Objetos
mediante la redefinición de operadores y funciones, la genericidad, la
herencia y el polimorfismo.
Esta búsqueda de aprovechar lo existente es una de las características básicas de la POO.
Algunos de estos recursos como el polimorfismo y la jerarquía de clases a través de la
herencia dotan de recursos para clasificar lógicamente a los objetos, evitando las
redundancias y obviando restricciones que otros paradigmas de programación imponen.
Otros conceptos como la genericidad, la manipulación de excepciones no son inherentes al
modelo de objeto pero encuentran en este paradigma una mejor forma de expresión.
La concepción de Programación Orientada a Objeto ha originado nuevos lenguajes para
expresarla, los Lenguajes Orientados a Objeto (LOO). Algunos de los más importantes son
9
SMALLTALK, Eiffel, Actor, Modular. (Reenskaug, Wold et al. 1996; Group 2003; Meyer
2005)
Sin embargo la dificultad para algunos de hacer el tránsito de las viejas a las nuevas
técnicas y la gran carga instalada (mental y electrónicamente) de software viejo, ha
provocado el surgimiento de extensiones de lenguajes tradicionales (de los mejores entre
los tradicionales como LISP, Pascal, C) que pretenden establecer un compromiso con sus
viejos programadores y las nuevas ideas. (Koschmann 2001; Zarko Gajic 2006)
En un TAD se especifican las propiedades funcionales de una estructura de datos y sus
operaciones, y éstas se implementan en términos de las construcciones existentes en el
lenguaje. Este concepto tuvo su primera materialización en el concepto de clase del
lenguaje SIMULA 67. (Dahl, Myhrhaug et al. 1970; Hennessy 1993; Jonnan 2000)
Junto con las clases aparecen en este lenguaje el concepto de herencia, mediante la cual
las subclases heredan las propiedades declaradas en la interfaz de las superclases y
pueden definir operaciones y datos adicionales que especializan el comportamiento de la
subclase. SIMULA tuvo un gran impacto en muchos de los lenguajes de programación
modernos.
MODULA-2 ofrece un excelente mecanismo de abstracción de datos, el cual incluye un
cierto grado de protección ya que no permite acceder directamente al estado interno del
TAD. Pero presenta algunas limitaciones como que los nombres de los procedimientos
usados en un módulo tienen que ser únicos y que los TAD pueden operar un solo tipo de
dato. MODULA-2 es uno de los primeros lenguajes de programación ampliamente
difundidos en usar la modularidad como un principio fundamental de estructuración. La
última versión conocida como Modula-3 fue diseñada por Luca Cardelli. (Cardelli, Donahue
et al. 1989)
ADA resuelve parcialmente ambos problemas mediante la sobrecarga de operadores
(operator overloading) y las unidades de programas genéricas (generic program unit). La
primera se refiere a permitir a un programador usar múltiples operadores con el mismo
nemotécnico. La distinción entre los operadores puede ser determinada en tiempo de
compilación examinando los tipos y el número de parámetros. El segundo término se refiere
a la posibilidad de definir un módulo para ser usado con tipos de datos diferentes, esta
10
unidad genérica es un procedimiento modelo (patrón) que puede ser parametrizado con
tipos reales durante la compilación de programas. En general, la abstracción de datos en
ADA se realiza usando tres herramientas principales. El package es usado para encapsular
un conjunto de definiciones relacionadas. El type determina el dominio de una variable (o
estructura de datos) y como ésta puede ser manipulada. La definición de generic permite
generar varias abstracciones similares desde un patrón. (ANTARESX 2004)
El estado alcanzado hasta aquí en el proceso evolutivo de los tipos de datos en los
lenguajes de programación, el cual se pretende sintetizar, presenta algunas limitaciones.
En SIMULA falta el mecanismo de información oculta. En ADA los packages son objetos de
segunda clase. La sobrecarga de operadores en ADA se resuelve en tiempo de
compilación. En ADA no aparece el concepto de clase.
Los desarrollos posteriores llevan al concepto actual de Programación Orientada a Objetos
(POO). Sobre el cual hay diversidad de opiniones y está lejos de estar formalizado, pero
realmente ha despertado un entusiasmo considerable a partir de la década del 80 y se ha
convertido en una palabra de uso frecuente. En este tipo de programación, los programas
están basados en objetos (entidades que combinan las propiedades de los datos y de los
procedimientos que actúan sobre ellos), los cuales son instancias de un tipo o clase de
objeto (descripción intencional del dato). Por eso, un objeto puede verse y usarse en una
forma completamente análoga a un TAD en los lenguajes de programación tradicionales.
Realmente tanto los TAD como la POO emergieron del lenguaje SIMULA. (Zalamanca
2004)
Si los TAD son similares a los objetos, se puede considerar a la POO simplemente como un
modelo de programación en el cual todos los datos son abstractos y toda la manipulación
de la información se implementa a través de las operaciones con los TAD, pero esto no es
posible, ante todo porque los objetos tienen un tipo (dado en la mayoría de los casos por su
clase) lo cual permite que sean valores de primera clase (pueden ser manipulados como
una estructura de datos dentro del lenguaje) y ser usados directamente en expresiones.
Además a la POO la caracterizan otros conceptos como herencia, polimorfismo y enlace
dinámico o tardío (late binding). (Zalamanca 2004)
En resumen, los diferentes paradigmas de programación, los lenguajes, métodos y
herramientas asociados a ellas son un reto para el Proceso Docente Educativo de las
11
disciplinas de programación de las carreras de perfil informático, esto ha influido en la
forma en que se plantean los planes de estudio de estas carreras.
1.4 Evolución del currículo de las carreras de ciencia de la computación.
Los esfuerzos para diseñar el modelo curricular de los programas de Ciencia de la
Computación e Ingeniero en Computación comenzaron en 1960, poco tiempo después se
estableció el primer departamento que involucraba estas áreas. En 1968 la Association for
Computing Machinery (ACM) publica el Curriculum´68, el cual ofrece detalladas
recomendaciones sobre los programas académicos de Ciencias de la Computación.
(ACM/IEEE 2001)
En la próxima década, las carreras de computación se desarrollan rápidamente, en la
década del 70, la ACM y la Sociedad de Computación del Instituto de Eléctrica e Ingeniería
Electrónica (IEEE-CS) se unen para revisar el currículo de estas carreras. En 1977 el
Comité de Educación de la IEEE-CS publicó un reporte para los programas de Ciencia de
la Computación e Ingeniería de Software. (ACM/IEEE 2001)
Al final de la década de los 80, la Sociedad de Computación y la ACM desarrollan la
revisión de un currículo más ambicioso, el cual fue publicado en 1991, como Currículum de
Computación ´91 (CC1991), la cual divide el cuerpo del conocimiento asociado con la
ciencia de la computación en unidades de conocimiento individuales, lo que conocemos
como disciplinas, dándole flexibilidad a las instituciones de enseñanza para estructurar
estas unidades de conocimiento en cursos, en dependencia de sus necesidades
particulares. El CC1991 incluye 11 ejemplos de implementación que muestran cómo las
unidades de conocimiento
pueden combinarse para formar cursos y programas que
satisfagan una gran variedad de necesidades. (ACM/IEEE 2001)
En 1993, la ACM produjo cinco reportes para dos años de los programas de las carreras de
computación, uno para Ciencia de la Computación, Ingeniero en Computación, Sistemas de
Información, servicios que apoyan la computación y la computación para otras carreras.
(ACM/IEEE 2001)
12
Al entrar en el Nuevo Milenio, la ciencia de la computación es un campo enormemente
dinámico, la rápida evolución de la computación tiene un profundo efecto en la educación
de las ciencias de la computación, afectando, tanto el sistema de contenidos como la
pedagogía de la ciencia en sí. Se han incluido otras unidades del conocimiento
relacionadas con las redes, al mismo tiempo, la existencia de la web ha cambiado la
naturaleza de los procesos de educación en sí mismos. La moderna tecnología de redes
provee ambientes idóneos para la comunicación y un acceso sin precedentes a la
información. En la mayoría de los programas académicos actualmente, no solo en las
carreras de computación, sino en otros campos también, la tecnología de redes de
computadoras se ha convertido en un instrumento pedagógico esencial. Estos cambios se
dividen en dos categorías, técnica y cultural, cada una de ellas tiene un efecto significativo
sobre el proceso de enseñanza-aprendizaje de las carreras de computación.
En el año 2001, la ACM y el IEEE, publican el reporte CC2001, donde proponen el currículo
de las principales carreras de computación, incluyendo, Ingeniería en Computación,
Ciencias de la Computación, Sistema de Información e Ingeniería de software. Los cambios
en la rama de la computación son tan rápidos que no permiten diseñar currículos para una
década, como hasta este momento se diseñaban. (ACM/IEEE 2001)
Los avances técnicos que han influido en la inclusión de nuevos tópicos en el currículo de
estas carreras son:

La World Wide Web y sus aplicaciones.

Tecnología de redes, particularmente aquellas basadas sobre TCP/IP

Gráficos y multimedia

Bases de Datos Relacionales

Interoperabilidad

Programación Orientada a Objeto

El uso de sofisticadas Interfaces de Programación de Aplicaciones (APIs)
(Application Programmer Interfaces)

Interacción Hombre-Computadora

Seguridad y Criptografía

Dominios de Aplicación
1.4.1 La carrera de Ingeniero en software
En 1998 la ACM y el IEEE-CS crean el Proyecto de Educación del Ingeniero en Software Software Engineering Education Project (SWEEP) – para rediseñar el currículo del
13
Ingeniero en Software, el cual queda plasmado en el reporte SE2004, participan muchos
países e instituciones interesadas en la calidad del graduado de este perfil, este reporte
centró su atención en los conocimientos y la pedagogía para impartirlos asociada al perfil
del ingeniero en software y de este trabajo se derivó la incorporación de nuevas disciplinas.
(ACM/IEEE 2005)
Los graduados de esta carrera influyen en muchas áreas de la computación por su base
teórico conceptual, pero también se requiere que los estudiantes utilicen conceptos de
otros campos, como las matemáticas, las ingenierías, la administración de proyectos y de
otros muchos dominios de aplicación. Los estudiantes deben aprender a integrar teoría y
práctica, reconocer la importancia de la abstracción y el modelado para adquirir un dominio
eficiente del conocimiento que se requiere para apoyar el desarrollo de software en
múltiples campos y para apreciar el valor de un buen diseño.
Este por ende no encaja aquí, no tiene que ver con lo que se viene diciendo Por ende, la
Informática Educativa no es una disciplina puramente técnica; sicólogos, educadores y
sociólogos discuten con relación a su valor pedagógico real. Hoy en día los avances en la
sicología, combinados con la explosión tecnológica, han dado lugar a una serie de sistemas
educativos que permiten resolver algunas limitaciones de la educación tradicional (Cabrera
2000; Lynch 2003; Señas and Moroni 2003).
Este capítulo debería ser mas extenso, al menos 5 hojas mas. El último acápite de cada
capítulo debe ser un resumen del capítulo que le de pie al siguiente
14