Pokemon
Plataforma con información detallada de cada Pokémon, incluyendo estadísticas, habilidades, movimientos, evoluciones y características únicas
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:
- 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.
- 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.
- Procesamiento de Estado: Las respuestas de red mutan un estado global inmutable (NgRx Signals) en el cliente.
- 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):
PokemonResolverdefine el contrato GraphQL (esquema autogenerado) y gestiona los objetos de entrada (filtros, paginación). - Capa de Aplicación (Services):
PokemonServiceorquesta los casos de uso, como la recuperación individual y la búsqueda difusa de entidades. - Capa de Infraestructura (Repositories):
InMemoryPokemonRepositoryimplementa 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,PokemonStatsyPokemonMovedefinen 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:
PokemonStorecentraliza 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ía | Categoría | Rol Técnico en la Arquitectura |
|---|---|---|
| Angular 19 | Frontend Framework | Motor de renderización reactiva; ciclo de vida de componentes y enrutamiento sincronizado con el estado. |
| NgRx Signals | State Management | Gestor de estado global mutando señales atómicas reactivas; reduce la complejidad del ciclo de digestión estándar. |
| Apollo Client | Data Fetching | Cliente GraphQL con estrategia de políticas de caché optimizada (ej. cache-and-network). |
| Tailwind CSS v4 | UI Styling | Motor CSS utilitario bajo arquitectura PostCSS, estructurando la capa de Glassmorphism sin librerías de componentes rígidas. |
| NestJS | Backend Framework | Estructuración modular mediante Inversión de Control (IoC), soportando patrones de diseño empresariales. |
| GraphQL | API Layer | Interfaz de consultas tipadas fuertemente, mitigando over-fetching de datos de modelos complejos. |
| Biome | Toolchain | Herramienta 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.