UML, Diagramas de Clases y de Flujo
En este artículo aprenderemos sobre diagramas UML (Unified Modeling Language), específicamente sobre diagramas de clases y de flujo. Veremos como mediante estos podemos representar modelos y relaciones entre clases, protocolos, propiedades y métodos.
Nota: El presente artículo es válido para cualquier desarrollador de software, sin importar el lenguaje o tecnología de su preferencia.
¿Qué es UML?
El Lenguaje Unificado de Modelado (UML) es una vía (lenguaje) de modelado visual, una combinación de varias notaciones orientadas a objetos: diseño orientado a objetos, técnica de modelado de objetos e ingeniería de software orientada a objetos.
La base de los lenguajes de programación modernos (orientados a objetos) es modelar los objetos del mundo real. UML es básicamente un reflejo de esto, y es lógico que lo sea, de lo contrario como representaríamos eficientemente toda la complejidad de una aplicación.
En palabras claras y simples UML es la vía mediante la cual representamos las peculiaridades de cierta aplicación, sus módulos, las relaciones entre clases o estructuras, las propiedades y métodos de estas, protocolos y etc.
UML no solo sirve para las ciencias informáticas, también se puede usar en todo ámbito donde tenga sentido, y se puedan extrapolar los objetos de la vida real al diagrama.
Dígase un objeto carro: sus gomas, timón, sus puertas (con sus variantes), el motor, la bomba de gasolina, los pistones, el conductor y resto de elementos. Todas estas relaciones se pueden modelar mediante un diagrama UML.
Diagramas de Clase
Los diagramas de clase dentro de UML son composiciones estáticas que describen la estructura de un sistema, mostrando las clases del mismo, sus atributos, operaciones (o métodos), y las relaciones entre los objetos.
Clase
Una clase la podemos representar de la siguiente manera:

Herencia
Para definir las relaciones de herencia entre una clase y otra lo hacemos mediante una flecha con la punta hueca, así:

La lógica tras el diagrama se evidencia aún más cuando lo describimos de manera correcta. Es decir que si tuviésemos que interpretar y describir este diagrama UML lo haríamos con las siguientes palabras: «Un Avión es una Aeronave«, siendo el segmento «es una» el correspondiente a la flecha de la herencia que siempre apunta a la clase base o padre.
Propiedad
Una propiedad (o asociación) la podemos representar mediante una flecha con la punta negra (o coloreada) y abierta, de esta manera:

Este diagrama lo describimos de esta manera: «La clase línea aerea tiene uno o más aviones. «, el segmento «tiene» viene a ser el asociado a la flecha que indica la asociación (o propiedad) de una clase sobre otra. Mediante el texto junto a la flecha «1 … *» especificamos que la clase Línea Aerea tiene 1 o más aviones.
Protocolo
Los protocolos también se pueden representar mediante cajas, siempre que se especifique explícitamente que lo es:

Tal y como vemos debemos especificar que es un protocolo con el texto «<<protocolo>>» seguido del nombre del protocolo, en el ejemplo anterior Seguridad.
Ahora, en conjunto con los protocolos también introducimos otro tipo de flecha nueva, de línea discontinua y de cabeza blanca, la cual especificamos cuando queremos declarar que una clase implementa cierto protocolo.
Veamos un ejemplo:

En este diagrama UML tenemos una clase Avión que implementa un protocolo Seguridad. Algo que se pudiera describir también como: «La clase Avión implementa el protocolo Seguridad.«, es decir que la clase Avión implementa las medidas de seguridad que estás descritas en el protocolo Seguridad.
Propiedades y Métodos
Tanto en las clases como en los protocolos podemos definir propiedades y métodos:

Aquí hemos definido que el protocolo Seguridad cuenta con una propiedad donde se establecerá el código del transpondedor, así como un método en el cual configuramos el ILS (Instrument Landing System).
Modificadores de Acceso a Miembros
Con propiedades y métodos también puede ser útil especificar los niveles de acceso (visibilidad) que estos poseen. Mostremos a continuación los niveles de acceso con sus símbolos correspondientes:
- (+) Public, se puede acceder al miembro de la clase o estructura desde cualquier lugar.
- (-) Private, se puede acceder al miembro de la clase o estructura desde la propia clase.
- (~) Internal, se puede acceder al miembro de la clase o estructura desde la propia clase o desde cualquier otra dentro del mismo módulo.
Estos modificadores se utilizan anteponiéndolos al nombre del elemento dentro del diagrama UML correspondiente a la clase o protocolo, de esta manera:

