Introducción a UML
Al comienzo del desarrollo de software, los programadores se involucraban en tareas de desarrollo como primera medida para crear un producto, pero a medida que los problemas se hacían más complejos, estos comenzaron a requerir una analítica previa que permitiese abordarlos desde una perspectiva más eficiente (y, tal vez, reutilizable).
Al analizar un sistema software futuro, nos interesa que todos los involucrados sean capaces de comprender los conceptos que lo componen, para ello es importante utilizar un lenguaje o notación global que permita describir los elementos del sistema. UML es el lenguaje de modelado que nos dará los elementos para llevar esto a cabo.
UML tiene su origen en la década de los ochenta, donde los «tres amigos» Grady Booch, James Rumbaugh e Ivar Jacobson diseñaron sus propias metodologías para el diseño y análisis orientado a objetos, cuando decidieron en los 90’s poner sus trabajos en común, sentaron las bases del UML que conocemos hoy.
UML se puede entender de muy diversas maneras, siendo la más correcta, tal vez, la que lo define como un estándar de notación para modelado de sistemas.
UML comprende una serie de símbolos con los cuales de definen varios tipos de diagramas, que posteriormente integrarán un sistema.
En la notación UML existen muchos tipos de diagramas que se tratarán en otros archivos de esta web, ahora vamos a tratar los diagramas de clases, los cuales nos permitirán comprender las relaciones.
Diagramas de clases
Los diagramas de clase nos dan una vista de los elementos estáticos de un sistema, las clases, que presentan en estos diagramas tres partes bien diferenciadas:
- Nombre
- Atributos
- Métodos, funciones o funcionalidades.
Las clases nos aportan gran cantidad de información y son los bloques que edifican un sistema software orientado a objetos, una de sus mayores capacidades es la de interactuar y comunicarse con otras clases, estos tipos de relación son relevantes a la hora de entender el funcionamiento del sistema, son las siguientes:
- Asociación: Es una relación entre clases que indica que objetos de esas clases están conectados de algún modo, se representa gráficamente con una linea sencilla. Si la relación presenta dirección, restringe la interacción entre las clases. La multiplicidad indica de qué modo se relacionan, un ejemplo sencillo es el de una persona que lee un libro, esta persona puede o no leer o leer tantos libros como quiera (0-n) y el libro puede no ser leído por nadie o ser leído de manera continua.
Hay dos posibilidades más que comentar a la hora de entender un diagrama de clases, el primero es la posible reflexividad, es decir, que un objeto de una clase realice una interacción sobre si misma, como peinarse, en dicho caso se expresa con una flechita que inicia y acaba en la misma clase.
Por otra parte, en ocasiones, cada interacción entre clases puede ser iterativa, es decir, suceder varias veces, por tanto se puede crear una clase intermedia (línea discontinua) que almacene información sobre esas interacciones, un ejemplo muy simple es la creación de un registro que almacene la fecha de cada vez que leo un libro.
- Generalización: Es una de las especializaciones de una asociación en la que interviene el concepto de «herencia». En una herencia de distinguen varios elementos : la clase raíz (o padre), carente de padre y las clases que no tienen descendientes, llamadas hojas (o hijos).
En este diagrama podemos ver como los diferentes tipos de aviones son hijos de la clase general «avión», esto evitará redundancia en la definición de los métodos, ya que como se aprecia, los hijos pueden heredar los métodos y atributos del padre.
Un tipo especial de herencia es la de clases abstractas, cuyos métodos no están definidos pero sí declarados y que no puede ser instanciada.
- Dependencia: La dependencia es la relación que se establece entre una clase normal y una derivada de la misma, el formulario de un sistema, las páginas de un libro… La dependencia dice que un cambio en la clase usada puede provocar un cambio en la clase dependiente, nunca al revés. Se representa con una línea discontinua, implica una necesidad.
- Interfaz: Es una especie de mezcla entre herencia y dependencia, de ahí que se represente con una flecha apuntando a la clase abstracta y las líneas discontinuas de la dependencia. Una clase interfaz genera dependencia en sus hijas.
- Composición débil o agregación: Es una asociación entre clases que indica composición, sin embargo la supresión de la clase principal no implica la supresión de la débil debido a que esta tiene más interacciones en el sistema. Se representa con una línea continua y un rombo sin relleno apuntando a la clase fuerte. Un ejemplo es una librería que tiene libros divididos en colecciones.
Aquí se puede apreciar una herencia simple o generalización de colecciones y libros hacia Producto, sin embargo, producto es una agregación de catálogo sin llegar a ser completamente dependiente de este.
- Composición: Es una asociación entre clases que implica una absoluta dependencia de la clase B hacia la clase A, la supresión de la principal implica la supresión de la dependiente.
De este modo, aunque las líneas de pedido tengan una relación más allá de la composición, esta desaparecerá si desaparece el pedido, siendo esta la gran diferencia entre una relación de composición y una de composición débil o agregación.