viernes, 19 de junio de 2015

Los Microservicios requieren macrodiseño.

Respondiendo una pregunta en StackOverflow sobre el tema; me he dado cuenta que la cosa daría para una pequeña entrada.

Microservicios es la palabreja de moda. Antes de que la mayoría de empresas medianas en vías de desarrollo hayan podido siquiera empezar a implantar decentemente SOA y ESB's en sus procesos de negocio informatizados ya salta algún geek que te dice que eso esta out; que el camino a seguir son los microservicios.

Afortunadamente, en este caso, estoy de acuerdo. Siguiendo una filosofía muy cercana con SOA con respecto a la distribución de la arquitectura; los microservicios enfatizan en eliminar la necesidad de coordinación y orquestación que se implementaba utilizando un ESB en SOA.

Para eliminar esa coordinación y orquestación se deben diseñar microservicios que no necesiten de transacciones distribuidas para ser completados ni requieran de otros microservicios.

Voy a intentar poner un ejemplo muy básico.

 Un arquitecto de software esta diseñando microservicios y ha terminado en esta situación:

  • 3 Microservicios
    • Usuarios
    • Almacenes
    • Productos

Los 2 primeros son sencillos y casi completamente CRUD; pero al llegar al tercero se encuentra con que debe cumplir restricciones de dominio que implicarían, en un principio utilizar otro microservicio. Resulta que sólo ciertos usuarios tienen permiso para añadir productos a ciertos almacenes. Por lo que a la hora de agregar un producto habría que utilizar el microservicio de Almacenes para autorizar la acción.

El problema es que el arquitecto ha modelado los microservicios emparejndolos 1 a 1 con un diseño de clases y sus métodos sin tener en cuenta el dominio ni el contexto. Esto no son microservicios, son objetos distribuidos que dan los dolores de cabeza que daba CORBA o JEE en los viejos tiempos.

El Microservicio Productos no debe exponer simplemente métodos de la clase Productos, debe ser un contexto que expone los casos de uso referentes a los productos e internamente debe utilizar los agregados raices necesarios para cumplir las reglas de dominio sin tener que depender de otro microservicio.

Pongo una implementación en pseudocódigo para que os hagáis una idea:

Class ProductosMicroservicio

{

     public void EntradaDeProducto(idProducto, cantidad, idUsuario, idAlmacenDestino)

    {

         AlmacenAggregate almacenDestino = persistencia.getAlmacenAggregateById(idAlmacenDestino);



         almacenDestino.AgregarProducto(idProducto, cantidad, idUsuario);



         persistencia.SaveChanges(almacenDestino);



        Events.Raise(new EntradaProductoAceptada(idProducto, cantidad, idUsuario, idAlmacenDestino));



    }

}



Class AlmacenAggregate

{

    private list<int> allowedUsersId;

    private uniqueTupleList<idProducto, cantidad> productosAlmacenados;



    public void AregarProducto(idProducto, cantidad, idUsuario)

    {

        if (idUsuario not IN allowedUsersId) throw UserNotAllowedError;

        productosAlmacenados.AddTuple(idProducto, cantidad);//agrega nueva tupla o suma la cantidad a una tupla existente en caso de que idProducto ya exista

        return;

    }

}



Como se puede observar, aunque el microservicio es relativo a los productos, se está utilizando un agregado raíz de Almacen puesto que es el almacén y sus reglas de dominio el que puede rechazar la operación.

Por supuesto, los nombres de los microservicios, según esta forma de diseñar, están mal. Los nombres deben tener relación con el contexto del dominio y no con entidades concretas como si fuesen objetos distribuidos.

No hay comentarios:

Publicar un comentario