DISEÑO Y PARADIGMAS DE LOS LENGUAJES DE PROGRAMACIÓN
Precedentes (I)
• El
diseño de lenguajes es un problema complejo
• En
los lenguajes de programación hay muchos errores de diseño
• Se
han considerado ideas erróneas
– FORTRAN
• uso
del GOTO
• declaración
implícita de variables
– COBOL
• Sentencias
demasiado largas
• Farragoso
de escribir y leer
• Uso
del GOTO
– APL
• si
puede significar algo, lo significa
– LISP
• una
sintaxis simple es más fácil de aprender
• Los
paréntesis dificultan escribir programas
• La
lectura es compleja por una sintaxis demasiado homogénea
Precedentes (II)
– C
• el
programador sabe lo que hace
– Obtener
direcciones de variables locales
– Printf no
comprueba el tipo y número de los argumentos
– C++
• se
puede extender C al paradigma orientado a objeto (demasiados compromisos de
compatibilidad)
• Uso
intensivo de apuntadores a objetos
• Lenguaje
demasiado complicado
– Un
lenguaje se puede utilizar para todo tipo de desarrollo de software
• Aun
con muchos errores de diseño es importante estudiar los lenguajes de
programación existentes ya que aportan muchas ideas
Consideraciones Preliminares
• ¿Cual
es el propósito del lenguaje?
– No hay
un lenguaje bueno para todo
– Aplicación
específica
• Bases
de datos, sistemas expertos, cálculo numérico, programación simbólica, diseño
algorítmico, etc.
• ¿Es
necesario diseñar un nuevo lenguaje?
– Ya
existe un lenguaje apropiado
• El
nuevo lenguaje se diferencia de los existentes
– Se
consume demasiado tiempo en el diseño e implementación de un nuevo lenguaje
• Es
demasiado fácil diseñar un lenguaje incompleto
• Lenguaje
demasiado especializado
• Sacrificar
características del lenguaje por un compilador simple.
– Otras
opciones
• Un
modulo o librería de funciones
• Ampliar
un lenguaje de programación
Fuentes de Ideas
• Lenguaje
natural (COBOL)
– Fácil
de leer y escribir
– Ambiguo
– Solo
se puede implementar un subconjunto
• Lenguajes
matemáticos (APL)
– No
ambiguos
– Crípticos
– La
programación no es matemáticas
• Lenguajes
de programación
– Errores
de diseño (pasado)
• Hay
que valorar cada característica de un lenguaje existente antes de incluirla en
el nuevo lenguaje
• Pruebas
y experimentos
– Programar
con el lenguaje antes de haber acabado su diseño
• Sirve
para detectar los problemas del diseño y tomar decisiones difíciles.
Objetivos y Filosofías de Diseño
• Comunicación
humana
• Prevención
y detección de errores
• Usabilidad
• Efectividad
• Compilabilidad
• Eficiencia
• Independencia
de la máquina
• Simplicidad
• Uniformidad
• Ortogonalidad
• Generalización
y especialización
• Otras
filosofías de diseño
Comunicación humana (I)
• Se
busca una comunicación eficiente entre el programador y el ordenador
• Un
buen nivel de comunicación se da cuando los programas son leíbles
– No ha
de ser necesaria una documentación externa al programa (minimizar)
– Es más
importante que un programa sea leíble que escribible
• Un
programa se escribe una vez, pero se lee muchas durante su depuración,
documentación y mantenimiento.
• Tendencia
actual a separar la interfaz de la implementación de un módulo
– La
sintaxis ha de reflejar la semántica
• Reducir
las manipulaciones implícitas
– Coerciones
(coerciones de PL/I o C)
– ON de BASIC
para eventos o excepciones
– Constructores
y destructores de C++ (necesarios, pero complican el seguimiento del flujo de
ejecución)
Comunicación humana (II)
– El
lenguaje ha de representar los patrones de pensamiento humanos
• No hay
que crear una sintaxis pensada exclusivamente para
– un modelo de
cómputo teórico (l-calculus)
– un conjunto
de instrucciones de la máquina
– facilitar la
compilación (forth)
– El
programador no es un ordenador
• Que el
compilador entienda una estructura es posible que el programador no
– Evitar
incluso la posibilidad de escribirlas
– Reducir el
conocimiento contextual
– El
programador no funciona con una pila como el programa compilado.
Prevención y detección de errores
• El
programador comete errores
– Hay
que prevenir los errores
• El
programador es su fuente
– El
programador no sabe lo que hace y el compilador ha de limitar sus acciones
(EUCLID, PASCAL)
– Hacer
imposible cierto tipo de errores
• Ejecutar
datos -> control de flujo limitado
• Errores
en el uso de datos -> Tipado fuerte
• Apuntadores
erróneos -> Gestión de memoria implícita (LISP, PROLOG, ML, etc).
– Hay
que facilitar su detección, identificación y corrección
• Redundancia
– Tener que
declarar antes de utilizar.
– Evitar
coerciones inductoras de errores
• float
a int por su perdida de precisión
• Comprobaciones
en tiempo de ejecución
– Indice de
array fuera de limites
–
Control sobre los apuntadores a NULL
Lenguaje Utilizable y Efectivo
• Un
lenguaje ha de ser fácil de utilizar
– Un
lenguaje ha de ser fácil de aprender y recordar
• Evitar
la necesidad de consultar el manual (C++ no cumple)
• Lenguaje
simple (C++ no cumple)
• Aprendizaje
incremental (PROLOG no cumple, LISP si cumple)
– El
comportamiento del lenguaje ha de ser predecible
• el uso
de void* de C++ es incomprensible
• Efectividad
– Los
detalles de implementación no han de oscurecer las intenciones del programador
• Soportar
abstracción
• Modularidad:
Separar especificación de implementación
– Los
Efectos de un cambio han de quedar localizados
– Evitar
los trucos (programas ilegible)
Otras filosofías de diseño
• Compilabilidad
– Se ha
de poder compilar programa en un tiempo
reducido
– Se ha
de poder depurar o aplicar otras herramientas de análisis
• Eficiencia:
La ejecución ha de ser rápida
• Independencia
de la máquina
• Simplicidad
• Uniformidad:
lenguaje predecible
• Ortogonalidad
– Todas
las características del lenguaje se han de poder combinar
• Generalización
y especialización
– La
generalización dice que algo similar también es correcto, pero es difícil de
implementar
– Hay
que especializar para facilitar la implementación sin perder la utilidad del
lenguaje
Diseño Detallado
• Microestructura
• Estructura
de las expresiones
• Estructuras
de datos
• Estructuras
de control
• Estructura
de compilación
• Estructura
de la entrada/salida
Reducción del Tamaño
Pragmatismo
Ejemplos:
Lenguajes de Programación y su Diseño
• El
lenguaje C
– Aplicación:
programación de sistemas
– Programador:
experto
– Sacar
el mayor rendimiento posible del ordenador
• PASCAL
– Aplicación:
docencia
– Programador:
inexperto
• LISP
– Aplicación:
procesamiento simbólico
– Desarrollo
rápido
• PROLOG
– Aplicación:
procesamiento simbólico
– Programación
lógica
– Desarrollo
rápido
El Lenguaje C (I)
• Lenguaje
pensado para el desarrollo de sistemas operativos (unix)
– Rendimiento/velocidad
de ejecución
– Programador
experto
– Código
compacto
• Redimiento/Velocidad
de ejecución
– Operaciones
básicas simples
– Apuntadores
• uso
para los strings y arrays
• Estructuras
de datos referenciadas por apuntadores (paso por referencia explícito)
– Gestión
de memoria explícita
– En las
primeras versiones las funciones solo retornan datos que puedan ir en un
registro del procesador
– Optimización
explícita
• Incremento
y decremento
• Operaciones
con asignación incluida
• variables
register
El Lenguaje C (II)
– En
contra de la velocidad
• Cálculos
en coma flotante con la máxima precisión posible
• Programador
experto
– Amplio
uso de coerciones
•
Implícitas
–
char ->
int -> double
– double <-
int <.- char
– void* ->
tipo*, tipo* -> void*
• Explícitas
– El
programador puede convertir cualquier tipo de datos en cualquier otro.
• int
-> void*
– Flujo
de ejecución
•
break
y continue
•
goto
local
•
long
jump
– Obtención
de direcciones
• Se
puede obtener la dirección de cualquier variable aunque esta sea local
El Lenguaje C (III)
– Prioridades
de operadores complejas
• Casi
cualquier combinación de operadores es aceptada por el compilador
• Otras
cuestiones
– Falta
de un método por defecto para la gestión de excepciones
• Códigos
de error retornados por las funciones de la librería que continuamente ha de
verificar el programa
– Faltan
comentarios de una línea
– Palabras
clave con diferentes significados según el contexto
• static
– Semántica
ambigua
• Incrementos
en una expresión
– Métodos
para la escritura de programas transportables soportados por el programador
• Compilación
condicional
• sizeof
El Lenguaje C (IV)
– Sintaxis
de los comentarios confundible (A=b/*p)
• Código
compacto
– La
mayor parte de las instrucciones se traducen a unas pocas instrucciones de
código máquina
– Faltan
instrucciones de alto nivel
• Strings
– Tratamiento
por apuntadores
– Gestión
explicita de la memoria
– Considerar
continuamente si la reserva de memoria es suficiente
• No hay
copia de datos compuestos
– Asignación
array a array
PASCAL
• Docencia
– Estructura
muy rígida de los programas
– Un
buen nivel de abstracción
– Transportable
– Lenguaje
simplificado
• Falta
de módulos y librerías
• Librería
básica muy limitada
– Escritura
farragosa de los programas
– Minimización
del uso de coerciones
• Todo
lo que hace el programa se indica explícitamente
– Pensado
para la resolución de problemas por subdivisión
• Definiciones
anidables de funciones y procedimientos
– Tipado
fuerte
LISP
• Sintaxis
demasiado simple
– Difícil
escritura y lectura de los programas
• Comprobaciones
semánticas en tiempo de ejecución
– Variables
declaradas
– Tipos
de datos
• Enfoque
pragmático
– Programación
imperativa y funcional
• Orientado
a optimizar el desarrollo frente a la velocidad de ejecución
– Gestión
de memoria implícita
– Uso de
listas para todo
– Amplia
librería de funciones
• Diseño
por etapas
– Funciones
repetidas
• setq y
setf
– Parches
para mantener compatibilidad
• forma
de creación de los places
PROLOG
• Programación
declarativa y lógica
• Implementación
del cálculo de predicados
– Faltan
funciones (l-prolog)
• Difícil
modularidad
– Un
método de programación demasiado alejado de la programación habitual
– Gramática
de operadores extensible
– Totalmente
transportable
– Modulariza
las búsquedas
• Convierte
los bucles de una búsqueda en una secuencia lineal de aplicación de predicados
C++
• Orientación
a objeto de C
– Mantener
la compatibilidad con C
• Uso
masivo de apuntadores
• Tratamiento
de excepciones no soportado por las librerías estándar
– Rendimiento
• Complica
el lenguaje
– Static en
métodos
– Métodos
virtuales y no virtuales
– Templates
• Destructores
por gestión de memoria explícita
• Apuntadores
y referencias
• Otros
– comentarios
de una línea fáciles de escribir y leer (repetición de //)
– Implementación
parcial de las coerciones
ADA
• Lenguaje
pensado para grandes proyectos de software
– Facilitar
el uso de librerías
• Interfaz
separa de la implementación del módulo
• Control
exhaustivo sobre la interfaz
– Fácil
lectura y detección de posibles bugs
• Sintaxis
de las instrucciones de control de flujo con marcadores claros de inicio y fin
(If then else end if)
•
Etiquetas
visibles <<etiqueta>>
• Coerciones
explicitas
– Reducción
de los errores
• Definición
de excepciones para controlar errores de ejecución
– Acceso a
array fuera de rango
– Un case del
que no se selecciona ninguna opción
• Atributos
asociados a las variables:
– un array
tiene asociado el atributo de su tamaño
Opciones en el Diseño (I)
• Sintaxis
de control de flujo
– Instrucción
compuesta
• C,
PASCAL (for (;;) ; {...}
– Instrucciones
de control de flujo con claros marcadores de inicio y fin
• ADA
– Instrucción
vacía
• Explicita
ADA (null)
• Implícita
C, PASCAL (; o nada)
• Lenguaje
orientado a
– Instrucción:
ADA, PASCAL
– Expresión:
C, funcionales
• Marcadores
de las estructuras sintácticas
– Si:
PASCAL, ADA
– No: C,
C++
• Expresiones
– Riqueza
de operadores C, C++
– Pobreza
de operadores PASCAL, ADA
Opciones en el Diseño (II)
• Sistema
de tipos
– No
tipado: LISP, BASIC
– Tipado:
C, PASCAL, ADA, etc.
• Código
genérico
– Datos
marcados con su tipo en ejecución
– Tipos
paramétricos
– templates
• Gestión
de memoria
– Explicita:
C, PASCAL, ADA
• Velocidad
– Implícita:
LISP, PROLOG, Java, funcionales
• Simplicidad
• Gestión
de errores de ejecución
– Responsabilidad
del programador: C, C++
– Responsabilidad
del lenguaje ADA
– Excepciones
sin declarar C++
– Excepciones
declaradas Java
Opciones en el Diseño (III)
• Estructura
declaraciones
– Rígida: PASCAL, ADA
– Poco
rígida: C
– Libre:
C++
• Ámbitos
– Expresión
LISP
– Instrucción
compuesta C, C++, Java
– Función
C, C++, PASCAL, ADA
– Espacios
de nombres
– Clases
– Paquetes
– Módulos
• Coerciones
– Explicitas:
ADA
– Pocas
implícitas: PASCAL
– Muchas
implícitas: C, C++
CARACTERÍSTICAS
GENERALES DE LOS LENGUAJES DE PROGRAMACIÓN. Valores. Almacenamiento. Ligaduras.
Abstracción.
SISTEMAS
DE TIPOS Y LENGUAJES IMPERATIVOS. Monomorfismo. Polimorfismo. Tipos
Paramétricos. Inferencia de Tipos. Coerciones. Subtipos. Flujos de control.
Excepciones.
ENCAPSULACIÓN
Y PARADIGMAS DE OBJETOS. PROGRAMACIÓN FUNCIONAL Y PROGRAMACIÓN LÓGICA. Tipos
abstractos. Objetos. Clases. Herencia. Funciones. Pattern matching. Valores y
tipos. Funcionales. Programación lógica. Cláusulas, relaciones y términos.
Concepto de mundo cerrad
CONCURRENCIA.
ENTRADA, SALIDA Y FICHEROS. Paradigmas concurrentes de alto nivel (Rendezvous).
Entrada / salida incluida en las primitivas del lenguaje o en bibliotecas de
funciones. Tipos de datos y la entrada / salida. Conceptos de entrada / salida
en un lenguaje. Ejemplos: Pascal, C, C++.
OBJETIVOS
Y FILOSOFÍAS DE DISEÑO. Consideraciones preliminares. Fuente de ideas.
Comunicación humana. Prevención y detección de errores. Utilizabilidad. Programación
efectiva. Compilabilidad. Eficiencia. Independencia del hardware. Simplicidad.
Uniformidad. Ortogonalidad.
CONSIDERACIONES
PRACTICAS. Generalización y especialización. Reducción de tamaño. Pragmatismo.
Metodología.
CARACTERÍSTICAS
GENERALES DE LOS LENGUAJES DE PROGRAMACIÓN. Valores. Almacenamiento. Ligaduras.
Abstracción.
SISTEMAS
DE TIPOS Y LENGUAJES IMPERATIVOS. Monomorfismo. Polimorfismo. Tipos
Paramétricos. Inferencia de Tipos. Coerciones. Subtipos. Flujos de control.
Excepciones.
ENCAPSULACIÓN
Y PARADIGMAS DE OBJETOS. PROGRAMACIÓN FUNCIONAL Y PROGRAMACIÓN LÓGICA. Tipos
abstractos. Objetos. Clases. Herencia. Funciones. Pattern matching. Valores y
tipos. Funcionales. Programación lógica. Cláusulas, relaciones y términos.
Concepto de mundo cerrado.
CONCURRENCIA.
ENTRADA, SALIDA Y FICHEROS. Paradigmas concurrentes de alto nivel (Rendezvous).
Entrada / salida incluida en las primitivas del lenguaje o en bibliotecas de
funciones. Tipos de datos y la entrada / salida. Conceptos de entrada / salida
en un lenguaje. Ejemplos: Pascal, C, C++.
CARACTERÍSTICAS
GENERALES DE LOS LENGUAJES DE PROGRAMACIÓN. Valores. Almacenamiento. Ligaduras.
Abstracción.
Diseño detallado
Descripción
En esta
etapa se adecúa el análisis a las características específicas del ambiente de
implementación y se completan las
distintas aplicaciones del sistema con los modelos de control, interfaz o
comunicaciones, según sea el caso.
Actividades
técnicas
1.
Agregar detalles de implementación al modelo del mundo
2.
Desarrollar el modelo de interfaz
3.
Desarrollar los modelos de control, persistencia y comunicaciones
Documentos
Entregables
Diagramas
de clases y paquetes, con el detalle de la implementación
Diagramas
de interacción con el detalle de las operaciones más importantes del sistema
Diagramas
de estados y/o actividades para las clases concurrentes o complejas
Actividades Técnicas
- Detalles de implementación del modelo del
mundo
Completar el detalle
de las clases:
Tipos de
los atributos
Atributos y metodos de clase
Diseño de asociaciones
Completar los métodos
Enriquecer
el modelo con el framework de base en el ambiente de implementación escogido
Incorporar
patrones de diseño
Subdividir
en paquetes
Definir
excepciones
Completar
comportamiento de las clases: Constructores, destructores, modificadores,
consultores
Adecuar el
modelo a las características del lenguaje de programación
Evaluar
eficiencia
Validar el
sistema
- Desarrollar el modelo de interfaz
Conocer el
framework de base
Enlazar
las clases de interfaz con las clases del modelo del mundo
- Desarrollar los modelos de control,
persistencia y comunicaciones
Conocer los
frameworks de base
Enlazar las
clases del framework con las demás clases del sistema
Documentos
Entregables
Diagramas
de clases y paquetes, con el detalle de la implementación
Diagramas
de interacción con el detalle de las operaciones más importantes del
sistema
Diagramas
de estados y/o actividades para las clases concurrentes o complejas