Volver a proyectos
Pokemon logo

Pokemon

Plataforma con información detallada de cada Pokémon, incluyendo estadísticas, habilidades, movimientos, evoluciones y características únicas

Angular NestJS GraphQL

A continuación, expongo el análisis técnico y arquitectónico de este proyecto Pokedex, diseñado para servir simultáneamente como documentación oficial del repositorio y como estudio de caso. Mi enfoque central se orienta en describir de forma analítica y objetiva el diseño del sistema, las decisiones arquitectónicas y los flujos de datos.

1. Utilidad y Funcionamiento General

La aplicación está diseñada para resolver el problema de indexación, búsqueda y visualización de datos complejos de entidades “Pokémon”. Su utilidad principal radica en consolidar información dispersa (estadísticas, líneas evolutivas, movimientos, descripciones físicas) en una interfaz de usuario cohesiva y de alta fidelidad visual.

El flujo de trabajo operativo principal ocurre de la siguiente manera:

  1. Inicialización: Al montar la aplicación web, el cliente solicita un estado base sincronizado con la URL actual. Si no hay parámetros definidos, el estado se auto-sincroniza con el identificador inicial (ID 1) y demanda el primer segmento paginado del directorio general.
  2. Resolución de Datos: Las consultas son enviadas mediante operaciones GraphQL hacia el servidor backend. Este servicio actúa como intermediario frente a una base de datos en memoria pre-sembrada con información consolidada, garantizando latencias mínimas.
  3. Procesamiento de Estado: Las respuestas de red mutan un estado global inmutable (NgRx Signals) en el cliente.
  4. Actualización Reactiva: Los componentes de presentación, que son agnósticos a la lógica de red, reciben los nuevos datos (propiedades del Pokémon seleccionado y cuadrícula de paginación) y actualizan el DOM consecuentemente, reflejando elementos gráficos como modelos y estadísticas base.

2. Arquitectura General y Flujos de Datos

He diseñado el sistema utilizando un enfoque que combina principios de Clean Architecture y Domain-Driven Design (DDD) en el backend, junto con un patrón de Contenedor/Presentador (Smart/Dumb Components) en el frontend. La separación de responsabilidades asegura alta mantenibilidad y escalabilidad.

Topología del Sistema

El siguiente diagrama ilustra la interacción entre los distintos dominios del sistema:

graph TD
    subgraph Frontend [Cliente - Angular 19]
        UI_Layout[Layout/Smart Components]
        UI_Dumb[Presentational Components]
        Store[NgRx Signal Store]
        Service[GraphQL Service / Apollo]

        UI_Layout -->|Despacha Acciones| Store
        Store -->|Provee Estado Reactivo| UI_Layout
        UI_Layout -->|Inyecta Datos| UI_Dumb
        Store -->|Invoca Métodos| Service
    end

    subgraph Backend [Servidor - NestJS]
        Resolver[GraphQL Resolver]
        AppService[Application Service]
        Repository[In-Memory Repository]
        Entities[Domain Entities]

        Service -->|GraphQL Queries| Resolver
        Resolver -->|Inyección de Dependencias| AppService
        AppService -->|Llamadas de Dominio| Repository
        Repository -.->|Mapeo| Entities
    end

    subgraph Data [Capa de Persistencia Inicial]
        Seed[Seed Data JSON]
        PokeAPI[External PokeAPI]
        Repository -.->|Hidratación Inicial| Seed
        Seed -.->|Caché Previo| PokeAPI
    end

Arquitectura del Backend

El servidor NestJS implementa una abstracción de capas (Domain-Driven Design):

  • Capa de Presentación (Resolvers): PokemonResolver define el contrato GraphQL (esquema autogenerado) y gestiona los objetos de entrada (filtros, paginación).
  • Capa de Aplicación (Services): PokemonService orquesta los casos de uso, como la recuperación individual y la búsqueda difusa de entidades.
  • Capa de Infraestructura (Repositories): InMemoryPokemonRepository implementa los mecanismos de persistencia reales. En esta topología, se utiliza almacenamiento en memoria basado en un set de datos de siembra generado previamente.
  • Capa de Dominio (Entities): Las clases como Pokemon, PokemonStats y PokemonMove definen el núcleo del negocio.

Arquitectura del Frontend

El cliente Angular 19 utiliza el modelo de Signals de NgRx para un manejo de estado altamente predecible y performante:

  • PokemonStore centraliza el estado global. Utiliza flujos reactivos (RxJS) internamente para la desfragmentación de eventos asíncronos (como el debounce de las búsquedas) antes de parchear el estado basado en Signals.
  • Los componentes se dividen estrictamente entre los encargados del layout/estado y los encargados de la renderización pura (Glassmorphism UI).

3. Modelado de Datos y Lógica de Negocio

La entidad principal, Pokemon, encapsula la complejidad de los datos asociados.

classDiagram
    class Pokemon {
        +String id
        +Number number
        +String name
        +String[] types
        +String description
        +PokemonPhysic physic
        +PokemonStats stats
        +PokemonEvolution evolution
        +PokemonMove[] moves
    }
    class PokemonStats {
        +Number health
        +Number attack
        +Number defense
        +Number resistance
        +Number speed
    }
    class PokemonMove {
        +String name
        +String type
        +Number damage
    }
    class PokemonPhysic {
        +Number weight
        +Number height
    }
    class PokemonEvolution {
        +String[] pre
        +String[] pos
    }

    Pokemon *-- PokemonStats
    Pokemon *-- PokemonMove
    Pokemon *-- PokemonPhysic
    Pokemon *-- PokemonEvolution

La lógica de búsqueda en el repositorio se resuelve aplicando operaciones de filtrado encadenadas a nivel del servidor, evaluando primero si el query de entrada intercepta el nombre o el índice numérico, y posteriormente reduciendo los resultados según un filtro de tipos opcional, antes de resolver el sub-arreglo correspondiente a la paginación de la vista actual.

4. Stack Tecnológico

La pila de tecnologías se ha seleccionado basándose en el tipado fuerte y en arquitecturas orientadas a eventos y flujos de datos.

TecnologíaCategoríaRol Técnico en la Arquitectura
Angular 19Frontend FrameworkMotor de renderización reactiva; ciclo de vida de componentes y enrutamiento sincronizado con el estado.
NgRx SignalsState ManagementGestor de estado global mutando señales atómicas reactivas; reduce la complejidad del ciclo de digestión estándar.
Apollo ClientData FetchingCliente GraphQL con estrategia de políticas de caché optimizada (ej. cache-and-network).
Tailwind CSS v4UI StylingMotor CSS utilitario bajo arquitectura PostCSS, estructurando la capa de Glassmorphism sin librerías de componentes rígidas.
NestJSBackend FrameworkEstructuración modular mediante Inversión de Control (IoC), soportando patrones de diseño empresariales.
GraphQLAPI LayerInterfaz de consultas tipadas fuertemente, mitigando over-fetching de datos de modelos complejos.
BiomeToolchainHerramienta unificada para formato de código y linting, garantizando consistencia sintáctica transversal.

5. Cierre Arquitectónico

La consolidación del patrón de Contenedor/Presentador en el frontend junto con una arquitectura GraphQL-to-DDD en el backend elimina la ambigüedad en los contratos de datos y aísla efectivamente las mutaciones de estado de los efectos secundarios en la UI. La incorporación de abstracciones asíncronas para el mapeo en memoria permite que el sistema responda con alta disponibilidad precalculada, simplificando la orquestación del servidor y focalizando el procesamiento en la manipulación reactiva de Signals a nivel del cliente.