Saltar al contenido →

Patrón Mediator con Swift

Bienvenidos a los que espero que se convierta en una serie de artículos en los que pretendo mostrar los patrones de diseño de software más importantes aplicados al lenguaje de programación Swift.

Recordemos que un patrón de diseño de software es…

Los patrones de diseño son unas técnicas para resolver problemas comunes en el desarrollo de software y otros ámbitos referentes al diseño de interacción o interfaces.

La importancía de los patrones de diseño radica en la finalidad que persigue

  • Construir elementos de software reusables
  • Evitar la pérdida de tiempo buscando soluciones a un mismo tipo de problema
  • Crear una forma común de resolver un problema, y que sea ampliamente conocida
  • Crear un estándar de construcción de software.

Mediator. ¿Para qué sirve?

Simplifica la comunicación entre objetos introduciendo un mediador entre ellos que realiza las labores de broker de comunicación entre todos los objetos.

¿Qué problema resuelve?

La comunicación entre los diferentes objetos, asegurándonos que todos los objetos reciben los mensajes enviados por los otros.

¿De qué elementos se compone?

La implementación básica consta de…

  • Un mediador (una clase) que se encarga de la comunicación entre los diferentes objetos.
  • Un protocolo que define las operaciones del mediador
  • Un cliente (una clase)
  • Un protocolo que define los mensajes que va recibir cada cliente

Manos a la obra

El cuartel general de la alianza rebelde nos acaba de informar de que una gran flota imperial se dirige a Hoth con la intención de eliminar a las fuerzas de ataque que allí tenemos destacadas.

Para preparar la evacuación de la manera más rápida posible nos han encargado el desarrollo de un software para coordinar a todos nuestros androides en las tareas de carga de material en las naves de transporte.

Día 1

Nos han dejado dos prototipos de androides, y la primera versión de nuestros software funciona muy bien. En nuestra clase Androide hemos añadido una referencia al otro androide para que se puedan comunicar. El proyecto ha quedado así.

Día 3

Tenemos un problema. El mando nos ha dicho que nuestro software tiene que ser capaz de controlar 100 androides. No vamos a crear 99 propiedades en clase Androide para que se comuniquen entre ellos, y aunque alguien ha dicho que las metamos en un Array el problema persiste, y es que hay una cantidad ingente de referencias.

Tenemos algún problema aleatorio porque a veces se nos olvida añadir alguna referencia entre androides y no son capaces de comunicarse y se acaban chocanado.

A ver qué se nos ocurre…Por cierto, el proyecto ahora se parece a esto.

Día 5

Esto va de mal en peor. Esta tarde ha llegado uno del Departamente de Logística y nos ha dicho que podremos contar con entre 20 o 30 androides más, cuando le hemos preguntado que si eran 20 o 30 pero no ha sabido decirnos el número exacto, pero que el día de la evacuación lo sabremos exacto, o no, que no lo sabe.

Hemos quemado el diagrama de clases.

Día 7

Hemos pensado en pasarnos en masa al grupo de TI de las Fuerzas Imperiales, pero alguien ha dicho que hizo una prueba de selección y que le pidieron hacer un EJB en un servidor de aplicaciones Java.

También le dijeron que había bebidas gratis y una mesa de ping-pong.

Nos quedamos.

Día 9

Ya tenemos resulto el problema. ¡Patrón Mediator al rescate! A ver, el problema es comunicar a más de 100 androides para que puedan moverse por la base sin que choquen entre ellos. Pues de controlar los movimientos se va encargar un mediador.

Cada androide sabe que posición tiene en un momento dado y a que posición se va a mover después para llegar a su destino. Pues cuando un androide quiera moverse a otra cuadrícula de la base le preguntará al mediador si ese movimiento es posible.

El mediador, que tiene una referencia a cada androide, les preguntará si están ocupando la posición a la que el otro androide quiere ir, si todos los androides informan que están en otros lugares damos vía libre el androide para que se mueva.

El mediador también tiene un mecanismo para registrar nuevos androides, de esa forma los vamos añadiendo de manera dinámica según vayan llegando a la base.

Al final la solución es algo como esto.

El código en detalle

Lo primero que tenemos que definir son los protocolos que definirán las operaciones entre el mediador y los clientes. En este caso el cliente implementará el protocolo Moveable que tiene la función element(_ element: Element, willMoveToPosition position: Position) -> Bool que es donde el mediador pregunta si está ocupando una posición que se pasa como parámetro.

Si el androide está en esa posición devuelve un false, indicando así que ese movimiento no se puede realizar.

Por su parte el mediador tiene las funciones register y unregister para añadir y quitar androides y la función checkMovement(to position: Position, from element: Element) -> Bool que es donde un androide pregunta antes de moverse, para saber si otro androide está en ese lugar.

Ahora nos toca implementar estos protocolos en las clases Robot y Manager. Vamos a empezar por los robots.

Lo primero que podeís ver es que incluimos una variables llamada manager que es del tipo Manager y que, efectivamente, es una referencia a la clase mediadora. El protocolo Movable está implementado en una extension.

Por cierto, toda la lógica del movimiento de los robots está en la función func changePosition(to movement: Position.Movement)

Vamos ahora con el mediador, que se encuentra en la clase Manager

Al igual que la clase Robot, hemos puesto la implementación del protocolo Controlling en una extensión de la clase. También hemos añadido el método que ayuda a la hora de crear los robots que pondremos bajo el control del mediador.

Por cierto, la lógica que comprueba si una posición solicitada por un robot está libre la podéis encontrar en la función checkMovement(to position: Position, from element: Robot) -> Bool

Resumen

Podríamos decir que el proceso normal de trabajo con el patrón Mediator sería…

  1. Registramos los objetos en el mediador.
  2. Un robot necesita moverse, así que usando la referencia al mediador le pregunta si puede moverse a una posición concreta.
  3. El mediador recibe la petición del robot y se encarga de preguntar al resto de robots si esa posición está libre.
  4. Una vez realizada la comprobación le dice al robot si la solicitud de movimiento está aceptada o no.

Podéis descargar todo el código que acompaña al artículo en este repositorio de GitHub

Epílogo

Día 11

Todos los test OK.

Día 12

Cuando íbamos a desplegar el software en los robots de producción de Hoth nos ha fallado la conexión. Le hemos preguntado a Paquito, del departamento de TI Comunicaciones, y nos ha dicho que ayer por la tarde le metieron fuego a la base un grupo de asalto imperial armados hasta los dientes, que para qué nos queríamos conectar.

Le hemos dicho que para probar si la Wi-Fi nos funcionaba, que nos iba a tirones.

También nos ha contado que los oficiales al mando de la base están que fuman en pipa, por lo visto, los robots que tenía que cargar el material no hicieron nada de nada, y que hasta el general al mando tuvo que cargar cajas como un animal, y que cuando se entarara de quiénes eran los que tenían que programar los robots les iba a dar dos medallas a cada uno. Uno por tontos y otra por si las perdían.

Hemos borrado el proyecto.

¿Robots? ¿Qué robots?

Publicado en Patrones de Software Swift