Não passe DTO's para componentes de UI
É comum que desenvolvedores frontend trabalhem com dados vindos de APIs ou serviços backend. Esses dados são nomeados como DTO's, e frequentemente eles são utilizados para renderizar informações na camada de UI (User Interface), mais especificamente nos componentes de uma aplicação frontend.
O que é DTO?
DTO significa Data Transfer Object. É um padrão de design usado no desenvolvimento de software para transferir dados entre subsistemas de uma aplicação. Em APIs RESTful, os DTOs são frequentemente usados para definir a estrutura dos dados que serão enviados e recebidos. Eles ajudam na comunicação entre o frontend e o backend.
O problema
Usar DTOs diretamente em componentes de UI pode levar a problemas em torno de manutenibilidade, reutilização e separação de conceitos. Isso pode ser considerado como um antipadrão.
Passar DTOs diretamente para componentes de UI (seja via props, parâmetros ou injeção de dependência) acaba por trazer um alto acoplamento dos componentes com as camadas do backend.
Isso pode dificultar a evolução ou refatoração de interfaces de componentes quando os contratos dos dados de backend mudam. Isso também infringe o Single responsibility principle e o Principle of least privilege.
Uma solução
Aqui vem a importância de definir bem a arquitetura do software e pensar na divisão de camadas. Podemos definir uma camada de Data Access responsável por traduzir esses objetos DTO's em modelos mais simples, e voltados à necessidade dos componentes de UI, comumente nomeados de View Models.
A camada de Data Access manipula os dados vindos de serviços externos, impedindo que eles vazem e poluam a camada de UI. Os componentes só precisam saber sobre os objetos adaptados para suas responsabilidades particulares, e não sobre as peculiaridades de como os dados são transportados pelas outras camadas.
Exemplo de código
Imagine que você tenha um DTO de backend para uma postagem de blog neste formato:
{
id: "anyId",
authorId: "anyAuthorId",
title: "Título do meu Post",
content: "Este é o conteúdo do meu post",
metadata: {
createdAt: "2024-01-01T06:32:00Z",
updatedAt: "2024-01-01T09:21:00Z",
tags: ["angular", "typescript"]
}
}
A camada Data Access pode mapear esse DTO para um Post
simplificado projetado apenas para renderização nos componentes:
{
id: "anyId",
author: "Andrew Rosário",
title: "Título do meu Post",
content: "Este é o conteúdo do meu post",
formattedDate: "01 de Janeiro de 2024",
tags: ["angular", "typescript"]
}
Observe como o objeto adaptado remove propriedades que não são úteis para a UI, como a authorId
. Ele também mapeia e deriva novos campos como o nome do autor e formattedDate
que são abstrações mais úteis para os propósitos de componente.
Construção dos componentes
À medida que nos aprofundamos em nossa hierarquia de componentes, podemos introduzir abstrações mais granulares com interfaces mais enxutas, focadas apenas nos dados necessários para suas responsabilidades.
Por exemplo, um componente que está acima no nível de hierarquia chamado PostComponent
pode precisar de toda a View Model. E ele é responsável por distribuir apenas as propriedades necessárias de objeto Post para os componentes filhos:
Conclusão
Ao preservar os limites de abstração e modelar interfaces de componentes deliberadamente, podemos construir uma arquitetura de UI que seja mais modular e sustentável. A camada de Data Access isola componentes de mudanças em modelos de dados de backend, enquanto props e parâmetros simplificados facilitam uma melhor reutilização e composição de elementos de UI.