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

  1. 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

 

  1. Desarrollar el modelo de interfaz

 

Conocer el framework de base

 Enlazar las clases de interfaz con las clases del modelo del mundo

 

 

  1. 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