lunes, 22 de marzo de 2010

Patrones de Asignación Certificados (Certified Attachment Pattern)

En el artículo anterior sobre  Eiffel: void-safety dimos los conceptos básicos que implementa el lenguaje Eiffel para conseguir sistemas que no produzcan el famoso error de referencia nula. O sea cuando se hace una llamada a una entidad que apunta a Void.
La estrategia de Eiffel se basa en tres mecanismos: Patrones de Asignación Certificados, Tipos Asignados y Object Test.
En el articulo de hoy vamos a explicar el primer mecanismo, el de Patrones de Asignación Certificados o CAP. La idea es que en ciertos patrones de código se sabe certeramente que una referencia no puede ser Void. Un CAP es simplemente uno de estos patrones identificado. Por ejemplo el siguiente patrón simplemente verifica que x no sea Void:



if x /= Void then
    -- Hacer cualquier cosa menos asignar algo a x
    x.f (a)
end



Si garantizamos que x no se le asigna nada entonces es segura la invocación x.f(a) dado que x no es Void. Este código es un CAP para x.  Para que esto valga (lo mismo con otros CAPs) x debe ser una variable local o un argumento, no puede ser un atributo de la clase. Es lógico esta prohibición dado que un atributo podría ser asignado a Void al invocar una rutina. Lo que decimos es:


Una llamada x.f(...) donde x es un argumento formal o una variable local de una rutina es void-safe (segura para void) si la llamada verifica que:

  • Aparece en el alcance de un testeo de void involucandro a x
  • No es precedida, en dicho alcance, por una asignación para x.


En siguientes artículos continuaremos analizado esta interesante propiedad implementada en el lenguaje Eiffel que nos permite tener sistemas orientados a objetos seguros para void.

martes, 16 de marzo de 2010

Eiffel: Void-safety. No más errores de null reference!!

Al momento de escribir el libro todavía no estaba implementado completamente el mecanismo que lograba void-safety en Eiffel. El problema que se evita es conocido como excepción por null reference o void call (según el lenguaje y entorno).
El problema se presentaba cuando se realiza una llamada de la forma: x.f(a)si  x era una referencia a Void (null reference). La tipificación estática no es suficiente, ya que ésta asegura (en el ejemplo anterior) que existe una feature f aplicable a x. Lo que garantizaría la void-safety es que en el momento de la ejecución haya un objeto asignado a x. En .Net este error es comúnmente encontrado mediante una excepción con el mensaje: "Object reference not set to an instance of an object". El mecanismo que logra evitar este problema esta completamente implementado a partir de EiffelStudio 6.4. 
Recordaran que en Eiffel existen dos clases de tipos: expandidos y de referencia. Con los primeros no hay problema por su propia semántica, siempre hay un objeto. El problema podría presentarse solamente con los tipos no expandidos. 
En resumen, lo que estamos diciendo, es que una entidad puede ser asiganda (attached) o  no asignada (detached) en este último caso es Void (null en otros lenguajes). Una llamada a una entidad no asignada provoca un error en tiempo de ejecución. Eiffel implementa un mecanismo para resolver este problema.
La asignación es vista (hasta ahora) cómo una propiedad en tiempo de ejecución, es decir una entidad en algún momento de la ejecución del programa puede estar asignada o no asignada. Para lograr la void-safety ampliamos este concepto de asignación para considerar también la asignación estática. Este último tipo de asignación puede ser evaluado en tiempo de compilación. El mecanismo implementado asegura que se cumpla una importante propiedad: la consistencia de asignación.


Consistencia de Asignación: si una entidad x es estáticamente asignada sus valores posibles en tiempo de ejecución son dinámicamente asignados.


Para garantizar entonces que no haya llamadas a void (void call) se incorpora al lenguaje la siguiente regla:


Regla de void-safety: Una llamada de la forma x.f(a) es permitida solamente si x es estáticamente asignada.


