Qué es el Patrón arquitectónico DTO y por qué es imprescindible que lo apliques
Un vochito en la imagen que bárbaro 🤩, qué tiene que ver dirás, es una analogía, averíguala aquí crack 😉

Así como para transmitir movimiento de un motor a otro elemento mecánico es necesario que entre ellos calze una faja a medida, de igual forma para transmitir información de una elemento del software a otro es necesario enviarle una clase a medida. Y es que hay tantos conceptos abstractos en nuestra profesión que hay que meterle unas ricas imágenes para entenderlos 😉

Es innegable que en las aplicaciones de hoy, hay un constante intercambio de información tanto desde el sistema o aplicación hacia afuera, como dentro de la misma aplicación en el intercambio de una capa a otra.

Es por ello que DTO o mejor dicho Data Transfer Object es un patrón de arquitectura, más que un patrón de diseño, ya que tiene efectos en la composición macro del proyecto añadiendo nuevas clases y carpetas o contenedores según lo definamos nosotros.

El concepto es sencillo y poderoso a la vez, DTO nos dice que debemos crear una serie de objetos con propiedades que haga de capa intermedia entre la entidad (clase que se mapea directamente hacia la base de datos) y el agente que lo consuma: el cual puede ser por ejemplo una vista o podría ser directamente un cliente si hablamos de un API.

Caso práctico

Para entenderlo mejor vamos a poner el siguiente caso:

Estás haciendo una web application en .Net core (o podría ser cualquier tecnología o stack)

Tengo el siguiente diagrama en la base de datos, pero concentrémonos en Libros y Autores

Las tablas Autores y Libros tienen una relación muchos-a-muchos por eso se tuvo que crear una clase intermedia llamada AutorLibro

En mi código, la entidad Libro tiene un aspecto similar a este:

    public class Libro
    {
        [Key]
        public int Id { get; set; }

        [Column(TypeName = "varchar(50)")]
        [Required]
        public string Titulo { get; set; }

        //propiedades de navegación
        public List<AutorLibro> AutoresLibros { get; set; }

    }

Lo que se muestra entre corchetes son llamadas anotaciones para añadir validaciones, investiga crack 😉

Hasta ahí todo bien, pero imaginemos que estamos desarrollando la funcionalidad de inserción de un nuevo Libro:

¿Qué entidad le pasaremos desde la vista hacia el controlador? Podríamos pensar que la entidad Libros, pero estaría mal por dos motivos principalmente:

  • Le pasaremos una clase con una propiedad que no tiene caso que le enviemos data: Id ya que al insertar un nuevo registro en la tabla Libro, no le pasamos el Id, este es autogenerado por la base de datos
  • Al crear un nuevo libro tenemos también que pasarle una lista de autores con 1 o más autores según corresponda pero la clase Libros no tiene eso, sino que está contenido en otra tabla

Y ni hablar de pasarle dos entidades Libro y Autor, eso estaría peor aún porque significa que si necesitamos hacer una inserción completa donde hay 4 tablas implicadas, le pasaremos como parámetros 4 entidades distintas? nah! 😐

Photo by Ciprian Boiciuc on Unsplash

Dándole solución

Al analizar estos problemas que nos estaríamos generando al querer usar las mismas clases de las entidades para insertar un registro, se muestra más claro por qué es necesario crear una clase intermedia que contenga sólo lo necesario para realizar la operación deseada y desde todas las tablas que haga falta. Hacer eso estimado amigo, es aplicar DTO!

Entre las ventajas de aplicar este estilo tenemos:

  • Tener un único modelo enviándose entre las capas de nuestros proyectos y no una serie de clases
  • Aumentar la seguridad en la comunicación entre capas al enviar sólo lo estrictamente necesario y evitar pasar información innecesaria.
  • Mejorar rendimiento al reducir el tamaño de los paquetes en los mensajes entre capas.

Para esto en nuestro proyecto podríamos crear una carpeta llamada DTO y dentro ir agregando las clases DTO por ejemplo en este caso crearía la clase LibroCreacionDTO con una apariencia como esta:

    public class LibroCreacionDTO
    {
        [Display(Name ="Titulo del libro")]
        [StringLength(maximumLength: 50)]
        public string Titulo { get; set; }

        public List<int> AutoresIds { get; set; }

    }

Si nos fijamos sólo contiene lo necesario y hace uso de propiedades de más de una tabla.

En tu proyecto web tendrías una estructura similar a esta:

De esta forma en la vista de creación de un nuevo libro lo que enviaremos de la vista al controlador no será una clase Libro, ni mucho menos dos clases, esa es una mala práctica, sino le enviaremos la clase LibroCreacionDTO.

Siguientes pasos...

Lo que resta es mapear en el controlador desde LibroCreacionDTO a las respectivas entidades y hacer la inserción hacia la base de datos.

En este mapeo lo podemos hacer manualmente, pero es más recomendable utilizar una herramienta llamada Automapper, pero ese será motivo del siguiente post en este tu blog del developer, no te pierdas la siguiente entrega.

Si este post te ha sido útil, considera compartirlo crack! 😉🚀

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *