Arquitectura Hexagonal: Lo esencial

14 May 2024 5 min (0) Comentarios

Dentro de C# utilizamos una gran cantidad de arquitecturas, diseños y patrones, una de las arquitecturas más populares es la arquitectura hexagonal, a la que también llamaremos puertos y adaptadores (ports and adapters) debido a su estructura.

 

 

1 - Qué es la arquitectura hexagonal?

Llamamos arquitectura hexagonal porque lo que tenemos es un núcleo central, donde tenemos la lógica de negocio, y luego alrededor del mismo tenemos otra capa que son los puertos y adaptadores que nos permiten interactuar con servicios externos, ya bien sean servicios de otras empresas, la base de datos, el sistema de ficheros o la propia interfaz.

 

Un apartado clave de la arquitectura hexagonal es que el núcleo, core (o llamalo como quieras), la lógica de negocio no sabe nada de cómo se procesan los datos o como se reciben los datos, pero todas las reglas y procesos están en un solo lugar. Lo que facilita el testeo y la simplicidad a la hora de desarrollar. 

 

Ahora llega el momento de explicar los puertos y los adaptadores.

Podemos entender los puertos como interfaces, las cuales inyectamos en nuestra lógica de negocio, estas interfaces contienen el contrato que la lógica va a utilizar.

 

Por lo que un adaptador no es más que la abstracción no implementación de dicho puerto, siendo la implementación completamente transparente e irrelevante al caso de uso.

arquitectura hexagonal

En mi opinión, usar los términos “puertos y adaptadores” es complicar las cosas cuando la realidad es que es interfaz e implementación. Pero bueno, cosas menores. 

 

 

2 - Características de la arquitectura hexagonal

Como todo en programación tenemos beneficios e inconvenientes. 

 

Desde mi punto de vista hay dos inconvenientes; 

El primero es obvio, para implementar Hexagonal como es debido tienes que crear los puertos y los adaptadores, lo que lleva a tener mucho código, otro punto importante es que tienes que hacer separación entre Entidades y Dto de una forma muy clara.

 

Por ejemplo, yo he visto lo siguiente: Leemos un usuario de la BBDD con Entity Framework y ese usuario lo convertimos en un DTO, ese DTO lo modificamos, cambiamos un valor y lo volvemos a guardar, pero claro, estás mandando a tu abstracción (adapter) de la base de datos un DTO y no la entidad de Entity framework por lo que tienes que volver a leer la entidad para poder guardarla.

 

Además, esta empresa en particular devolvía el usuario actualizado al usuario como respuesta, lo que implica otra conversión (aunque se puede devolver una interfaz IUser).

complejidad en arquitectura hexagonal

Como ejemplo creo que ilustra muy bien a lo que me refiero, aquí hay claramente pasos “de más”, cuando este proceso en particular se puede hacer con 4 líneas de código. 

 

El otro punto negativo, aunque depende más de la empresa en la que estés es que toda la lógica de negocio está ubicada en un solo fichero, crean un fichero llamado UsuarioRepository, y ahí está toda la lógica que tiene que ver con el usuario, el problema es que está en un solo fichero todas las acciones, por ejemplo, leer un usuario, actualizarlo, borrarlo, validarlo, etc, todo en el mismo fichero.

Nota: en este caso UsuarioRepository es la lógica del usuario, no el acceso a datos... Si, tema naming da para otro post. 

 

Y eso es si está partido, que muchas veces la app entera tiene un solo fichero, sería AppRepository y todo lo que tiene que ver con usuarios ahí, si tu app va sobre libros, todo lo que tiene que ver con libros en ese mismo fichero, y al final acabas con un fichero de tres mil líneas que se puede partir muy rápido y de una forma simple pero nadie quiere hacerlo por si algo se rompe. 

 

Si en vez de tenerlo todo en un único fichero, separamos los casos de uso, mejoraremos la aplicación de forma drástica, porque ya estamos separando la responsabilidad  con los puertos y los adaptadores, así que por qué no separar los casos de uso también. Llegado el momento cuando otro desarrollador quiera hacer un cambio o implementar algo nuevo  solo tiene que preocuparse por lo que está haciendo. 

 

Si juntamos todo lo anterior, nos damos cuenta que hacer tests es muy sencillo, o bueno de primeras parece sencillo ya que todas las dependencias están detrás de interfaces, lo que implica que podemos hacer un doble sin problemas. 

Testear hexagonal es muy simple siempre y cuando tengamos los casos de uso separados, ya que solo inyectamos los puertos (interfaces) que usamos en ese caso de uso, pero si tenemos un God Object estaremos inyectando muchos puertos que no necesitamos para cada uno de los casos de uso.

 

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café