Al garantizar que x es estáticamente asignada, por la regla de la consistencia de la asignación x no puede asumir valores void en ninguna llamada.


Para garantizar la void-safety Eiffel utiliza una estrategia basada en tres mecanismos:

  • Patrones de asignación certificados (Certified Attachment Patterns o CAPs), que básicamente representan esquemas de código que el compilador puede garantizar ser seguros.
  • Tipos asignados. Son tipos que no pueden tener valores nulos (void). 
  • Instrucción "Object Test". Esta instrucción permite a los programadores tratar de forma especial los valores nulos

En los siguientes artículos iremos describiendo cada uno de estos mecanismos en detalle.

sábado, 6 de marzo de 2010

Tabla de Contenidos

Este blog está dedicado al libro Algoritmos, Objetos y Estructura de Datos. Una introducción a la Programación con Contratos (Gerardo Rossel - Andrea V. Manna 2009). Trataremos temas relacionados al libro, ejercicios, erratas, etc.
Para los que aún no tienen el libro a continuación la tabla de contenido:


1. Conceptos Introductorios
1.1. Un enfoque orientado a objetos
1.2. ¿Qué es un algoritmo?
1.3. Compilación de Programas
1.4. Códigos ASCII y UNICODE
1.5. Máquinas Virtuales
1.6. Algoritmos y sentencias
1.6.1. Decisión
1.6.1.1. Estructuras de decisión anidadas
1.6.1.2. Estructuras de selección y lenguajes
1.6.1.3. Estructura de decisión generalizada o múltiple
1.6.2. Repetición o Iteración
1.6.2.1. Estructura repetir-hastaque
1.6.2.2. Estructura mientras-hacer-finmientras
1.6.2.3. Estructura para-hacer-finpara
1.6.2.4. Estructuras de repetición y lenguajes
1.7. Ejercicios
2. Primeros pasos con Objetos
2.1. ¿Qué son los objetos?
2.2. Sentencias.
2.3. Nuestro primer programa: Hola Mundo
2.4. Trabajando con EiffelStudio
2.5. Creación de objetos
2.6. Relación entre variables y objetos
2.7. El objeto Current
2.8. Código C#
3. Tipos de Abstractos de Datos
3.1. El método axiomático
3.2. El TAD CUENTA_BANCARIA
3.3. El método de las poscondiciones.
3.4. Ejercicios
4. Clases y Objetos
4.1. TAD y Clases
4.1.1. Traslación de las operaciones de TAD
4.2. Rutinas y Atributos
4.3. El concepto de propiedad
4.4. Pasaje de argumentos
4.4.1. Pasaje de Argumentos por Valor
4.4.2. Pasaje de Argumentos por Referencia
4.4.3. Pasaje por Copia/Restauración
4.4.4. Pasaje de Argumentos por Valor Constante
4.4.5. Pasaje de Argumentos por Nombre
4.4.6. Pasaje de Argumentos en Eiffel
4.4.7. Pasaje de Argumentos en C#
4.5. Clusters y espacios de Nombres
4.6. Accesibilidad
5. Contratos
5.1. Precondiciones
5.2. Poscondiciones
5.3. Invariante de Clase
5.4. Que no son las aserciones
5.5. Corrección de ciclos
5.6. La instrucción check
5.7. Monitoreo de aserciones
5.8. Vista de contrato
5.9. Ejercicios
6. Estructuras de Datos (primera parte)
6.1. Clases Genéricas
6.1.1. Clases genéricas en C#
6.2. Arreglos
6.2.1. Creación de un arreglo
6.2.2. Acceso y notación bracket
6.2.3. Arreglos en C#
6.3. Pilas y Colas
6.4. Listas
6.4.1. Movimiento del Cursor
6.4.2. Modificación de la lista
6.5. Implementaciones de Listas
6.5.1. Listas encadenadas
6.5.2. Listas doblemente encadenadas
6.5.3. Operaciones sobre Listas
6.6. Tuplas
6.7. Iteradores
6.8. Estructuras en C#
6.9. Ejercicios
7. Complejidad Algorítmica
7.1. Análisis de Algoritmos
7.2. La notación “Big O”
7.3. Complejidad de un algoritmo
7.3.1. Comparando complejidades
8. Algoritmos: Recursividad
8.1. Características
8.2. ¿Iteración ó Recursión?
8.3. Contratos y recursividad
8.4. Ejercicios
9. Algoritmos: Ordenación y Búsqueda
9.1. Búsqueda
9.1.1. Búsqueda Secuencial o Lineal
9.1.2. Búsqueda Binaria
9.1.3. Algoritmos de Búsqueda en C#
9.2. Ordenación
9.2.1. Ordenación por selección directa
9.2.2. Ordenación por el método de Burbujeo
9.2.3. Ordenación rápida ó Quicksort
10. Introducción a la Herencia
10.1.¿Qué es Herencia?
10.2.Herencia un ejemplo
10.3.Polimorfismo
10.4.Conformidad de tipos
10.4.1. El tipo Current y los tipos anclados
10.4.2. Herencia no conformante
10.5.Invocando al antecesor
10.6.Herencia en C#
10.7.Testeo de objetos y asignación condicional
10.8.Ejercicios
11. Tipos, rutinas y objetos
11.1.Introducción
11.2.Agentes en Eiffel
11.2.1. Tipos de los agentes
11.2.2. Llamando a un agente
11.2.3. Agentes e iteradores
11.3.Delegados y Eventos en C#
11.3.1. Delegados
11.3.2. Eventos
11.4.Tipos de Referencia y Tipos expandidos
11.4.1. Tipos Básicos
11.5.Tipos de Valor en C#
11.5.1. Tipos simples
11.5.2. Tipos enumerados y estructuras
11.5.3. Tipos anulables
11.5.4. Boxing y Unboxing
11.6.Rutinas “Once” y Constantes
11.7.Miembros y Clases Estáticas en C#
11.8.Ejercicios
12. Arboles
12.1.¿Qué es un Árbol?
12.2.Árboles binarios
12.2.1. Árbol Binario en C#
12.3.Recorrer un árbol binario
12.3.1. Recorrido en pre-orden
12.3.2. Recorrido en-orden
12.3.3. Recorrido post-orden
12.3.4. Complejidad de los recorridos
12.4.Árboles binarios de búsqueda
12.4.1. Insertar un elemento
12.4.2. Borrar un elemento
12.5.Ejercicios
13. Herencia Parte II
13.1.Introducción
13.2.Redefinición: Covarianza
13.3.Renombrado y otras operaciones
13.3.1. Fusión de abstracciones
13.3.2. Choque de nombres
13.4.Herencia repetida
13.4.1. La clausula select.
13.4.2. Compartir o replicar
13.5.Congelar características y clases.
13.6.Contratos y herencia
13.6.1. Invariante en herencia
13.6.2. Pre y poscondiciones
13.7.Generalidad restringida
13.8.Interfaces en C#
13.9.Ejercicios
14. Grafos
14.1.Introducción
14.2.Definiciones
14.3.Implementación de Grafos
14.3.1. Representación con lista de adyacencia
14.3.2. Representación por matriz de adyacencia
14.3.3. Implementación con lista de ejes y vértices.
14.4.Algoritmos sobre grafos
14.4.1. Profundidad primero
14.4.2. Ancho Primero
14.4.3. Camino más corto: el algoritmo de Dijkstra
14.5.Ejercicios
15. Diseño Orientado a Objetos
15.1.Introducción
15.2.Elicitación de Clases
15.2.1. Casos de Uso
15.3.BON, UML: describiendo Clases.
15.3.1. Diagramas de Clase
15.3.2. Diagrama de Secuencias
15.3.3. Eso no es todo.
15.4.Un pequeño problema
15.5.Ejercicios