Dependencias
Las dependencias usualmente se confunden con Asociaciones (o Propiedades), y esto es debido principalmente a los matices que pueden adoptar las relaciones entre clases, en dependencia de la arquitectura o lo que sea que estemos implementando.
A favor de despejar lo confuso del tema nombremos los escenarios en los cuales podemos identificar una dependencia:
- Una propiedad o delegate declarada como weak.
- Un objeto que ha sido pasado a un método como parámetro y cuya referencia no se retiene como propiedad.
- Un callback, al estilo IBAction desde un View hacia el Controller.
Veamos un ejemplo de una dependencia representada en un diagrama:

En este diagrama introducimos una nueva flecha, me refiero a la flecha de dependencia, la que es acompañada con el texto «Delega a«, como podemos observar es también discontinua y con la cabeza negra y abierta.
Con respecto al texto pudiéramos decir que si el significado de una flecha es obvio podemos dejarla tal cual, sin un texto asociado. Por lo general en UML, omitimos esta ayuda en flechas que representan herencia, propiedades, implementación de protocolos, agregación o composición.
Mientras que si agregamos una descripción a flechas de dependencia, es básicamente porque su significado no siempre es obvio.
Incluso si no conociéramos el significado de la flecha delegación el diagrama es lo suficientemente legible. La clase Avión delega los protocolos de seguridad que vienen de fábrica al piloto, que es el que los gestionará:
- Establecerá un código de transpondedor cada vez que el ATC se lo indique
- Utilizará el sistema ILS para un aterrizaje más seguro siempre y cuando el aeropuerto cuente con esta tecnología (casi todos hoy día).
Agregación
Como agregación clasificamos toda asociación entre dos objetos donde un objeto B forma parte de un objeto A, siendo B un enlace de tipo weak. Es decir que la existencia de B no está delimitada por el ciclo de vida de A.
Una agregación se denota mediante una flecha constante, con cabeza de diamante y de color blanco:

En este ejemplo mostramos un Avión en relación de agregación con un Piloto. Si bien es cierto que un avión necesita de un piloto para volar, el piloto no es parte del avión
Esta dependencia no se debe confundir con la que vimos anteriormente ya que por ejemplo, un avión depende de un piloto para ejecutar la función de volar, pero no para ser lo que es, un avión. Básicamente porque un avión es un avión tanto en tierra como en el aire, y por ende no depende de un piloto para ser definido como tal.
Composición
Mediante una composición representamos que un objeto se une a otro del cual formará parte, como los dedos forman parte de la mano, o un cuarto forma parte de una casa.
Continuando con nuestros ejemplos de aviación veamos el siguiente diagrama:

Aquí tenemos un objeto Avión que tiene una relación de composición con el objeto Turbina. Es decir un Avión para poder desplazarse (tanto por tierra como por aire) necesita de una Turbina, depende de esta como parte de su naturaleza. La conjunción de todos los objetos que forman parte de un avión (alas, flaps, timón de cola, etc.) es lo que lo convierten en ese objeto más complejo llamado avión.
Esta composición se representa en UML mediante una flecha continua con cabeza de diamante coloreada, en este caso de color negro.
A nivel de programación podemos decir que el objeto A (Avión) está compuesto por el objeto B (Turbina), y una vez que la instancia de A deje de existir también lo hará el objeto B que forma parte de A, ya que B fuera de A no cumple función alguna.
Consideraciones
Siempre que modelamos un sistema en UML debemos enmarcarlo en un determinado contexto, y para ellos usualmente necesitamos acudir a cierta abstracción, de lo contrario mucho de lo que hemos hablado sonará ambiguo.
Para evitar perdernos dentro de la confusión debemos filtrar los puntos de vista y posibles soluciones, elegir siempre la más apropiada para el negocio que intentamos modelar, ejemplo:
Como hemos visto anteriormente la relación entre las clases Avión y Turbina son de composición, no tiene sentido que una vez que deje de existir el objeto Avión continue existiendo una instancia de la clase Turbina que forma parte de Avión.
¿Cierto?
Esto estaría bien para algunos casos, no para todos. Digamos que en otro escenario, quizás un software que gestione toda una línea aérea, las turbinas no solo se modelan en los aviones sino también como activos de esta línea aérea, donde cada turbina tiene un número de serie y se lleva un registro de las que están instaladas en los aviones y las que se encuentran en almacén como repuesto.
En este caso la relación entre la Turbina y el Avión sería de agregación ya que la Turbina si tiene sentido de ser fuera de un Avión, ya sea porque se bajó de este por mantenimiento o porque toca ser remplazada, al mismo tiempo que hay otras que no se encuentran acopladas a ningún avión y se encuentran en almacén.
A esto me refiero con que siempre hay que definir el contexto del negocio, y lógicamente basado en esto, establecer los ciclos de vida de cada objeto.
Diagramas de Flujo
Los diagramas de flujo (o flujograma) consisten en la representación gráfica de un algoritmo o proceso, dígase los protocolos a seguir dentro de una emergencia de un hospital o cualquier otro proceso de este tipo.
Como podemos ver los diagramas de flujo UML se utilizan en disciplinas como la programación, medicina, también en la economía, en la psicología cognitiva, en procesos industriales, y así en cualquier otro ámbito donde el trabajo conste de pasos y toma de decisiones, casi en todo.
Símbolos
Estos diagramas utilizan símbolos con significados definidos que representan los pasos del algoritmo, el flujo de ejecución mediante flechas que conectan los puntos de inicio y de fin del proceso, una toma de desiciones, etc.
Veamos los símbolos más frecuentes y sus descripciones:

