Apunte de Diseño (Ingeniería I)

De Cuba-Wiki

Plantilla:Back

La idea del diseño es en primer lugar generar los diagramas de secuencia para distintas funcionalidades y escenarios, generar el diagrama de clase a partir de lo obtenido y refinarlo aplicando distintas técnicas de diseño.

Diagramas de Secuencia

Cada diagrama de secuencia se corresponde uno a uno con un determinado escenario. Un escenario es una situación concreta, con objetos concretos, sobre una determinada funcionalidad del sistema.

Estructura

El diagrama de secuencias tiene instanciaciones de objetos, que pueden pertenecer o no a ciertas clases. Para notar que un objeto esta vivo, se traza una linea punteada debajo de el. Cuando un objeto inicia la ejecucion de un método, se nota con una barra sobre la línea punteada. Una vez termina la ejecución, se vuelve a la punteada.

El diagrama de secuencias busca representar una determinada funcionalidad, un metodo en particular, que es el que se ejecuta inicialmente. Todos los metodos tienen un objeto (una instancia particular de un objeto) que los llama, excepto el primero que da inicio al diagrama. Los metodos se notan con flechas que van de un objeto a otro, y los resultados con flechas punteadas que vuelven.

Los resultados pueden ser de cualquier tipo, o incluso omitirse si la respuesta no es importante y no afecta a la claridad del diagrama.

Puede suceder que un objeto invoque un metodo de un objeto que ya estaba ejecutando, en ese caso se agrega una nueva barra de ejecucion para indicar que es otro contexto. Lo mismo sucede cuando un objeto ejecuta un metodo de si mismo, se tira una flecha de la barra principal a otra nueva, y el retorno se hace de la misma forma.

Referencias a objetos

Es muy importante conocer un objeto antes de poder invocar su método. Hay tres maneras posibles de obtener una referencia a un objeto:

  • En el diagrama de clases existe una asociación directa entre ellos, que se crea en algún momento previo a la ejecución del método que está representando el diagrama.
  • El objeto llamador recibió una referencia a ese objeto como parámetro del método que inició el contexto de ejecución actual.
  • El llamador ejecutó un getter de otro objeto conocido que le devolvió la referencia al buscado; esto solo sirve si el objeto al que se le ejecutó el getter conoce al buscado.

Notar que en los dos últimos casos la referencia al objeto se guarda solamente por el contexto de ejecución, sea en parámetros o variables locales. Cuando se termina la ejecución estas referencias se pierden. Lo mismo si se inicia un nuevo contexto de ejecución, por más que sea dentro del que posee las referencias, el nuevo no las conoce.

Constructores y destructores

Para notar que un objeto construye a otro (y no que el objeto estaba vivo desde antes y el llamador simplemente lo activa, que es lo que representa la notacion anterior), se traza una flecha con el método new() desde el contexto de ejecución del creador directamente hacia la caja con el nombre del creado.

Si se quieren ejecutar métodos dentro del constructor de un objeto, en lugar de dibujar una linea punteada a continuacion de la caja (que contiene el nombre del objeto) recien creada, se dibuja una barra de ejecucion.

El destructor es un metodo delete(), que termina la vida de otro objeto con una cruz. Un objeto también puede destruirse a si mismo (salir de scope, por ejemplo), terminando su barra de ejecución con una cruz y sin prolongar la línea punteada.

Estructuras de control

Si bien el diagrama de secuencias está construido sobre un escenario, o sea, una instancia concreta del mundo, en ciertos casos para evitar la reescritura de gran parte de los diagramas y facilitar su comprension se utilizan estructuras de control.

Para los bucles se encierra la sección a repetir en un frame, agregando arriba a la izquierda la palabra reservada loop, e indicando la guarda de ejecución. El esquema típico para un bucle es:

  • Ejecutar método que obtiene la condición una primer vez
  • Ejecutar el cuerpo del bucle
  • Ejecutar nuevamente el método que obtiene la condición
  • Encerrar las dos ultimas dentro del bucle

Para los condicionales, se usa un frame dividido en dos con la palabra alt, y se coloca en la parte superior la rama true, y en la inferior la false.

Notar que teniendo muy pocas estructuras anidadas el diagrama se vuelve incomprensible, esto es porque los frames no estan pensados para ser usados intensivamente en secuencias; sino que se supone que los valores del mundo están fijos y se estructura el flujo de acuerdo a ello.

Diagramas de Clases

A partir de la construcción de muchos diagramas de secuencia se puede realizar el proceso de inferir un diagrama de clases, el cual representa el diseño en sí del sistema. Una vez generado el diagrama, se busca refinarlo mediante la aplicación de técnicas de diseño.

Estructura

El diagrama de clases tiene la misma estructura que el modelo conceptual, pero sin la notación molesta de <<Clase Conceptual>> sobre cada una de las clases. Las clases tiene atributos y métodos como antes.

Las asociaciones de las clases resultan de lo observado en los diagramas de secuencia para resolver el conocimiento entre objetos. Ahora las asociaciones pueden ser unidireccionales, es decir, un objeto conoce al otro pero no al revés.

Respecto de los métodos y atributos, se agregan los modificadores de visibilidad propios del diseño orientado a objetos:

  • Público +
  • Privado -
  • Protegido #
  • Estático (subrayado)
  • Abstracto (itálica)
  • Final (constante)

Dependencias

Una métrica importante a tener en cuenta en los diseños son las dependencias entre clases. Estas se notan con una flecha punteada y la palabra <<usa>>.

Se busca evitar dependencias circulares, el fan-in (un objeto del que dependen muchos otros) y el fan-out (un objeto que depende de muchos otros). La dependencia da idea de la cohesión y el acoplamiento del modelo.

También pueden notarse otros tipos de dependencia, usando la misma flecha punteada, pero con otra palabra reservada, como por ejemplo <<crea>>. Notar que en el diagrama se dibujan solamente las dependencias más significativas por temas de legibilidad.

Interfaces

Una interfaz busca representar comportamiento común a distintas clases. Puede poseer solamente métodos abstractos o atributos finales estáticos (constantes).

La implementación de interfaces busca evitar la utilización de herencia múltiple, poco soportada en los lenguajes actuales, y que posee otra semántica.

Para notar que una clase implementa una interfaz, se dibuja una flecha punteada hacia la interfaz con la keyword <<realizes>>.