Mediante estos símbolos recreamos el flujo de cierto proceso, ya sea de software o de cualquier aspecto de nuestra vida, por ejemplo hacer café:

El flujo se desarrolla de izquierda a derecha y de arriba hacia abajo, siendo opcional el uso de las flechas. Cuando el sentido es invertido (de derecha a izquierda o de abajo hacia arriba), el uso de las flechas es obligatorio a favor de la claridad del diagrama.
Otros Tipos de Diagrama UML
Los diagramas UML se organizan en dos clases: diagramas estructurales y diagramas de comportamiento. Estos diagramas se agrupan jerárquicamente como se muestra en el siguiente diagrama de clases:

Como ya he comentado en este artículo nos hemos enfocado en lo más importante para nosotros los programadores.
No obstante aquí os dejo enlaces (la mayoría en castellano) a los otros tipos de diagramas que igual por curiosidad les puede interesar:
Diagramas UML – Estructurales
- Diagrama de Clases (este artículo)
- Diagrama de componentes
- Diagrama de estructura compuesta
- Diagrama de despliegue
- Diagrama de objetos
- Diagrama de paquetes
- Diagrama de perfil
Diagramas UML – Comportamiento
- Diagrama de flujo (este artículo)
- Diagrama de comunicación
- Diagrama global de interacciones
- Diagrama de secuencia
- Diagrama de Máquina de Estados
- Diagrama de tiempos
- Diagrama de casos de uso
Conclusión
Como se puede intuir a lo largo de este artículo nuestro objetivo no es crear una guía exhaustiva sobre UML, y extendernos analizando varios casos-tipo que al final redundarían sobre lo mismo y no aportarían mucho más.
Lo más probable es que llegado el momento tu caso sea completamente distinto a cualquiera que se me pueda ocurrir.
El objetivo ha sido enfocarnos en lo más común, que podamos representar ante nuestros compañeros de equipo o nosotros mismos la relaciones entre diversas clases o protocolos, representar el fujo de cierto algoritmo que deseamos implementar, modelar una base de datos y sus diversas tablas y vistas.
Como una imagen (diagrama) vale más que mil palabras, con todo lo que hemos visto, creo que el objetivo ha sido logrado.
Falta aún mucho por aprender en nuestro camino a convertirnos en iOS Developer. Suscríbete a nuestra lista de correo mediante el formulario en el panel derecho y síguenos en nuestras redes sociales. Mantente así al tanto de todas nuestras publicaciones futuras.
Espero que todo cuanto se ha dicho aquí, de una forma u otra le haya servido de aprendizaje, de referencia y que haya valido su preciado tiempo.
Este artículo, al igual que el resto, será revisado con cierta frecuencia en pos de mantener un contenido de calidad y actualizado.
Cualquier sugerencia, ya sea errores, información o ejemplos a añadir, será más que bienvenida, necesaria!